summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-layerscape
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-layerscape')
-rw-r--r--arch/arm/mach-layerscape/Kconfig34
-rw-r--r--arch/arm/mach-layerscape/Makefile16
-rw-r--r--arch/arm/mach-layerscape/boot.c60
-rw-r--r--arch/arm/mach-layerscape/errata.c144
-rw-r--r--arch/arm/mach-layerscape/icid.c381
-rw-r--r--arch/arm/mach-layerscape/include/mach/bbu.h22
-rw-r--r--arch/arm/mach-layerscape/include/mach/debug_ll.h34
-rw-r--r--arch/arm/mach-layerscape/include/mach/errata.h7
-rw-r--r--arch/arm/mach-layerscape/include/mach/layerscape.h19
-rw-r--r--arch/arm/mach-layerscape/include/mach/lowlevel.h7
-rw-r--r--arch/arm/mach-layerscape/include/mach/xload.h10
-rw-r--r--arch/arm/mach-layerscape/lowlevel-ls1028a.c42
-rw-r--r--arch/arm/mach-layerscape/lowlevel-ls102xa.c400
-rw-r--r--arch/arm/mach-layerscape/lowlevel-ls1046a.c16
-rw-r--r--arch/arm/mach-layerscape/lowlevel.S2
-rw-r--r--arch/arm/mach-layerscape/ls102xa_stream_id.c50
-rw-r--r--arch/arm/mach-layerscape/pblimage.c8
-rw-r--r--arch/arm/mach-layerscape/ppa-entry.S2
-rw-r--r--arch/arm/mach-layerscape/ppa.c33
-rw-r--r--arch/arm/mach-layerscape/restart.c25
-rw-r--r--arch/arm/mach-layerscape/soc.c189
-rw-r--r--arch/arm/mach-layerscape/tzc400.c303
-rw-r--r--arch/arm/mach-layerscape/tzc400.h164
-rw-r--r--arch/arm/mach-layerscape/xload-qspi.c47
-rw-r--r--arch/arm/mach-layerscape/xload.c24
25 files changed, 1787 insertions, 252 deletions
diff --git a/arch/arm/mach-layerscape/Kconfig b/arch/arm/mach-layerscape/Kconfig
index c15d5873a5..5658a63b33 100644
--- a/arch/arm/mach-layerscape/Kconfig
+++ b/arch/arm/mach-layerscape/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
if ARCH_LAYERSCAPE
config ARCH_LAYERSCAPE_PPA
@@ -5,7 +7,6 @@ config ARCH_LAYERSCAPE_PPA
select ARM_PSCI_OF
select ARM_SMCCC
select FITIMAGE
- bool
help
The "Primary Protected Application" (PPA) is a PSCI compliant firmware
distributed by NXP. It is needed to start the secondary cores on
@@ -13,10 +14,23 @@ config ARCH_LAYERSCAPE_PPA
work properly. The precompiled firmware images can be found here:
https://github.com/NXP/qoriq-ppa-binary
-config ARCH_LS1046
+config ARCH_LS1028
+ bool
select CPU_V8
select SYS_SUPPORTS_64BIT_KERNEL
+ select ARM_ATF
+ select FIRMWARE_LS1028A_ATF
+
+config ARCH_LS1046
bool
+ select CPU_V8
+ select SYS_SUPPORTS_64BIT_KERNEL
+
+if 64BIT
+
+config MACH_LS1028ARDB
+ bool "QorIQ LS1028A Reference Design Board"
+ select ARCH_LS1028
config MACH_LS1046ARDB
bool "QorIQ LS1046A Reference Design Board"
@@ -35,3 +49,19 @@ config MACH_TQMLS1046A
select DDR_FSL_DDR4
endif
+
+config ARCH_LS1021
+ select CPU_V7
+ bool
+
+if 32BIT
+
+config MACH_LS1021AIOT
+ bool "LS1021AIOT Board"
+ select ARCH_LS1021
+ select DDR_FSL
+ select DDR_FSL_DDR3
+
+endif
+
+endif
diff --git a/arch/arm/mach-layerscape/Makefile b/arch/arm/mach-layerscape/Makefile
index 854a327c91..e4bb1b42f2 100644
--- a/arch/arm/mach-layerscape/Makefile
+++ b/arch/arm/mach-layerscape/Makefile
@@ -1,8 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
obj- := __dummy__.o
-lwl-y += lowlevel.o errata.o
-lwl-$(CONFIG_ARCH_LS1046) += lowlevel-ls1046a.o
-obj-y += icid.o
-obj-pbl-y += boot.o
+lwl-y += errata.o
+lwl-$(CONFIG_ARCH_LS1046) += lowlevel.o lowlevel-ls1046a.o
+obj-$(CONFIG_ARCH_LS1046) += icid.o
+obj-pbl-y += boot.o soc.o
pbl-y += xload-qspi.o xload.o
+pbl-$(CONFIG_ARCH_LS1028) += tzc400.o
obj-$(CONFIG_ARCH_LAYERSCAPE_PPA) += ppa.o ppa-entry.o
obj-$(CONFIG_BOOTM) += pblimage.o
+
+lwl-$(CONFIG_ARCH_LS1021) += lowlevel-ls102xa.o
+obj-$(CONFIG_ARCH_LS1021) += restart.o ls102xa_stream_id.o
+
+lwl-$(CONFIG_ARCH_LS1028) += lowlevel-ls1028a.o
diff --git a/arch/arm/mach-layerscape/boot.c b/arch/arm/mach-layerscape/boot.c
index c804977d22..4d074205cc 100644
--- a/arch/arm/mach-layerscape/boot.c
+++ b/arch/arm/mach-layerscape/boot.c
@@ -3,10 +3,12 @@
#include <common.h>
#include <init.h>
#include <bootsource.h>
-#include <mach/layerscape.h>
+#include <linux/bitfield.h>
+#include <mach/layerscape/layerscape.h>
#include <soc/fsl/immap_lsch2.h>
+#include <soc/fsl/immap_lsch3.h>
-enum bootsource ls1046_bootsource_get(void)
+enum bootsource ls1046a_bootsource_get(void)
{
void __iomem *dcfg = IOMEM(LSCH2_DCFG_ADDR);
uint32_t rcw_src;
@@ -27,13 +29,55 @@ enum bootsource ls1046_bootsource_get(void)
return BOOTSOURCE_UNKNOWN;
}
-static int ls1046a_bootsource_init(void)
+enum bootsource ls1021a_bootsource_get(void)
{
- if (!of_machine_is_compatible("fsl,ls1046a"))
- return 0;
+ return ls1046a_bootsource_get();
+}
+
+void ls1021a_bootsource_init(void)
+{
+ bootsource_set_raw(ls1021a_bootsource_get(), BOOTSOURCE_INSTANCE_UNKNOWN);
+}
+
+void ls1046a_bootsource_init(void)
+{
+ bootsource_set_raw(ls1046a_bootsource_get(), BOOTSOURCE_INSTANCE_UNKNOWN);
+}
+
+#define PORSR1_RCW_SRC GENMASK(26, 23)
+
+static enum bootsource ls1028a_bootsource_get(int *instance)
+{
+ void __iomem *porsr1 = IOMEM(LSCH3_DCFG_BASE);
+ uint32_t rcw_src;
- bootsource_set(ls1046_bootsource_get());
+ rcw_src = FIELD_GET(PORSR1_RCW_SRC, readl(porsr1));
+
+ printf("%s: 0x%08x\n", __func__, rcw_src);
+
+ switch (rcw_src) {
+ case 8:
+ *instance = 0;
+ return BOOTSOURCE_MMC;
+ case 9:
+ *instance = 1;
+ return BOOTSOURCE_MMC;
+ case 0xa:
+ return BOOTSOURCE_I2C;
+ case 0xd:
+ case 0xc:
+ return BOOTSOURCE_NAND;
+ case 0xf:
+ return BOOTSOURCE_SPI_NOR;
+ }
+
+ return BOOTSOURCE_UNKNOWN;
+}
+
+void ls1028a_bootsource_init(void)
+{
+ int instance = BOOTSOURCE_INSTANCE_UNKNOWN;
+ enum bootsource source = ls1028a_bootsource_get(&instance);
- return 0;
+ bootsource_set_raw(source, instance);
}
-coredevice_initcall(ls1046a_bootsource_init); \ No newline at end of file
diff --git a/arch/arm/mach-layerscape/errata.c b/arch/arm/mach-layerscape/errata.c
index 4f4b759ddb..deab584243 100644
--- a/arch/arm/mach-layerscape/errata.c
+++ b/arch/arm/mach-layerscape/errata.c
@@ -2,13 +2,12 @@
#include <common.h>
#include <io.h>
#include <soc/fsl/immap_lsch2.h>
+#include <soc/fsl/immap_lsch3.h>
#include <soc/fsl/fsl_ddr_sdram.h>
#include <asm/system.h>
-#include <mach/errata.h>
-#include <mach/lowlevel.h>
-
-#define scfg_clrsetbits32(addr, clear, set) clrsetbits_be32(addr, clear, set)
-#define scfg_clrbits32(addr, clear) clrbits_be32(addr, clear)
+#include <mach/layerscape/errata.h>
+#include <mach/layerscape/lowlevel.h>
+#include <soc/fsl/scfg.h>
static inline void set_usb_pcstxswingfull(u32 __iomem *scfg, u32 offset)
{
@@ -17,6 +16,22 @@ static inline void set_usb_pcstxswingfull(u32 __iomem *scfg, u32 offset)
SCFG_USB_PCSTXSWINGFULL << 9);
}
+static void erratum_a008997_ls1021a(void)
+{
+ u32 __iomem *scfg = (u32 __iomem *)LSCH2_SCFG_ADDR;
+
+ set_usb_pcstxswingfull(scfg, SCFG_USB3PRM2CR_USB1);
+}
+
+static void erratum_a008997_ls1028a(void)
+{
+ void __iomem *dcsr = IOMEM(LSCH3_DCSR_BASE);
+
+ clrsetbits_le32(dcsr + LSCH3_DCSR_USB_IOCR1,
+ 0x7f << 11,
+ LSCH3_DCSR_USB_PCSTXSWINGFULL << 11);
+}
+
static void erratum_a008997_ls1046a(void)
{
u32 __iomem *scfg = (u32 __iomem *)LSCH2_SCFG_ADDR;
@@ -26,22 +41,24 @@ static void erratum_a008997_ls1046a(void)
set_usb_pcstxswingfull(scfg, SCFG_USB3PRM2CR_USB3);
}
-#define PROGRAM_USB_PHY_RX_OVRD_IN_HI(phy) \
- out_be16((phy) + SCFG_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_1); \
- out_be16((phy) + SCFG_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_2); \
- out_be16((phy) + SCFG_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_3); \
- out_be16((phy) + SCFG_USB_PHY_RX_OVRD_IN_HI, USB_PHY_RX_EQ_VAL_4)
+static void erratum_a009007(void __iomem *phy, u16 val1, u16 val2, u16 val3, u16 val4)
+{
+ scfg_out16(phy + SCFG_USB_PHY_RX_OVRD_IN_HI, val1);
+ scfg_out16(phy + SCFG_USB_PHY_RX_OVRD_IN_HI, val2);
+ scfg_out16(phy + SCFG_USB_PHY_RX_OVRD_IN_HI, val3);
+ scfg_out16(phy + SCFG_USB_PHY_RX_OVRD_IN_HI, val4);
+}
static void erratum_a009007_ls1046a(void)
{
- void __iomem *usb_phy = IOMEM(SCFG_USB_PHY1);
-
- PROGRAM_USB_PHY_RX_OVRD_IN_HI(usb_phy);
- usb_phy = (void __iomem *)SCFG_USB_PHY2;
- PROGRAM_USB_PHY_RX_OVRD_IN_HI(usb_phy);
+ erratum_a009007(IOMEM(SCFG_USB_PHY1), 0x0000, 0x0080, 0x0380, 0x0b80);
+ erratum_a009007(IOMEM(SCFG_USB_PHY2), 0x0000, 0x0080, 0x0380, 0x0b80);
+ erratum_a009007(IOMEM(SCFG_USB_PHY3), 0x0000, 0x0080, 0x0380, 0x0b80);
+}
- usb_phy = (void __iomem *)SCFG_USB_PHY3;
- PROGRAM_USB_PHY_RX_OVRD_IN_HI(usb_phy);
+static void erratum_a009007_ls1021a(void)
+{
+ erratum_a009007(IOMEM(SCFG_USB_PHY1), 0x0000, 0x8000, 0x8004, 0x800C);
}
static inline void set_usb_txvreftune(u32 __iomem *scfg, u32 offset)
@@ -49,6 +66,18 @@ static inline void set_usb_txvreftune(u32 __iomem *scfg, u32 offset)
scfg_clrsetbits32(scfg + offset / 4, 0xf << 6, SCFG_USB_TXVREFTUNE << 6);
}
+static void erratum_a009007_ls1028a(void)
+{
+ erratum_a009007(IOMEM(LSCH3_DCSR_BASE), 0x0000, 0x0080, 0x0380, 0x0b80);
+}
+
+static void erratum_a009008_ls1021a(void)
+{
+ u32 __iomem *scfg = IOMEM(LSCH2_SCFG_ADDR);
+
+ set_usb_txvreftune(scfg, SCFG_USB3PRM1CR_USB1);
+}
+
static void erratum_a009008_ls1046a(void)
{
u32 __iomem *scfg = IOMEM(LSCH2_SCFG_ADDR);
@@ -63,6 +92,13 @@ static inline void set_usb_sqrxtune(u32 __iomem *scfg, u32 offset)
scfg_clrbits32(scfg + offset / 4, SCFG_USB_SQRXTUNE_MASK << 23);
}
+static void erratum_a009798_ls1021a(void)
+{
+ u32 __iomem *scfg = IOMEM(LSCH2_SCFG_ADDR);
+
+ set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR_USB1);
+}
+
static void erratum_a009798_ls1046a(void)
{
u32 __iomem *scfg = IOMEM(LSCH2_SCFG_ADDR);
@@ -72,15 +108,16 @@ static void erratum_a009798_ls1046a(void)
set_usb_sqrxtune(scfg, SCFG_USB3PRM1CR_USB3);
}
-static void erratum_a008850_early(void)
+static void erratum_a008850_early(struct ccsr_cci400 __iomem *cci,
+ struct ccsr_ddr __iomem *ddr)
{
/* part 1 of 2 */
- struct ccsr_cci400 __iomem *cci = IOMEM(LSCH2_CCI400_ADDR);
- struct ccsr_ddr __iomem *ddr = IOMEM(LSCH2_DDR_ADDR);
/* Skip if running at lower exception level */
- if (current_el() < 3)
- return;
+#if __LINUX_ARM_ARCH__ > 7
+ if (current_el() < 3)
+ return;
+#endif
/* disables propagation of barrier transactions to DDRC from CCI400 */
out_le32(&cci->ctrl_ord, CCI400_CTRLORD_TERM_BARRIER);
@@ -89,27 +126,64 @@ static void erratum_a008850_early(void)
ddr_out32(&ddr->eor, DDR_EOR_RD_REOD_DIS | DDR_EOR_WD_REOD_DIS);
}
-/* erratum_a009942_check_cpo */
+/*
+ * This erratum requires a register write before being Memory
+ * controller 3 being enabled.
+ */
+static void erratum_a008514(void)
+{
+ u32 *eddrtqcr1;
+
+ eddrtqcr1 = IOMEM(LSCH3_DCSR_DDR3_ADDR) + 0x800;
+ out_le32(eddrtqcr1, 0x63b20002);
+}
+
+static void erratum_a009798(void)
+{
+ u32 __iomem *scfg = IOMEM(LSCH3_SCFG_BASE);
+
+ clrbits_be32(scfg + LSCH3_SCFG_USB3PRM1CR / 4,
+ LSCH3_SCFG_USB_SQRXTUNE_MASK << 23);
+}
void ls1046a_errata(void)
{
- erratum_a008850_early();
+ erratum_a008850_early(IOMEM(LSCH2_CCI400_ADDR), IOMEM(LSCH2_DDR_ADDR));
erratum_a009008_ls1046a();
erratum_a009798_ls1046a();
erratum_a008997_ls1046a();
erratum_a009007_ls1046a();
}
-static void erratum_a008850_post(void)
+void ls1021a_errata(void)
+{
+ erratum_a008850_early(IOMEM(LSCH2_CCI400_ADDR), IOMEM(LSCH2_DDR_ADDR));
+ erratum_a009008_ls1021a();
+ erratum_a009798_ls1021a();
+ erratum_a008997_ls1021a();
+ erratum_a009007_ls1021a();
+}
+
+void ls1028a_errata(void)
+{
+ erratum_a008850_early(IOMEM(LSCH3_CCI400_ADDR), IOMEM(LSCH3_DDR_ADDR));
+ erratum_a009007_ls1028a();
+ erratum_a008997_ls1028a();
+ erratum_a008514();
+ erratum_a009798();
+}
+
+static void erratum_a008850_post(struct ccsr_cci400 __iomem *cci,
+ struct ccsr_ddr __iomem *ddr)
{
/* part 2 of 2 */
- struct ccsr_cci400 __iomem *cci = IOMEM(LSCH2_CCI400_ADDR);
- struct ccsr_ddr __iomem *ddr = IOMEM(LSCH2_DDR_ADDR);
u32 tmp;
/* Skip if running at lower exception level */
- if (current_el() < 3)
- return;
+#if __LINUX_ARM_ARCH__ > 7
+ if (current_el() < 3)
+ return;
+#endif
/* enable propagation of barrier transactions to DDRC from CCI400 */
out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER);
@@ -190,6 +264,16 @@ static void erratum_a009942_check_cpo(void)
void ls1046a_errata_post_ddr(void)
{
- erratum_a008850_post();
+ erratum_a008850_post(IOMEM(LSCH2_CCI400_ADDR), IOMEM(LSCH2_DDR_ADDR));
erratum_a009942_check_cpo();
}
+
+void ls1021a_errata_post_ddr(void)
+{
+ erratum_a008850_post(IOMEM(LSCH2_CCI400_ADDR), IOMEM(LSCH2_DDR_ADDR));
+}
+
+void ls1028a_errata_post_ddr(void)
+{
+ erratum_a008850_post(IOMEM(LSCH3_CCI400_ADDR), IOMEM(LSCH3_DDR_ADDR));
+}
diff --git a/arch/arm/mach-layerscape/icid.c b/arch/arm/mach-layerscape/icid.c
index 644401b181..ebe3896075 100644
--- a/arch/arm/mach-layerscape/icid.c
+++ b/arch/arm/mach-layerscape/icid.c
@@ -1,10 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <io.h>
#include <init.h>
#include <of_address.h>
#include <soc/fsl/immap_lsch2.h>
+#include <soc/fsl/immap_lsch3.h>
#include <soc/fsl/fsl_qbman.h>
#include <soc/fsl/fsl_fman.h>
+#include <mach/layerscape/layerscape.h>
/*
* Stream IDs on Chassis-2 (for example ls1043a, ls1046a, ls1012) devices
@@ -65,6 +69,72 @@ struct icid_id_table {
phys_addr_t reg_addr;
};
+static void of_set_iommu_prop(struct device_node *np, phandle iommu_handle,
+ int stream_id)
+{
+ u32 prop[] = {
+ iommu_handle,
+ stream_id
+ };
+
+ of_property_write_u32_array(np, "iommus", prop, ARRAY_SIZE(prop));
+}
+
+static phandle of_get_iommu_handle(struct device_node *root)
+{
+ struct device_node *iommu;
+
+ iommu = of_find_compatible_node(root, NULL, "arm,mmu-500");
+ if (!iommu) {
+ pr_info("No \"arm,mmu-500\" node found, won't fixup\n");
+ return 0;
+ }
+
+ return of_node_create_phandle(iommu);
+}
+
+static int of_fixup_icid(struct device_node *root, phandle iommu_handle,
+ const struct icid_id_table *icid_table, int num_icid)
+{
+ int i;
+
+ for (i = 0; i < num_icid; i++) {
+ const struct icid_id_table *icid = &icid_table[i];
+ struct device_node *np;
+
+ if (!icid->compat)
+ continue;
+
+ for_each_compatible_node_from(np, root, NULL, icid->compat) {
+ struct resource res;
+
+ if (of_address_to_resource(np, 0, &res))
+ continue;
+
+ if (res.start == icid->compat_addr) {
+ of_set_iommu_prop(np, iommu_handle, icid->id);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void setup_icid_offsets(const struct icid_id_table *icid_table, int num_icids, bool le)
+{
+ int i;
+
+ for (i = 0; i < num_icids; i++) {
+ const struct icid_id_table *icid = &icid_table[i];
+
+ if (le)
+ out_le32((u32 *)(icid->reg_addr), icid->reg);
+ else
+ out_be32((u32 *)(icid->reg_addr), icid->reg);
+ }
+}
+
struct fman_icid_id_table {
u32 port_id;
u32 icid;
@@ -78,7 +148,7 @@ struct fman_icid_id_table {
#define SEC_QIIC_LS 0x70024
#define SEC_IRBAR_JRn(n) (0x10000 * ((n) + 1))
-struct icid_id_table icid_tbl_ls1046a[] = {
+static const struct icid_id_table icid_tbl_ls1046a[] = {
{
.compat = "fsl,qman",
.id = DPAA1_SID_START,
@@ -206,7 +276,7 @@ struct icid_id_table icid_tbl_ls1046a[] = {
},
};
-struct fman_icid_id_table fman_icid_tbl_ls1046a[] = {
+static const struct fman_icid_id_table fman_icid_tbl_ls1046a[] = {
{
.port_id = 0x02,
.icid = DPAA1_SID_END,
@@ -276,7 +346,7 @@ struct fman_icid_id_table fman_icid_tbl_ls1046a[] = {
},
};
-static int get_fman_port_icid(int port_id, struct fman_icid_id_table *tbl,
+static int get_fman_port_icid(int port_id, const struct fman_icid_id_table *tbl,
const int size)
{
int i;
@@ -289,18 +359,7 @@ static int get_fman_port_icid(int port_id, struct fman_icid_id_table *tbl,
return -ENODEV;
}
-static void fdt_set_iommu_prop(struct device_node *np, phandle iommu_handle,
- int stream_id)
-{
- u32 prop[2];
-
- prop[0] = cpu_to_fdt32(iommu_handle);
- prop[1] = cpu_to_fdt32(stream_id);
-
- of_set_property(np, "iommus", prop, sizeof(prop), 1);
-}
-
-static void fdt_fixup_fman_port_icid_by_compat(struct device_node *root,
+static void of_fixup_fman_port_icid_by_compat(struct device_node *root,
phandle iommu_handle,
const char *compat)
{
@@ -321,11 +380,11 @@ static void fdt_fixup_fman_port_icid_by_compat(struct device_node *root,
continue;
}
- fdt_set_iommu_prop(np, iommu_handle, icid);
+ of_set_iommu_prop(np, iommu_handle, icid);
}
}
-static void fdt_fixup_fman_icids(struct device_node *root, phandle iommu_handle)
+static void of_fixup_fman_icids(struct device_node *root, phandle iommu_handle)
{
static const char * const compats[] = {
"fsl,fman-v3-port-oh",
@@ -335,7 +394,7 @@ static void fdt_fixup_fman_icids(struct device_node *root, phandle iommu_handle)
int i;
for (i = 0; i < ARRAY_SIZE(compats); i++)
- fdt_fixup_fman_port_icid_by_compat(root, iommu_handle, compats[i]);
+ of_fixup_fman_port_icid_by_compat(root, iommu_handle, compats[i]);
}
struct qportal_info {
@@ -345,7 +404,7 @@ struct qportal_info {
u8 sdest;
};
-struct qportal_info qp_info[] = {
+static const struct qportal_info qp_info[] = {
{
.dicid = DPAA1_SID_END,
.ficid = DPAA1_SID_END,
@@ -437,7 +496,7 @@ static void setup_qbman_portals(void)
out_be32(&qman->qcsp_bar, (u32)QMAN_MEM_PHYS);
for (i = 0; i < ARRAY_SIZE(qp_info); i++) {
- struct qportal_info *qi = &qp_info[i];
+ const struct qportal_info *qi = &qp_info[i];
out_be32(&qman->qcsp[i].qcsp_lio_cfg, (qi->icid << 16) | qi->dicid);
/* set frame icid */
@@ -449,22 +508,22 @@ static void setup_qbman_portals(void)
inhibit_portals(qpaddr, ARRAY_SIZE(qp_info), QMAN_SP_CINH_SIZE);
}
-static void fdt_set_qportal_iommu_prop(struct device_node *np, phandle iommu_handle,
- struct qportal_info *qp_info)
+static void of_set_qportal_iommu_prop(struct device_node *np, phandle iommu_handle,
+ const struct qportal_info *qp_info)
{
- u32 prop[6];
-
- prop[0] = cpu_to_fdt32(iommu_handle);
- prop[1] = cpu_to_fdt32(qp_info->icid);
- prop[2] = cpu_to_fdt32(iommu_handle);
- prop[3] = cpu_to_fdt32(qp_info->dicid);
- prop[4] = cpu_to_fdt32(iommu_handle);
- prop[5] = cpu_to_fdt32(qp_info->ficid);
+ u32 prop[] = {
+ iommu_handle,
+ qp_info->icid,
+ iommu_handle,
+ qp_info->dicid,
+ iommu_handle,
+ qp_info->ficid
+ };
- of_set_property(np, "iommus", prop, sizeof(prop), 1);
+ of_property_write_u32_array(np, "iommus", prop, ARRAY_SIZE(prop));
}
-static void fdt_fixup_qportals(struct device_node *root, phandle iommu_handle)
+static void of_fixup_qportals(struct device_node *root, phandle iommu_handle)
{
struct device_node *np;
unsigned int maj, min;
@@ -484,77 +543,253 @@ static void fdt_fixup_qportals(struct device_node *root, phandle iommu_handle)
if (ret)
continue;
- fdt_set_qportal_iommu_prop(np, iommu_handle, &qp_info[cell_index]);
+ of_set_qportal_iommu_prop(np, iommu_handle, &qp_info[cell_index]);
}
}
-static int icid_of_fixup(struct device_node *root, void *context)
+static int of_fixup_ls1046a(struct device_node *root, void *context)
{
- int i;
- struct device_node *iommu;
phandle iommu_handle;
- iommu = of_find_compatible_node(root, NULL, "arm,mmu-500");
- if (!iommu) {
- pr_info("No \"arm,mmu-500\" node found, won't fixup\n");
+ iommu_handle = of_get_iommu_handle(root);
+ if (!iommu_handle)
return 0;
- }
- iommu_handle = of_node_create_phandle(iommu);
+ of_fixup_icid(root, iommu_handle, icid_tbl_ls1046a, ARRAY_SIZE(icid_tbl_ls1046a));
+ of_fixup_fman_icids(root, iommu_handle);
+ of_fixup_qportals(root, iommu_handle);
- for (i = 0; i < ARRAY_SIZE(icid_tbl_ls1046a); i++) {
- struct icid_id_table *icid = &icid_tbl_ls1046a[i];
- struct device_node *np;
+ return 0;
+}
- if (!icid->compat)
- continue;
+void ls1046a_setup_icids(void)
+{
+ struct ccsr_fman *fm = (void *)LSCH2_FM1_ADDR;
+ int i;
- for_each_compatible_node_from(np, root, NULL, icid->compat) {
- struct resource res;
+ setup_icid_offsets(icid_tbl_ls1046a, ARRAY_SIZE(icid_tbl_ls1046a), false);
- if (of_address_to_resource(np, 0, &res))
- continue;
+ /* setup fman icids */
+ for (i = 0; i < ARRAY_SIZE(fman_icid_tbl_ls1046a); i++) {
+ const struct fman_icid_id_table *icid = &fman_icid_tbl_ls1046a[i];
- if (res.start == icid->compat_addr) {
- fdt_set_iommu_prop(np, iommu_handle, icid->id);
- break;
- }
- }
+ out_be32(&fm->fm_bmi_common.fmbm_ppid[icid->port_id - 1],
+ icid->icid);
+ }
+
+ setup_qbman_portals();
+
+ of_register_fixup(of_fixup_ls1046a, NULL);
+}
+
+static const struct icid_id_table icid_tbl_ls1028a[] = {
+ {
+ .compat = "snps,dwc3",
+ .id = 1,
+ .reg = 1,
+ .compat_addr = LSCH3_XHCI_USB1_ADDR,
+ .reg_addr = offsetof(struct lsch3_ccsr_gur, usb1_amqr) + LSCH3_GUTS_ADDR,
+ }, {
+ .compat = "snps,dwc3",
+ .id = 2,
+ .reg = 2,
+ .compat_addr = LSCH3_XHCI_USB2_ADDR,
+ .reg_addr = offsetof(struct lsch3_ccsr_gur, usb2_amqr) + LSCH3_GUTS_ADDR,
+ }, {
+ .compat = "fsl,esdhc",
+ .id = 3,
+ .reg = 3,
+ .compat_addr = LSCH3_ESDHC1_BASE_ADDR,
+ .reg_addr = offsetof(struct lsch3_ccsr_gur, sdmm1_amqr) + LSCH3_GUTS_ADDR,
+ }, {
+ .compat = "fsl,esdhc",
+ .id = 69,
+ .reg = 69,
+ .compat_addr = LSCH3_ESDHC2_BASE_ADDR,
+ .reg_addr = offsetof(struct lsch3_ccsr_gur, sdmm2_amqr) + LSCH3_GUTS_ADDR,
+ }, {
+ .compat = "fsl,ls1028a-ahci",
+ .id = 4,
+ .reg = 4,
+ .compat_addr = LSCH3_AHCI1_ADDR,
+ .reg_addr = offsetof(struct lsch3_ccsr_gur, sata1_amqr) + LSCH3_GUTS_ADDR,
+ }, {
+ .compat = "fsl,vf610-edma",
+ .id = 40,
+ .reg = 40,
+ .compat_addr = LSCH3_EDMA_ADDR,
+ .reg_addr = offsetof(struct lsch3_ccsr_gur, spare3_amqr) + LSCH3_GUTS_ADDR,
+ }, {
+ .compat = "fsl,ls1028a-qdma",
+ .id = 5,
+ .reg = (1 << 31) | 5,
+ .compat_addr = LSCH3_QDMA_ADDR,
+ .reg_addr = LSCH3_QDMA_ADDR + QMAN_CQSIDR_REG,
+ }, {
+ .compat = NULL,
+ .id = 5,
+ .reg = (1 << 31) | 5,
+ .compat_addr = LSCH3_QDMA_ADDR,
+ .reg_addr = LSCH3_QDMA_ADDR + QMAN_CQSIDR_REG + 4,
+ }, {
+ .compat = "vivante,gc",
+ .id = 71,
+ .reg = 71,
+ .compat_addr = LSCH3_GPU_ADDR,
+ .reg_addr = offsetof(struct lsch3_ccsr_gur, misc1_amqr) + LSCH3_GUTS_ADDR,
+ }, {
+ .compat = "arm,mali-dp500",
+ .id = 72,
+ .reg = 72,
+ .compat_addr = LSCH3_DISPLAY_ADDR,
+ .reg_addr = offsetof(struct lsch3_ccsr_gur, spare2_amqr) + LSCH3_GUTS_ADDR,
+ }, {
+ .compat = "fsl,sec-v4.0-job-ring",
+ .id = 65,
+ .reg = 65,
+ .compat_addr = LSCH3_SEC_JR0_ADDR,
+ .reg_addr = offsetof(struct ccsr_sec, jrliodnr[0].ls) + LSCH3_SEC_ADDR,
+ }, {
+ .compat = "fsl,sec-v4.0-job-ring",
+ .id = 66,
+ .reg = 66,
+ .compat_addr = LSCH3_SEC_JR1_ADDR,
+ .reg_addr = offsetof(struct ccsr_sec, jrliodnr[1].ls) + LSCH3_SEC_ADDR,
+ }, {
+ .id = 67,
+ .reg = 67,
+ .compat_addr = LSCH3_SEC_JR2_ADDR,
+ .reg_addr = offsetof(struct ccsr_sec, jrliodnr[2].ls) + LSCH3_SEC_ADDR,
+ }, {
+ .compat = "fsl,sec-v4.0-job-ring",
+ .id = 68,
+ .reg = 68,
+ .compat_addr = LSCH3_SEC_JR3_ADDR,
+ .reg_addr = offsetof(struct ccsr_sec, jrliodnr[3].ls) + LSCH3_SEC_ADDR,
+ }, {
+ .id = 64,
+ .reg = 64,
+ .compat_addr = 0,
+ .reg_addr = offsetof(struct ccsr_sec, rticliodnr[0].ls) + LSCH3_SEC_ADDR,
+ }, {
+ .id = 64,
+ .reg = 64,
+ .compat_addr = 0,
+ .reg_addr = offsetof(struct ccsr_sec, rticliodnr[1].ls) + LSCH3_SEC_ADDR,
+ }, {
+ .id = 64,
+ .reg = 64,
+ .compat_addr = 0,
+ .reg_addr = offsetof(struct ccsr_sec, rticliodnr[2].ls) + LSCH3_SEC_ADDR,
+ }, {
+ .id = 64,
+ .reg = 64,
+ .compat_addr = 0,
+ .reg_addr = offsetof(struct ccsr_sec, rticliodnr[3].ls) + LSCH3_SEC_ADDR,
+ }, {
+ .id = 64,
+ .reg = 64,
+ .compat_addr = 0,
+ .reg_addr = offsetof(struct ccsr_sec, decoliodnr[0].ls) + LSCH3_SEC_ADDR,
+ }, {
+ .id = 64,
+ .reg = 64,
+ .compat_addr = 0,
+ .reg_addr = offsetof(struct ccsr_sec, decoliodnr[1].ls) + LSCH3_SEC_ADDR,
}
+};
+
+static int of_fixup_icid_ls1028a(struct device_node *root, void *context)
+{
+ phandle iommu_handle;
+
+ iommu_handle = of_get_iommu_handle(root);
+ if (!iommu_handle)
+ return 0;
- fdt_fixup_fman_icids(root, iommu_handle);
- fdt_fixup_qportals(root, iommu_handle);
+ of_fixup_icid(root, iommu_handle, icid_tbl_ls1028a, ARRAY_SIZE(icid_tbl_ls1028a));
return 0;
}
-static int layerscape_setup_icids(void)
+/* offset of IERB config register per PCI function */
+static const int ierb_offset[] = {
+ 0x0800,
+ 0x1800,
+ 0x2800,
+ 0x3800,
+ 0x4800,
+ 0x5800,
+ 0x6800,
+ -1,
+ 0x0804,
+ 0x0808,
+ 0x1804,
+ 0x1808,
+};
+
+#define ECAM_IERB_BASE 0x1f0800000ULL
+#define ECAM_IERB_MSICAR (ECAM_IERB_BASE + 0xa400)
+#define ECAM_IERB_MSICAR_VALUE 0x30
+#define FSL_ECAM_STREAM_ID_START 41
+
+/*
+ * Use a custom function for LS1028A, for now this is the only SoC with IERB
+ * and we're currently considering reorganizing IERB for future SoCs.
+ */
+static void ls1028a_set_ecam_icids(void)
{
int i;
- struct ccsr_fman *fm = (void *)LSCH2_FM1_ADDR;
- if (!of_machine_is_compatible("fsl,ls1046a"))
- return 0;
+ out_le32(ECAM_IERB_MSICAR, ECAM_IERB_MSICAR_VALUE);
- /* setup general icid offsets */
- for (i = 0; i < ARRAY_SIZE(icid_tbl_ls1046a); i++) {
- struct icid_id_table *icid = &icid_tbl_ls1046a[i];
+ for (i = 0; i < ARRAY_SIZE(ierb_offset); i++) {
+ if (ierb_offset[i] < 0)
+ continue;
- out_be32((u32 *)(icid->reg_addr), icid->reg);
+ out_le32(ECAM_IERB_BASE + ierb_offset[i],
+ FSL_ECAM_STREAM_ID_START + i);
}
+}
- /* setup fman icids */
- for (i = 0; i < ARRAY_SIZE(fman_icid_tbl_ls1046a); i++) {
- struct fman_icid_id_table *icid = &fman_icid_tbl_ls1046a[i];
+static int of_fixup_ecam_ls1028a(struct device_node *root, void *context)
+{
+ struct device_node *np;
+ int i, ret;
+ const char *props[] = { "msi-map", "iommu-map" };
+ uint32_t map[4];
- out_be32(&fm->fm_bmi_common.fmbm_ppid[icid->port_id - 1],
- icid->icid);
+ np = of_find_compatible_node(root, NULL, "pci-host-ecam-generic");
+ if (!np) {
+ pr_info("No \"pci-host-ecam-generic\" node found, won't fixup\n");
+ return 0;
}
- setup_qbman_portals();
+ for (i = 0; i < ARRAY_SIZE(props); i++) {
+ ret = of_property_read_u32_array(np, props[i], map, 4);
+ if (ret) {
+ pr_err("Cannot read \"%s\" property: %pe", props[i], ERR_PTR(ret));
+ return ret;
+ }
- of_register_fixup(icid_of_fixup, NULL);
+ map[2] = FSL_ECAM_STREAM_ID_START;
+ map[3] = ARRAY_SIZE(ierb_offset);
+ ret = of_property_write_u32_array(np, props[i], map, 4);
+ if (ret) {
+ pr_err("Cannot write \"%s\" property: %pe", props[i], ERR_PTR(ret));
+ return ret;
+ }
+ }
return 0;
}
-coredevice_initcall(layerscape_setup_icids);
+
+void ls1028a_setup_icids(void)
+{
+ setup_icid_offsets(icid_tbl_ls1028a, ARRAY_SIZE(icid_tbl_ls1028a), true);
+
+ ls1028a_set_ecam_icids();
+
+ of_register_fixup(of_fixup_icid_ls1028a, NULL);
+ of_register_fixup(of_fixup_ecam_ls1028a, NULL);
+}
diff --git a/arch/arm/mach-layerscape/include/mach/bbu.h b/arch/arm/mach-layerscape/include/mach/bbu.h
deleted file mode 100644
index 1ea0cbb11f..0000000000
--- a/arch/arm/mach-layerscape/include/mach/bbu.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef __MACH_LAYERSCAPE_BBU_H
-#define __MACH_LAYERSCAPE_BBU_H
-
-#include <bbu.h>
-
-static inline int ls1046a_bbu_mmc_register_handler(const char *name,
- const char *devicefile,
- unsigned long flags)
-{
- return bbu_register_std_file_update(name, flags, devicefile,
- filetype_layerscape_image);
-}
-
-static inline int ls1046a_bbu_qspi_register_handler(const char *name,
- const char *devicefile,
- unsigned long flags)
-{
- return bbu_register_std_file_update(name, flags, devicefile,
- filetype_layerscape_qspi_image);
-}
-
-#endif /* __MACH_LAYERSCAPE_BBU_H */ \ No newline at end of file
diff --git a/arch/arm/mach-layerscape/include/mach/debug_ll.h b/arch/arm/mach-layerscape/include/mach/debug_ll.h
deleted file mode 100644
index 2658a4a7c9..0000000000
--- a/arch/arm/mach-layerscape/include/mach/debug_ll.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef __INCLUDE_ARCH_DEBUG_LL_H__
-#define __INCLUDE_ARCH_DEBUG_LL_H__
-
-#include <io.h>
-#include <soc/fsl/immap_lsch2.h>
-
-#define __LS_UART_BASE(num) LSCH2_NS16550_COM##num
-#define LS_UART_BASE(num) __LS_UART_BASE(num)
-
-static inline uint8_t debug_ll_read_reg(int reg)
-{
- void __iomem *base = IOMEM(LS_UART_BASE(CONFIG_DEBUG_LAYERSCAPE_UART_PORT));
-
- return readb(base + reg);
-}
-
-static inline void debug_ll_write_reg(int reg, uint8_t val)
-{
- void __iomem *base = IOMEM(LS_UART_BASE(CONFIG_DEBUG_LAYERSCAPE_UART_PORT));
-
- writeb(val, base + reg);
-}
-
-#include <debug_ll/ns16550.h>
-
-static inline void debug_ll_init(void)
-{
- uint16_t divisor;
-
- divisor = debug_ll_ns16550_calc_divisor(300000000);
- debug_ll_ns16550_init(divisor);
-}
-
-#endif /* __INCLUDE_ARCH_DEBUG_LL_H__ */
diff --git a/arch/arm/mach-layerscape/include/mach/errata.h b/arch/arm/mach-layerscape/include/mach/errata.h
deleted file mode 100644
index bdefa22172..0000000000
--- a/arch/arm/mach-layerscape/include/mach/errata.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MACH_ERRATA_H
-#define __MACH_ERRATA_H
-
-void ls1046a_errata(void);
-void ls1046a_errata_post_ddr(void);
-
-#endif /* __MACH_ERRATA_H */
diff --git a/arch/arm/mach-layerscape/include/mach/layerscape.h b/arch/arm/mach-layerscape/include/mach/layerscape.h
deleted file mode 100644
index 1f1da0f66e..0000000000
--- a/arch/arm/mach-layerscape/include/mach/layerscape.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __MACH_LAYERSCAPE_H
-#define __MACH_LAYERSCAPE_H
-
-#define LS1046A_DDR_SDRAM_BASE 0x80000000
-#define LS1046A_DDR_FREQ 2100000000
-
-enum bootsource ls1046_bootsource_get(void);
-
-#ifdef CONFIG_ARCH_LAYERSCAPE_PPA
-int ls1046a_ppa_init(resource_size_t ppa_start, resource_size_t ppa_size);
-#else
-static inline int ls1046a_ppa_init(resource_size_t ppa_start,
- resource_size_t ppa_size)
-{
- return -ENOSYS;
-}
-#endif
-
-#endif /* __MACH_LAYERSCAPE_H */
diff --git a/arch/arm/mach-layerscape/include/mach/lowlevel.h b/arch/arm/mach-layerscape/include/mach/lowlevel.h
deleted file mode 100644
index 0f5f0f3aad..0000000000
--- a/arch/arm/mach-layerscape/include/mach/lowlevel.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __MACH_LOWLEVEL_H
-#define __MACH_LOWLEVEL_H
-
-void ls1046a_init_lowlevel(void);
-void ls1046a_init_l2_latency(void);
-
-#endif /* __MACH_LOWLEVEL_H */
diff --git a/arch/arm/mach-layerscape/include/mach/xload.h b/arch/arm/mach-layerscape/include/mach/xload.h
deleted file mode 100644
index eb2d998865..0000000000
--- a/arch/arm/mach-layerscape/include/mach/xload.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __MACH_XLOAD_H
-#define __MACH_XLOAD_H
-
-int ls1046a_esdhc_start_image(unsigned long r0, unsigned long r1, unsigned long r2);
-int ls1046a_qspi_start_image(unsigned long r0, unsigned long r1,
- unsigned long r2);
-int ls1046a_xload_start_image(unsigned long r0, unsigned long r1,
- unsigned long r2);
-
-#endif /* __MACH_XLOAD_H */
diff --git a/arch/arm/mach-layerscape/lowlevel-ls1028a.c b/arch/arm/mach-layerscape/lowlevel-ls1028a.c
new file mode 100644
index 0000000000..fd013b2b52
--- /dev/null
+++ b/arch/arm/mach-layerscape/lowlevel-ls1028a.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+#include <common.h>
+#include <io.h>
+#include <asm/syscounter.h>
+#include <asm/system.h>
+#include <mach/layerscape/errata.h>
+#include <mach/layerscape/lowlevel.h>
+#include <soc/fsl/immap_lsch3.h>
+#include <soc/fsl/scfg.h>
+
+static void ls1028a_timer_init(void)
+{
+ u32 __iomem *cntcr = IOMEM(LSCH3_TIMER_ADDR);
+ u32 __iomem *cltbenr = IOMEM(LSCH3_PMU_CLTBENR);
+
+ u32 __iomem *pctbenr = IOMEM(LSCH3_PCTBENR_OFFSET);
+
+ /* Enable timebase for all clusters.
+ * It is safe to do so even some clusters are not enabled.
+ */
+ out_le32(cltbenr, 0xf);
+
+ /*
+ * In certain Layerscape SoCs, the clock for each core's
+ * has an enable bit in the PMU Physical Core Time Base Enable
+ * Register (PCTBENR), which allows the watchdog to operate.
+ */
+ setbits_le32(pctbenr, 0xff);
+
+ /* Enable clock for timer
+ * This is a global setting.
+ */
+ out_le32(cntcr, 0x1);
+}
+
+void ls1028a_init_lowlevel(void)
+{
+ scfg_init(SCFG_ENDIANESS_LITTLE);
+ set_cntfrq(25000000);
+ ls1028a_timer_init();
+ ls1028a_errata();
+}
diff --git a/arch/arm/mach-layerscape/lowlevel-ls102xa.c b/arch/arm/mach-layerscape/lowlevel-ls102xa.c
new file mode 100644
index 0000000000..440d50282a
--- /dev/null
+++ b/arch/arm/mach-layerscape/lowlevel-ls102xa.c
@@ -0,0 +1,400 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * Derived from Freescale LSDK-19.09-update-311219
+ */
+#include <common.h>
+#include <io.h>
+#include <clock.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/syscounter.h>
+#include <asm/system.h>
+#include <mach/layerscape/errata.h>
+#include <mach/layerscape/lowlevel.h>
+#include <mach/layerscape/fsl_epu.h>
+#include <soc/fsl/immap_lsch2.h>
+#include <soc/fsl/fsl_immap.h>
+#include <soc/fsl/scfg.h>
+
+void udelay(unsigned long usecs)
+{
+ arm_architected_timer_udelay(usecs);
+}
+
+void mdelay(unsigned long msecs)
+{
+ udelay(1000 * msecs);
+}
+
+enum csu_cslx_access {
+ CSU_NS_SUP_R = 0x08,
+ CSU_NS_SUP_W = 0x80,
+ CSU_NS_SUP_RW = 0x88,
+ CSU_NS_USER_R = 0x04,
+ CSU_NS_USER_W = 0x40,
+ CSU_NS_USER_RW = 0x44,
+ CSU_S_SUP_R = 0x02,
+ CSU_S_SUP_W = 0x20,
+ CSU_S_SUP_RW = 0x22,
+ CSU_S_USER_R = 0x01,
+ CSU_S_USER_W = 0x10,
+ CSU_S_USER_RW = 0x11,
+ CSU_ALL_RW = 0xff,
+};
+
+struct csu_ns_dev {
+ unsigned long ind;
+ uint32_t val;
+};
+
+enum csu_cslx_ind {
+ CSU_CSLX_PCIE2_IO = 0,
+ CSU_CSLX_PCIE1_IO,
+ CSU_CSLX_MG2TPR_IP,
+ CSU_CSLX_IFC_MEM,
+ CSU_CSLX_OCRAM,
+ CSU_CSLX_GIC,
+ CSU_CSLX_PCIE1,
+ CSU_CSLX_OCRAM2,
+ CSU_CSLX_QSPI_MEM,
+ CSU_CSLX_PCIE2,
+ CSU_CSLX_SATA,
+ CSU_CSLX_USB3,
+ CSU_CSLX_SERDES = 32,
+ CSU_CSLX_QDMA,
+ CSU_CSLX_LPUART2,
+ CSU_CSLX_LPUART1,
+ CSU_CSLX_LPUART4,
+ CSU_CSLX_LPUART3,
+ CSU_CSLX_LPUART6,
+ CSU_CSLX_LPUART5,
+ CSU_CSLX_DSPI2 = 40,
+ CSU_CSLX_DSPI1,
+ CSU_CSLX_QSPI,
+ CSU_CSLX_ESDHC,
+ CSU_CSLX_2D_ACE,
+ CSU_CSLX_IFC,
+ CSU_CSLX_I2C1,
+ CSU_CSLX_USB2,
+ CSU_CSLX_I2C3,
+ CSU_CSLX_I2C2,
+ CSU_CSLX_DUART2 = 50,
+ CSU_CSLX_DUART1,
+ CSU_CSLX_WDT2,
+ CSU_CSLX_WDT1,
+ CSU_CSLX_EDMA,
+ CSU_CSLX_SYS_CNT,
+ CSU_CSLX_DMA_MUX2,
+ CSU_CSLX_DMA_MUX1,
+ CSU_CSLX_DDR,
+ CSU_CSLX_QUICC,
+ CSU_CSLX_DCFG_CCU_RCPM = 60,
+ CSU_CSLX_SECURE_BOOTROM,
+ CSU_CSLX_SFP,
+ CSU_CSLX_TMU,
+ CSU_CSLX_SECURE_MONITOR,
+ CSU_CSLX_RESERVED0,
+ CSU_CSLX_ETSEC1,
+ CSU_CSLX_SEC5_5,
+ CSU_CSLX_ETSEC3,
+ CSU_CSLX_ETSEC2,
+ CSU_CSLX_GPIO2 = 70,
+ CSU_CSLX_GPIO1,
+ CSU_CSLX_GPIO4,
+ CSU_CSLX_GPIO3,
+ CSU_CSLX_PLATFORM_CONT,
+ CSU_CSLX_CSU,
+ CSU_CSLX_ASRC,
+ CSU_CSLX_SPDIF,
+ CSU_CSLX_FLEXCAN2,
+ CSU_CSLX_FLEXCAN1,
+ CSU_CSLX_FLEXCAN4 = 80,
+ CSU_CSLX_FLEXCAN3,
+ CSU_CSLX_SAI2,
+ CSU_CSLX_SAI1,
+ CSU_CSLX_SAI4,
+ CSU_CSLX_SAI3,
+ CSU_CSLX_FTM2,
+ CSU_CSLX_FTM1,
+ CSU_CSLX_FTM4,
+ CSU_CSLX_FTM3,
+ CSU_CSLX_FTM6 = 90,
+ CSU_CSLX_FTM5,
+ CSU_CSLX_FTM8,
+ CSU_CSLX_FTM7,
+ CSU_CSLX_EPU,
+ CSU_CSLX_COP_DCSR,
+ CSU_CSLX_DDI,
+ CSU_CSLX_GDI,
+ CSU_CSLX_RESERVED1,
+ CSU_CSLX_USB3_PHY = 116,
+ CSU_CSLX_RESERVED2,
+ CSU_CSLX_MAX,
+};
+
+static struct csu_ns_dev ns_dev[] = {
+ { CSU_CSLX_PCIE2_IO, CSU_ALL_RW },
+ { CSU_CSLX_PCIE1_IO, CSU_ALL_RW },
+ { CSU_CSLX_MG2TPR_IP, CSU_ALL_RW },
+ { CSU_CSLX_IFC_MEM, CSU_ALL_RW },
+ { CSU_CSLX_OCRAM, CSU_ALL_RW },
+ { CSU_CSLX_GIC, CSU_ALL_RW },
+ { CSU_CSLX_PCIE1, CSU_ALL_RW },
+ { CSU_CSLX_OCRAM2, CSU_ALL_RW },
+ { CSU_CSLX_QSPI_MEM, CSU_ALL_RW },
+ { CSU_CSLX_PCIE2, CSU_ALL_RW },
+ { CSU_CSLX_SATA, CSU_ALL_RW },
+ { CSU_CSLX_USB3, CSU_ALL_RW },
+ { CSU_CSLX_SERDES, CSU_ALL_RW },
+ { CSU_CSLX_QDMA, CSU_ALL_RW },
+ { CSU_CSLX_LPUART2, CSU_ALL_RW },
+ { CSU_CSLX_LPUART1, CSU_ALL_RW },
+ { CSU_CSLX_LPUART4, CSU_ALL_RW },
+ { CSU_CSLX_LPUART3, CSU_ALL_RW },
+ { CSU_CSLX_LPUART6, CSU_ALL_RW },
+ { CSU_CSLX_LPUART5, CSU_ALL_RW },
+ { CSU_CSLX_DSPI2, CSU_ALL_RW },
+ { CSU_CSLX_DSPI1, CSU_ALL_RW },
+ { CSU_CSLX_QSPI, CSU_ALL_RW },
+ { CSU_CSLX_ESDHC, CSU_ALL_RW },
+ { CSU_CSLX_2D_ACE, CSU_ALL_RW },
+ { CSU_CSLX_IFC, CSU_ALL_RW },
+ { CSU_CSLX_I2C1, CSU_ALL_RW },
+ { CSU_CSLX_USB2, CSU_ALL_RW },
+ { CSU_CSLX_I2C3, CSU_ALL_RW },
+ { CSU_CSLX_I2C2, CSU_ALL_RW },
+ { CSU_CSLX_DUART2, CSU_ALL_RW },
+ { CSU_CSLX_DUART1, CSU_ALL_RW },
+ { CSU_CSLX_WDT2, CSU_ALL_RW },
+ { CSU_CSLX_WDT1, CSU_ALL_RW },
+ { CSU_CSLX_EDMA, CSU_ALL_RW },
+ { CSU_CSLX_SYS_CNT, CSU_ALL_RW },
+ { CSU_CSLX_DMA_MUX2, CSU_ALL_RW },
+ { CSU_CSLX_DMA_MUX1, CSU_ALL_RW },
+ { CSU_CSLX_DDR, CSU_ALL_RW },
+ { CSU_CSLX_QUICC, CSU_ALL_RW },
+ { CSU_CSLX_DCFG_CCU_RCPM, CSU_ALL_RW },
+ { CSU_CSLX_SECURE_BOOTROM, CSU_ALL_RW },
+ { CSU_CSLX_SFP, CSU_ALL_RW },
+ { CSU_CSLX_TMU, CSU_ALL_RW },
+ { CSU_CSLX_SECURE_MONITOR, CSU_ALL_RW },
+ { CSU_CSLX_RESERVED0, CSU_ALL_RW },
+ { CSU_CSLX_ETSEC1, CSU_ALL_RW },
+ { CSU_CSLX_SEC5_5, CSU_ALL_RW },
+ { CSU_CSLX_ETSEC3, CSU_ALL_RW },
+ { CSU_CSLX_ETSEC2, CSU_ALL_RW },
+ { CSU_CSLX_GPIO2, CSU_ALL_RW },
+ { CSU_CSLX_GPIO1, CSU_ALL_RW },
+ { CSU_CSLX_GPIO4, CSU_ALL_RW },
+ { CSU_CSLX_GPIO3, CSU_ALL_RW },
+ { CSU_CSLX_PLATFORM_CONT, CSU_ALL_RW },
+ { CSU_CSLX_CSU, CSU_ALL_RW },
+ { CSU_CSLX_ASRC, CSU_ALL_RW },
+ { CSU_CSLX_SPDIF, CSU_ALL_RW },
+ { CSU_CSLX_FLEXCAN2, CSU_ALL_RW },
+ { CSU_CSLX_FLEXCAN1, CSU_ALL_RW },
+ { CSU_CSLX_FLEXCAN4, CSU_ALL_RW },
+ { CSU_CSLX_FLEXCAN3, CSU_ALL_RW },
+ { CSU_CSLX_SAI2, CSU_ALL_RW },
+ { CSU_CSLX_SAI1, CSU_ALL_RW },
+ { CSU_CSLX_SAI4, CSU_ALL_RW },
+ { CSU_CSLX_SAI3, CSU_ALL_RW },
+ { CSU_CSLX_FTM2, CSU_ALL_RW },
+ { CSU_CSLX_FTM1, CSU_ALL_RW },
+ { CSU_CSLX_FTM4, CSU_ALL_RW },
+ { CSU_CSLX_FTM3, CSU_ALL_RW },
+ { CSU_CSLX_FTM6, CSU_ALL_RW },
+ { CSU_CSLX_FTM5, CSU_ALL_RW },
+ { CSU_CSLX_FTM8, CSU_ALL_RW },
+ { CSU_CSLX_FTM7, CSU_ALL_RW },
+ { CSU_CSLX_COP_DCSR, CSU_ALL_RW },
+ { CSU_CSLX_EPU, CSU_ALL_RW },
+ { CSU_CSLX_GDI, CSU_ALL_RW },
+ { CSU_CSLX_DDI, CSU_ALL_RW },
+ { CSU_CSLX_RESERVED1, CSU_ALL_RW },
+ { CSU_CSLX_USB3_PHY, CSU_ALL_RW },
+ { CSU_CSLX_RESERVED2, CSU_ALL_RW },
+};
+
+/* Found in U-boot but not in LS1021ARM.pdf 02/2020 */
+#define DCSR_RCPM2_ADDR 0x20223000
+#define DCSR_RCPM2_CPMFSMCR0 0x400
+#define DCSR_RCPM2_CPMFSMSR0 0x404
+#define DCSR_RCPM2_CPMFSMCR1 0x414
+#define DCSR_RCPM2_CPMFSMSR1 0x418
+#define CPMFSMSR_FSM_STATE_MASK 0x7f
+
+#define DCSR_EPU_ADDR 0x20000000
+
+static void set_devices_ns_access(unsigned long index, u16 val)
+{
+ u32 *base = IOMEM(LSCH2_CSU_ADDR);
+ u32 *reg;
+ uint32_t tmp;
+
+ reg = base + index / 2;
+ tmp = in_be32(reg);
+ if (index % 2 == 0) {
+ tmp &= 0x0000ffff;
+ tmp |= val << 16;
+ } else {
+ tmp &= 0xffff0000;
+ tmp |= val;
+ }
+
+ out_be32(reg, tmp);
+}
+
+static void init_csu(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ns_dev); i++)
+ set_devices_ns_access(ns_dev[i].ind, ns_dev[i].val);
+}
+
+/**
+ * fsl_epu_clean - Clear EPU registers
+ */
+static void fsl_epu_clean(void *epu_base)
+{
+ u32 offset;
+
+ /* follow the exact sequence to clear the registers */
+ /* Clear EPACRn */
+ for (offset = EPACR0; offset <= EPACR15; offset += EPACR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPEVTCRn */
+ for (offset = EPEVTCR0; offset <= EPEVTCR9; offset += EPEVTCR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPGCR */
+ out_be32(epu_base + EPGCR, 0);
+
+ /* Clear EPSMCRn */
+ for (offset = EPSMCR0; offset <= EPSMCR15; offset += EPSMCR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPCCRn */
+ for (offset = EPCCR0; offset <= EPCCR31; offset += EPCCR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPCMPRn */
+ for (offset = EPCMPR0; offset <= EPCMPR31; offset += EPCMPR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPCTRn */
+ for (offset = EPCTR0; offset <= EPCTR31; offset += EPCTR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPIMCRn */
+ for (offset = EPIMCR0; offset <= EPIMCR31; offset += EPIMCR_STRIDE)
+ out_be32(epu_base + offset, 0);
+
+ /* Clear EPXTRIGCRn */
+ out_be32(epu_base + EPXTRIGCR, 0);
+
+ /* Clear EPECRn */
+ for (offset = EPECR0; offset <= EPECR15; offset += EPECR_STRIDE)
+ out_be32(epu_base + offset, 0);
+}
+
+#define TIMER_COMP_VAL 0xffffffffffffffffull
+#define ARCH_TIMER_CTRL_ENABLE (1 << 0)
+#define SYS_COUNTER_CTRL_ENABLE (1 << 24)
+#define SCFG_QSPI_CLKSEL 0x50100000
+
+/* ls102xa_init_lowlevel
+ * Based on ls1046 and U-boot ls102xa arch_cpu_init
+ */
+void ls102xa_init_lowlevel(void)
+{
+ struct ccsr_cci400 __iomem *cci = IOMEM(LSCH2_CCI400_ADDR);
+ struct ls102xa_ccsr_scfg *scfg = IOMEM(LSCH2_SCFG_ADDR);
+ struct ls102xa_ccsr_gur __iomem *gur = IOMEM(LSCH2_GUTS_ADDR);
+ void *rcpm2_base = IOMEM(DCSR_RCPM2_ADDR);
+ void *epu_base = IOMEM(DCSR_EPU_ADDR);
+ uint32_t state, major, ctrl, freq;
+ uint64_t val;
+
+ cortex_a7_lowlevel_init();
+ arm_cpu_lowlevel_init();
+
+ scfg_init(SCFG_ENDIANESS_BIG);
+ init_csu();
+
+ writel(SYS_COUNTER_CTRL_ENABLE, LSCH2_SYS_COUNTER_ADDR);
+ freq = 12500000;
+ asm("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq));
+
+ /* Set PL1 Physical Timer Ctrl */
+ ctrl = ARCH_TIMER_CTRL_ENABLE;
+ asm("mcr p15, 0, %0, c14, c2, 1" : : "r" (ctrl));
+
+ /* Set PL1 Physical Comp Value */
+ val = TIMER_COMP_VAL;
+ asm("mcrr p15, 2, %Q0, %R0, c14" : : "r" (val));
+
+
+ state = in_be32(rcpm2_base + DCSR_RCPM2_CPMFSMSR0) &
+ CPMFSMSR_FSM_STATE_MASK;
+ if (state != 0) {
+ out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR0, 0x80);
+ out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR0, 0x0);
+ }
+ state = in_be32(rcpm2_base + DCSR_RCPM2_CPMFSMSR1) &
+ CPMFSMSR_FSM_STATE_MASK;
+ if (state != 0) {
+ out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR1, 0x80);
+ out_be32(rcpm2_base + DCSR_RCPM2_CPMFSMCR1, 0x0);
+ }
+
+ fsl_epu_clean(epu_base);
+
+ /* Enable all the snoop signal for various masters */
+ out_be32(&scfg->snpcnfgcr, SCFG_SNPCNFGCR_SEC_RD_WR |
+ SCFG_SNPCNFGCR_DBG_RD_WR |
+ SCFG_SNPCNFGCR_EDMA_SNP);
+
+ if (IS_ENABLED(CONFIG_DRIVER_SPI_FSL_QUADSPI))
+ out_be32(&scfg->qspi_cfg, SCFG_QSPI_CLKSEL);
+
+ /* Configure Little endian for SAI, ASRC and SPDIF */
+ out_be32(&scfg->endiancr, SCFG_ENDIANCR_LE);
+
+ /*
+ * Enable snoop requests and DVM message requests for
+ * All the slave interfaces.
+ */
+ out_le32(&cci->slave[0].snoop_ctrl,
+ CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
+ out_le32(&cci->slave[1].snoop_ctrl,
+ CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
+ out_le32(&cci->slave[2].snoop_ctrl,
+ CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
+ out_le32(&cci->slave[4].snoop_ctrl,
+ CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN);
+
+ major = in_be32(&gur->svr);
+ if (SVR_MAJ(major) == SOC_MAJOR_VER_1_0) {
+ /*
+ * Set CCI-400 Slave interface S1, S2 Shareable Override
+ * Register All transactions are treated as non-shareable
+ */
+ out_le32(&cci->slave[1].sha_ord, CCI400_SHAORD_NON_SHAREABLE);
+ out_le32(&cci->slave[2].sha_ord, CCI400_SHAORD_NON_SHAREABLE);
+ }
+
+ /*
+ * Memory controller require a register write before being enabled.
+ * Affects: DDR
+ * Register: EDDRTQCFG
+ * Description: Memory controller performance is not optimal with
+ * default internal target queue register values.
+ * Workaround: Write a value of 63b2_0042h to address: 157_020Ch.
+ */
+ out_be32(&scfg->eddrtqcfg, 0x63b20042);
+
+ ls1021a_errata();
+}
diff --git a/arch/arm/mach-layerscape/lowlevel-ls1046a.c b/arch/arm/mach-layerscape/lowlevel-ls1046a.c
index 32f825ec25..1307c05eaf 100644
--- a/arch/arm/mach-layerscape/lowlevel-ls1046a.c
+++ b/arch/arm/mach-layerscape/lowlevel-ls1046a.c
@@ -3,10 +3,11 @@
#include <io.h>
#include <asm/syscounter.h>
#include <asm/system.h>
-#include <mach/errata.h>
-#include <mach/lowlevel.h>
+#include <mach/layerscape/errata.h>
+#include <mach/layerscape/lowlevel.h>
#include <soc/fsl/immap_lsch2.h>
#include <soc/fsl/fsl_immap.h>
+#include <soc/fsl/scfg.h>
enum csu_cslx_access {
CSU_NS_SUP_R = 0x08,
@@ -222,16 +223,19 @@ void ls1046a_init_lowlevel(void)
struct ccsr_cci400 __iomem *cci = IOMEM(LSCH2_CCI400_ADDR);
struct ccsr_scfg *scfg = IOMEM(LSCH2_SCFG_ADDR);
+ scfg_init(SCFG_ENDIANESS_BIG);
init_csu();
ls1046a_init_l2_latency();
set_cntfrq(25000000);
syscnt_enable(IOMEM(LSCH2_SYS_COUNTER_ADDR));
- /* Make SEC reads and writes snoopable */
+ /* Make DMA master reads and writes snoopable */
setbits_be32(&scfg->snpcnfgcr, SCFG_SNPCNFGCR_SECRDSNP |
- SCFG_SNPCNFGCR_SECWRSNP |
- SCFG_SNPCNFGCR_SATARDSNP |
- SCFG_SNPCNFGCR_SATAWRSNP);
+ SCFG_SNPCNFGCR_SECWRSNP | SCFG_SNPCNFGCR_USB1RDSNP |
+ SCFG_SNPCNFGCR_USB1WRSNP | SCFG_SNPCNFGCR_USB2RDSNP |
+ SCFG_SNPCNFGCR_USB2WRSNP | SCFG_SNPCNFGCR_USB3RDSNP |
+ SCFG_SNPCNFGCR_USB3WRSNP | SCFG_SNPCNFGCR_SATARDSNP |
+ SCFG_SNPCNFGCR_SATAWRSNP | SCFG_SNPCNFGCR_EDMASNP);
/*
* Enable snoop requests and DVM message requests for
diff --git a/arch/arm/mach-layerscape/lowlevel.S b/arch/arm/mach-layerscape/lowlevel.S
index adb3e54367..e8e6410c52 100644
--- a/arch/arm/mach-layerscape/lowlevel.S
+++ b/arch/arm/mach-layerscape/lowlevel.S
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#include <linux/linkage.h>
.section .text.ls1046a_init_l2_latency
diff --git a/arch/arm/mach-layerscape/ls102xa_stream_id.c b/arch/arm/mach-layerscape/ls102xa_stream_id.c
new file mode 100644
index 0000000000..fd9be35c1d
--- /dev/null
+++ b/arch/arm/mach-layerscape/ls102xa_stream_id.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2014 Freescale Semiconductor
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <soc/fsl/immap_lsch2.h>
+#include <mach/layerscape/layerscape.h>
+
+struct smmu_stream_id {
+ uint16_t offset;
+ uint16_t stream_id;
+ char dev_name[32];
+};
+
+static struct smmu_stream_id dev_stream_id[] = {
+ { 0x100, 0x01, "ETSEC MAC1" },
+ { 0x104, 0x02, "ETSEC MAC2" },
+ { 0x108, 0x03, "ETSEC MAC3" },
+ { 0x10c, 0x04, "PEX1" },
+ { 0x110, 0x05, "PEX2" },
+ { 0x114, 0x06, "qDMA" },
+ { 0x118, 0x07, "SATA" },
+ { 0x11c, 0x08, "USB3" },
+ { 0x120, 0x09, "QE" },
+ { 0x124, 0x0a, "eSDHC" },
+ { 0x128, 0x0b, "eMA" },
+ { 0x14c, 0x0c, "2D-ACE" },
+ { 0x150, 0x0d, "USB2" },
+ { 0x18c, 0x0e, "DEBUG" },
+};
+
+static void
+ls102xa_config_smmu_stream_id(struct smmu_stream_id *id, uint32_t num)
+{
+ void *scfg = (void *)LSCH2_SCFG_ADDR;
+ int i;
+ u32 icid;
+
+ for (i = 0; i < num; i++) {
+ icid = (id[i].stream_id & 0xff) << 24;
+ out_be32((u32 *)(scfg + id[i].offset), icid);
+ }
+}
+
+void ls102xa_smmu_stream_id_init(void)
+{
+ ls102xa_config_smmu_stream_id(dev_stream_id, ARRAY_SIZE(dev_stream_id));
+}
diff --git a/arch/arm/mach-layerscape/pblimage.c b/arch/arm/mach-layerscape/pblimage.c
index deaf7143b9..5a525f0933 100644
--- a/arch/arm/mach-layerscape/pblimage.c
+++ b/arch/arm/mach-layerscape/pblimage.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#define pr_fmt(fmt) "pblimage: " fmt
#include <bootm.h>
@@ -5,6 +7,7 @@
#include <init.h>
#include <memory.h>
#include <linux/sizes.h>
+#include <mach/layerscape/layerscape.h>
#define BAREBOX_STAGE2_OFFSET SZ_128K
@@ -48,11 +51,8 @@ static struct image_handler image_handler_layerscape_qspi_pbl_image = {
.filetype = filetype_layerscape_qspi_image,
};
-static int layerscape_register_pbl_image_handler(void)
+void layerscape_register_pbl_image_handler(void)
{
register_image_handler(&image_handler_layerscape_pbl_image);
register_image_handler(&image_handler_layerscape_qspi_pbl_image);
-
- return 0;
}
-late_initcall(layerscape_register_pbl_image_handler);
diff --git a/arch/arm/mach-layerscape/ppa-entry.S b/arch/arm/mach-layerscape/ppa-entry.S
index 18cfa6c37e..f5f30b6719 100644
--- a/arch/arm/mach-layerscape/ppa-entry.S
+++ b/arch/arm/mach-layerscape/ppa-entry.S
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#include <linux/linkage.h>
.section .text.ppa_entry
diff --git a/arch/arm/mach-layerscape/ppa.c b/arch/arm/mach-layerscape/ppa.c
index d962fba751..21efaae3ab 100644
--- a/arch/arm/mach-layerscape/ppa.c
+++ b/arch/arm/mach-layerscape/ppa.c
@@ -4,6 +4,7 @@
#include <common.h>
#include <init.h>
+#include <mmu.h>
#include <firmware.h>
#include <memory.h>
#include <linux/sizes.h>
@@ -13,7 +14,7 @@
#include <asm/system.h>
#include <image-fit.h>
#include <asm/psci.h>
-#include <mach/layerscape.h>
+#include <mach/layerscape/layerscape.h>
#include <asm/cache.h>
int ppa_entry(const void *, u32 *, u32 *);
@@ -46,7 +47,7 @@ static int of_psci_do_fixup(struct device_node *root, void *unused)
break;
}
- return of_psci_fixup(root, psci_version);
+ return of_psci_fixup(root, psci_version, "smc");
}
static int ppa_init(void *ppa, size_t ppa_size, void *sec_firmware_addr)
@@ -54,17 +55,11 @@ static int ppa_init(void *ppa, size_t ppa_size, void *sec_firmware_addr)
int ret;
u32 *boot_loc_ptr_l, *boot_loc_ptr_h;
struct ccsr_scfg __iomem *scfg = (void *)(LSCH2_SCFG_ADDR);
- int el = current_el();
struct fit_handle *fit;
void *conf;
const void *buf;
unsigned long firmware_size;
- if (el < 3) {
- printf("EL%d, skip ppa init\n", el);
- return 0;
- }
-
boot_loc_ptr_l = &scfg->scratchrw[1];
boot_loc_ptr_h = &scfg->scratchrw[0];
@@ -115,9 +110,10 @@ int ls1046a_ppa_init(resource_size_t ppa_start, resource_size_t ppa_size)
struct resource *res;
void *ppa_fw;
size_t ppa_fw_size;
+ int el = current_el();
int ret;
- res = request_sdram_region("ppa", ppa_start, ppa_size);
+ res = reserve_sdram_region("ppa", ppa_start, ppa_size);
if (!res) {
pr_err("Cannot request SDRAM region %pa - %pa\n",
&ppa_start, &ppa_end);
@@ -126,11 +122,22 @@ int ls1046a_ppa_init(resource_size_t ppa_start, resource_size_t ppa_size)
get_builtin_firmware(ppa_ls1046a_bin, &ppa_fw, &ppa_fw_size);
- ret = ppa_init(ppa_fw, ppa_fw_size, (void *)ppa_start);
- if (ret)
- return ret;
+ if (el == 3) {
+ unsigned long cr;
+
+ asm volatile("mrs %0, sctlr_el3" : "=r" (cr) : : "cc");
+ remap_range((void *)ppa_start, ppa_size, MAP_CACHED);
+
+ ret = ppa_init(ppa_fw, ppa_fw_size, (void *)ppa_start);
+
+ asm volatile("msr sctlr_el2, %0" : : "r" (cr) : "cc");
+ remap_range((void *)ppa_start, ppa_size, MAP_UNCACHED);
+
+ if (ret)
+ return ret;
+ }
- of_add_reserve_entry(ppa_start, ppa_end);
+ of_register_fixup(of_fixup_reserved_memory, res);
return 0;
}
diff --git a/arch/arm/mach-layerscape/restart.c b/arch/arm/mach-layerscape/restart.c
new file mode 100644
index 0000000000..138a82bdb5
--- /dev/null
+++ b/arch/arm/mach-layerscape/restart.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <common.h>
+#include <init.h>
+#include <restart.h>
+#include <asm/io.h>
+#include <soc/fsl/immap_lsch2.h>
+#include <soc/fsl/fsl_immap.h>
+#include <mach/layerscape/layerscape.h>
+
+static void ls102xa_restart(struct restart_handler *rst)
+{
+ void __iomem *rcr = IOMEM(LSCH2_RST_ADDR);
+
+ /* Set RESET_REQ bit */
+ setbits_be32(rcr, 0x2);
+
+ mdelay(100);
+
+ hang();
+}
+
+void ls1021a_restart_register_feature(void)
+{
+ restart_handler_register_fn("soc-reset", ls102xa_restart);
+}
diff --git a/arch/arm/mach-layerscape/soc.c b/arch/arm/mach-layerscape/soc.c
new file mode 100644
index 0000000000..1742ff58ce
--- /dev/null
+++ b/arch/arm/mach-layerscape/soc.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <soc/fsl/scfg.h>
+#include <io.h>
+#include <init.h>
+#include <memory.h>
+#include <linux/bug.h>
+#include <linux/bitfield.h>
+#include <linux/printk.h>
+#include <mach/layerscape/layerscape.h>
+#include <of.h>
+#include <of_address.h>
+
+int __layerscape_soc_type;
+
+static enum scfg_endianess scfg_endianess = SCFG_ENDIANESS_INVALID;
+
+static void scfg_check_endianess(void)
+{
+ BUG_ON(scfg_endianess == SCFG_ENDIANESS_INVALID);
+}
+
+void scfg_clrsetbits32(void __iomem *addr, u32 clear, u32 set)
+{
+ scfg_check_endianess();
+
+ if (scfg_endianess == SCFG_ENDIANESS_LITTLE)
+ clrsetbits_le32(addr, clear, set);
+ else
+ clrsetbits_be32(addr, clear, set);
+}
+
+void scfg_clrbits32(void __iomem *addr, u32 clear)
+{
+ scfg_check_endianess();
+
+ if (scfg_endianess == SCFG_ENDIANESS_LITTLE)
+ clrbits_le32(addr, clear);
+ else
+ clrbits_be32(addr, clear);
+}
+
+void scfg_setbits32(void __iomem *addr, u32 set)
+{
+ scfg_check_endianess();
+
+ if (scfg_endianess == SCFG_ENDIANESS_LITTLE)
+ setbits_le32(addr, set);
+ else
+ setbits_be32(addr, set);
+}
+
+void scfg_out16(void __iomem *addr, u16 val)
+{
+ scfg_check_endianess();
+
+ if (scfg_endianess == SCFG_ENDIANESS_LITTLE)
+ out_le16(addr, val);
+ else
+ out_be16(addr, val);
+}
+
+void scfg_init(enum scfg_endianess endianess)
+{
+ scfg_endianess = endianess;
+}
+
+static int layerscape_soc_from_dt(void)
+{
+ if (of_machine_is_compatible("fsl,ls1021a"))
+ return LAYERSCAPE_SOC_LS1021A;
+ if (of_machine_is_compatible("fsl,ls1028a"))
+ return LAYERSCAPE_SOC_LS1028A;
+ if (of_machine_is_compatible("fsl,ls1046a"))
+ return LAYERSCAPE_SOC_LS1046A;
+
+ return 0;
+}
+
+static int ls1021a_init(void)
+{
+ if (!cpu_is_ls1021a())
+ return -EINVAL;
+
+ ls1021a_bootsource_init();
+ ls102xa_smmu_stream_id_init();
+ layerscape_register_pbl_image_handler();
+ ls1021a_restart_register_feature();
+
+ return 0;
+}
+
+static int ls1028a_init(void)
+{
+ if (!cpu_is_ls1028a())
+ return -EINVAL;
+
+ ls1028a_bootsource_init();
+ layerscape_register_pbl_image_handler();
+ ls1028a_setup_icids();
+
+ return 0;
+}
+
+static int ls1028a_reserve_tfa(void)
+{
+ resource_size_t tfa_start = LS1028A_TFA_RESERVED_START;
+ resource_size_t tfa_size = LS1028A_TFA_RESERVED_SIZE;
+ struct resource *res;
+
+ if (!cpu_is_ls1028a())
+ return 0;
+
+ res = reserve_sdram_region("tfa", tfa_start, tfa_size);
+ if (!res) {
+ pr_err("Cannot request SDRAM region %pa - %pa\n", &tfa_start, &tfa_size);
+ return -EINVAL;
+ }
+
+ of_register_fixup(of_fixup_reserved_memory, res);
+
+ return 0;
+}
+mmu_initcall(ls1028a_reserve_tfa);
+
+#define DWC3_GSBUSCFG0 0xc100
+#define DWC3_GSBUSCFG0_CACHETYPE_MASK GENMASK(31, 16)
+
+static void layerscape_usb_enable_snooping(void)
+{
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "snps,dwc3") {
+ struct resource res;
+
+ if (of_address_to_resource(np, 0, &res))
+ continue;
+
+ /* Set cacheable bit for all of Data read, Descriptor read,
+ * Data write and Descriptor write. Bufferable and read/write
+ * allocate bits are not set. This is the recommended configurationr
+ * in LS1046ARM Rev. 3 34.2.10.2:
+ * "For master interface DMA access, program the GSBUSCFG0
+ * register to 0x2222000F for better performance.".
+ * The 0x000F is configured via snps,incr-burst-type-adjustment
+ * (which despite the name is Layerscape-specific), so below
+ * line only manipulates the upper 16 bits.
+ */
+ clrsetbits_le32(IOMEM(res.start) + DWC3_GSBUSCFG0,
+ DWC3_GSBUSCFG0_CACHETYPE_MASK,
+ FIELD_PREP(DWC3_GSBUSCFG0_CACHETYPE_MASK, 0x2222));
+ }
+}
+
+static int ls1046a_init(void)
+{
+ if (!cpu_is_ls1046a())
+ return -EINVAL;
+
+ ls1046a_bootsource_init();
+ ls1046a_setup_icids();
+ layerscape_register_pbl_image_handler();
+ layerscape_usb_enable_snooping();
+
+ return 0;
+}
+
+static int layerscape_init(void)
+{
+ struct device_node *root;
+
+ root = of_get_root_node();
+ if (root) {
+ __layerscape_soc_type = layerscape_soc_from_dt();
+ if (!__layerscape_soc_type)
+ return 0;
+ }
+
+ switch (__layerscape_soc_type) {
+ case LAYERSCAPE_SOC_LS1021A:
+ return ls1021a_init();
+ case LAYERSCAPE_SOC_LS1028A:
+ return ls1028a_init();
+ case LAYERSCAPE_SOC_LS1046A:
+ return ls1046a_init();
+ }
+
+ return 0;
+}
+postcore_initcall(layerscape_init);
diff --git a/arch/arm/mach-layerscape/tzc400.c b/arch/arm/mach-layerscape/tzc400.c
new file mode 100644
index 0000000000..04a97809f5
--- /dev/null
+++ b/arch/arm/mach-layerscape/tzc400.c
@@ -0,0 +1,303 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
+ *
+ */
+#define pr_fmt(fmt) "tzc400: " fmt
+
+#include <common.h>
+#include <linux/bitfield.h>
+#include <linux/sizes.h>
+#include <mach/layerscape/lowlevel.h>
+#include <mach/layerscape/layerscape.h>
+
+#include "tzc400.h"
+
+static inline void mmio_write_32(uintptr_t addr, uint32_t value)
+{
+ out_le32(addr, value);
+}
+
+static inline uint32_t mmio_read_32(uintptr_t addr)
+{
+ return in_le32(addr);
+}
+
+static inline void mmio_clrsetbits_32(uintptr_t addr,
+ uint32_t clear,
+ uint32_t set)
+{
+ clrsetbits_le32(addr, clear, set);
+}
+
+static inline unsigned int tzc_read_peripheral_id(uintptr_t base)
+{
+ unsigned int id;
+
+ id = mmio_read_32(base + PID0_OFF);
+ /* Masks DESC part in PID1 */
+ id |= ((mmio_read_32(base + PID1_OFF) & 0xFU) << 8U);
+
+ return id;
+}
+
+/*
+ * Implementation defined values used to validate inputs later.
+ * Filters : max of 4 ; 0 to 3
+ * Regions : max of 9 ; 0 to 8
+ * Address width : Values between 32 to 64
+ */
+struct tzc400_instance {
+ uintptr_t base;
+ uint8_t addr_width;
+ uint8_t num_filters;
+ uint8_t num_regions;
+};
+
+static struct tzc400_instance tzc400;
+
+static inline unsigned int tzc400_read_gate_keeper(void)
+{
+ uintptr_t base = tzc400.base;
+
+ return mmio_read_32(base + TZC400_GATE_KEEPER);
+}
+
+static inline void tzc400_write_gate_keeper(unsigned int val)
+{
+ uintptr_t base = tzc400.base;
+
+ mmio_write_32(base + TZC400_GATE_KEEPER, val);
+}
+
+static unsigned int tzc400_open_status(void)
+{
+ return FIELD_GET(TZC400_GATE_KEEPER_OS, tzc400_read_gate_keeper());
+}
+
+static unsigned int tzc400_get_gate_keeper(unsigned int filter)
+{
+ return (tzc400_open_status() >> filter) & GATE_KEEPER_FILTER_MASK;
+}
+
+/* This function is not MP safe. */
+static void tzc400_set_gate_keeper(unsigned int filter, int val)
+{
+ unsigned int os;
+
+ /* Upper half is current state. Lower half is requested state. */
+ os = tzc400_open_status();
+
+ if (val != 0)
+ os |= (1UL << filter);
+ else
+ os &= ~(1UL << filter);
+
+ tzc400_write_gate_keeper(FIELD_PREP(TZC400_GATE_KEEPER_OR, os));
+
+ /* Wait here until we see the change reflected in the TZC status. */
+ while ((tzc400_open_status()) != os)
+ ;
+}
+
+void tzc400_set_action(unsigned int action)
+{
+ uintptr_t base = tzc400.base;
+
+ ASSERT(base != 0U);
+ ASSERT(action <= TZC_ACTION_ERR_INT);
+
+ mmio_write_32(base + TZC400_ACTION, action);
+}
+
+void tzc400_init(uintptr_t base)
+{
+ unsigned int tzc400_id;
+ unsigned int tzc400_build;
+
+ tzc400.base = base;
+
+ tzc400_id = tzc_read_peripheral_id(base);
+ if (tzc400_id != TZC400_PERIPHERAL_ID)
+ panic("TZC-400 : Wrong device ID (0x%x).\n", tzc400_id);
+
+ /* Save values we will use later. */
+ tzc400_build = mmio_read_32(base + TZC400_BUILD_CONFIG);
+ tzc400.num_filters = FIELD_GET(TZC400_BUILD_CONFIG_NF, tzc400_build) + 1;
+ tzc400.addr_width = FIELD_GET(TZC400_BUILD_CONFIG_AW, tzc400_build) + 1;
+ tzc400.num_regions = FIELD_GET(TZC400_BUILD_CONFIG_NR, tzc400_build) + 1;
+}
+
+/*
+ * `tzc400_configure_region` is used to program regions into the TrustZone
+ * controller. A region can be associated with more than one filter. The
+ * associated filters are passed in as a bitmap (bit0 = filter0), except that
+ * the value TZC400_REGION_ATTR_FILTER_BIT_ALL selects all filters, based on
+ * the value of tzc400.num_filters.
+ * NOTE:
+ * Region 0 is special; it is preferable to use tzc400_configure_region0
+ * for this region (see comment for that function).
+ */
+void tzc400_configure_region(unsigned int filters, unsigned int region, uint64_t region_base,
+ uint64_t region_top, unsigned int sec_attr,
+ unsigned int nsaid_permissions)
+{
+ uintptr_t rbase = tzc400.base + TZC_REGION_OFFSET(TZC400_REGION_SIZE, region);
+
+ /* Adjust filter mask by real filter number */
+ if (filters == TZC400_REGION_ATTR_FILTER_BIT_ALL)
+ filters = (1U << tzc400.num_filters) - 1U;
+
+ /* Do range checks on filters and regions. */
+ ASSERT(((filters >> tzc400.num_filters) == 0U) &&
+ (region < tzc400.num_regions));
+
+ /*
+ * Do address range check based on TZC configuration. A 64bit address is
+ * the max and expected case.
+ */
+ ASSERT((region_top <= (U64_MAX >> (64U - tzc400.addr_width))) &&
+ (region_base < region_top));
+
+ /* region_base and (region_top + 1) must be 4KB aligned */
+ ASSERT(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U);
+
+ ASSERT(sec_attr <= TZC_REGION_S_RDWR);
+
+ pr_debug("TrustZone : Configuring region %u\n", region);
+ pr_debug("TrustZone : ... base = %llx, top = %llx,\n", region_base, region_top);
+ pr_debug("TrustZone : ... sec_attr = 0x%x, ns_devs = 0x%x)\n",
+ sec_attr, nsaid_permissions);
+
+ /***************************************************/
+ /* Inputs look ok, start programming registers. */
+ /* All the address registers are 32 bits wide and */
+ /* have a LOW and HIGH */
+ /* component used to construct an address up to a */
+ /* 64bit. */
+ /***************************************************/
+ mmio_write_32(rbase + TZC400_REGION_BASE_LOW_0, (uint32_t)region_base);
+ mmio_write_32(rbase + TZC400_REGION_BASE_HIGH_0, (uint32_t)(region_base >> 32));
+ mmio_write_32(rbase + TZC400_REGION_TOP_LOW_0, (uint32_t)region_top);
+ mmio_write_32(rbase + TZC400_REGION_TOP_HIGH_0, (uint32_t)(region_top >> 32));
+
+ /* Enable filter to the region and set secure attributes */
+ mmio_write_32(rbase + TZC400_REGION_ATTR_0,
+ (sec_attr << TZC_REGION_ATTR_SEC_SHIFT) | (filters << TZC_REGION_ATTR_F_EN_SHIFT));
+
+ /***************************************************/
+ /* Specify which non-secure devices have permission*/
+ /* to access this region. */
+ /***************************************************/
+ mmio_write_32(rbase + TZC400_REGION_ID_ACCESS_0, nsaid_permissions);
+}
+
+void tzc400_update_filters(unsigned int region, unsigned int filters)
+{
+ uintptr_t rbase = tzc400.base + TZC_REGION_OFFSET(TZC400_REGION_SIZE, region);
+ uint32_t filters_mask = GENMASK(tzc400.num_filters - 1U, 0);
+
+ /* Do range checks on filters and regions. */
+ ASSERT(((filters >> tzc400.num_filters) == 0U) &&
+ (region < tzc400.num_regions));
+
+ mmio_clrsetbits_32(rbase + TZC400_REGION_ATTR_0,
+ filters_mask << TZC_REGION_ATTR_F_EN_SHIFT,
+ filters << TZC_REGION_ATTR_F_EN_SHIFT);
+}
+
+void tzc400_enable_filters(void)
+{
+ unsigned int state;
+ unsigned int filter;
+
+ ASSERT(tzc400.base != 0U);
+
+ for (filter = 0U; filter < tzc400.num_filters; filter++) {
+ state = tzc400_get_gate_keeper(filter);
+ if (state != 0U) {
+ /* Filter 0 is special and cannot be disabled.
+ * So here we allow it being already enabled. */
+ if (filter == 0U)
+ continue;
+
+ /*
+ * The TZC filter is already configured. Changing the
+ * programmer's view in an active system can cause
+ * unpredictable behavior therefore panic for now rather
+ * than try to determine whether this is safe in this
+ * instance.
+ *
+ * See the 'ARM (R) CoreLink TM TZC-400 TrustZone (R)
+ * Address Space Controller' Technical Reference Manual.
+ */
+ panic("TZC-400 : Filter %u Gatekeeper already enabled.\n",
+ filter);
+ }
+ tzc400_set_gate_keeper(filter, 1);
+ }
+}
+
+void tzc400_disable_filters(void)
+{
+ unsigned int filter;
+ unsigned int state;
+ unsigned int start = 0U;
+
+ ASSERT(tzc400.base != 0U);
+
+ /* Filter 0 is special and cannot be disabled. */
+ state = tzc400_get_gate_keeper(0);
+ if (state != 0U)
+ start++;
+
+ for (filter = start; filter < tzc400.num_filters; filter++)
+ tzc400_set_gate_keeper(filter, 0);
+}
+
+unsigned long ls1028a_tzc400_init(unsigned long memsize)
+{
+ unsigned long lowmem, highmem, lowmem_end;
+
+ tzc400_init(LS1028A_TZC400_BASE);
+ tzc400_disable_filters();
+
+ /* Region 0 set to no access by default */
+ mmio_write_32(tzc400.base + TZC400_REGION_ATTR_0, TZC_REGION_S_NONE << TZC_REGION_ATTR_SEC_SHIFT);
+ mmio_write_32(tzc400.base + TZC400_REGION_ID_ACCESS_0, 0);
+
+ lowmem = min_t(unsigned long, LS1028A_DDR_SDRAM_LOWMEM_SIZE, memsize);
+ lowmem_end = LS1028A_DDR_SDRAM_BASE + lowmem;
+ highmem = memsize - lowmem;
+
+ /* region 1: secure memory */
+ tzc400_configure_region(1, 1,
+ lowmem_end - LS1028A_SECURE_DRAM_SIZE,
+ lowmem_end - 1,
+ TZC_REGION_S_RDWR, TZC_REGION_NS_NONE);
+
+ /* region 2: shared memory */
+ tzc400_configure_region(1, 2,
+ lowmem_end - LS1028A_SECURE_DRAM_SIZE - LS1028A_SP_SHARED_DRAM_SIZE,
+ lowmem_end - LS1028A_SECURE_DRAM_SIZE - 1,
+ TZC_REGION_S_RDWR, TZC_NS_ACCESS_ID);
+
+ /* region 3: nonsecure low memory */
+ tzc400_configure_region(1, 3,
+ LS1028A_DDR_SDRAM_BASE,
+ lowmem_end - LS1028A_SECURE_DRAM_SIZE - LS1028A_SP_SHARED_DRAM_SIZE - 1,
+ TZC_REGION_S_RDWR, TZC_NS_ACCESS_ID);
+
+ if (highmem)
+ /* nonsecure high memory */
+ tzc400_configure_region(1, 4,
+ LS1028A_DDR_SDRAM_HIGHMEM_BASE,
+ LS1028A_DDR_SDRAM_HIGHMEM_BASE + highmem - 1,
+ TZC_REGION_S_RDWR, TZC_NS_ACCESS_ID);
+
+ tzc400_set_action(TZC_ACTION_ERR);
+
+ tzc400_enable_filters();
+
+ return lowmem - LS1028A_SECURE_DRAM_SIZE - LS1028A_SP_SHARED_DRAM_SIZE;
+}
diff --git a/arch/arm/mach-layerscape/tzc400.h b/arch/arm/mach-layerscape/tzc400.h
new file mode 100644
index 0000000000..c8d4583622
--- /dev/null
+++ b/arch/arm/mach-layerscape/tzc400.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TZC400_H
+#define TZC400_H
+
+#include <linux/bits.h>
+
+/*
+ * Offset of core registers from the start of the base of configuration
+ * registers for each region.
+ */
+
+/* ID Registers */
+#define PID0_OFF 0xfe0
+#define PID1_OFF 0xfe4
+#define PID2_OFF 0xfe8
+#define PID3_OFF 0xfec
+#define PID4_OFF 0xfd0
+#define CID0_OFF 0xff0
+#define CID1_OFF 0xff4
+#define CID2_OFF 0xff8
+#define CID3_OFF 0xffc
+
+/*
+ * What type of action is expected when an access violation occurs.
+ * The memory requested is returned as zero. But we can also raise an event to
+ * let the system know it happened.
+ * We can raise an interrupt(INT) and/or cause an exception(ERR).
+ * TZC_ACTION_NONE - No interrupt, no Exception
+ * TZC_ACTION_ERR - No interrupt, raise exception -> sync external
+ * data abort
+ * TZC_ACTION_INT - Raise interrupt, no exception
+ * TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync
+ * external data abort
+ */
+#define TZC_ACTION_NONE 0
+#define TZC_ACTION_ERR 1
+#define TZC_ACTION_INT 2
+#define TZC_ACTION_ERR_INT (TZC_ACTION_ERR | TZC_ACTION_INT)
+
+/* Bit positions of TZC_ACTION registers */
+#define TZC_ACTION_RV_SHIFT 0
+#define TZC_ACTION_RV_MASK 0x3
+#define TZC_ACTION_RV_LOWOK 0x0
+#define TZC_ACTION_RV_LOWERR 0x1
+#define TZC_ACTION_RV_HIGHOK 0x2
+#define TZC_ACTION_RV_HIGHERR 0x3
+
+/*
+ * Controls secure access to a region. If not enabled secure access is not
+ * allowed to region.
+ */
+#define TZC_REGION_S_NONE 0
+#define TZC_REGION_S_RD 1
+#define TZC_REGION_S_WR 2
+#define TZC_REGION_S_RDWR (TZC_REGION_S_RD | TZC_REGION_S_WR)
+
+#define TZC_REGION_ATTR_S_RD_SHIFT 30
+#define TZC_REGION_ATTR_S_WR_SHIFT 31
+#define TZC_REGION_ATTR_F_EN_SHIFT 0
+#define TZC_REGION_ATTR_SEC_SHIFT 30
+#define TZC_REGION_ATTR_S_RD_MASK 0x1
+#define TZC_REGION_ATTR_S_WR_MASK 0x1
+#define TZC_REGION_ATTR_SEC_MASK 0x3
+
+#define TZC_REGION_ACCESS_WR_EN_SHIFT 16
+#define TZC_REGION_ACCESS_RD_EN_SHIFT 0
+#define TZC_REGION_ACCESS_ID_MASK 0xf
+
+/* Macros for allowing Non-Secure access to a region based on NSAID */
+#define TZC_REGION_ACCESS_RD(nsaid) \
+ ((U(1) << ((nsaid) & TZC_REGION_ACCESS_ID_MASK)) << \
+ TZC_REGION_ACCESS_RD_EN_SHIFT)
+#define TZC_REGION_ACCESS_WR(nsaid) \
+ ((U(1) << ((nsaid) & TZC_REGION_ACCESS_ID_MASK)) << \
+ TZC_REGION_ACCESS_WR_EN_SHIFT)
+#define TZC_REGION_ACCESS_RDWR(nsaid) \
+ (TZC_REGION_ACCESS_RD(nsaid) | \
+ TZC_REGION_ACCESS_WR(nsaid))
+
+/* Returns offset of registers to program for a given region no */
+#define TZC_REGION_OFFSET(region_size, region_no) \
+ ((region_size) * (region_no))
+
+#define TZC400_BUILD_CONFIG 0x000
+#define TZC400_GATE_KEEPER 0x008
+#define TZC400_SPECULATION_CTRL 0x00c
+#define TZC400_INT_STATUS 0x010
+#define TZC400_INT_CLEAR 0x014
+
+#define TZC400_FAIL_ADDRESS_LOW 0x020
+#define TZC400_FAIL_ADDRESS_HIGH 0x024
+#define TZC400_FAIL_CONTROL 0x028
+#define TZC400_FAIL_ID 0x02c
+
+#define TZC400_BUILD_CONFIG_NF GENMASK(25, 24)
+#define TZC400_BUILD_CONFIG_AW GENMASK(13, 8)
+#define TZC400_BUILD_CONFIG_NR GENMASK(4, 0)
+
+/*
+ * Number of gate keepers is implementation defined. But we know the max for
+ * this device is 4. Get implementation details from BUILD_CONFIG.
+ */
+#define TZC400_GATE_KEEPER_OS GENMASK(19, 16)
+#define TZC400_GATE_KEEPER_OR GENMASK(3, 0)
+#define GATE_KEEPER_FILTER_MASK 0x1
+
+#define TZC400_FAIL_CONTROL_DIR_WRITE BIT(24)
+#define TZC400_FAIL_CONTROL_NS_NONSECURE BIT(21)
+#define TZC400_FAIL_CONTROL_PRIV BIT(20)
+
+#define TZC400_PERIPHERAL_ID 0x460
+
+/* Filter enable bits in a TZC */
+#define TZC400_REGION_ATTR_F_EN_MASK 0xf
+#define TZC400_REGION_ATTR_FILTER_BIT(x) (1) << (x))
+#define TZC400_REGION_ATTR_FILTER_BIT_ALL TZC400_REGION_ATTR_F_EN_MASK
+
+/*
+ * All TZC region configuration registers are placed one after another. It
+ * depicts size of block of registers for programming each region.
+ */
+#define TZC400_REGION_SIZE 0x20
+#define TZC400_ACTION 0x4
+
+#define FILTER_OFFSET 0x10
+
+#define TZC400_REGION_BASE_LOW_0 0x100
+#define TZC400_REGION_BASE_HIGH_0 0x104
+#define TZC400_REGION_TOP_LOW_0 0x108
+#define TZC400_REGION_TOP_HIGH_0 0x10c
+#define TZC400_REGION_ATTR_0 0x110
+#define TZC400_REGION_ID_ACCESS_0 0x114
+
+#define TZC_REGION_NS_NONE 0x00000000U
+
+/*
+ * NXP Platforms do not support NS Access ID (NSAID) based non-secure access.
+ * Supports only non secure through generic NS ACCESS ID
+ */
+#define TZC_NS_ACCESS_ID 0xFFFFFFFFU
+
+/*******************************************************************************
+ * Function & variable prototypes
+ ******************************************************************************/
+void tzc400_init(uintptr_t base);
+void tzc400_configure_region0(unsigned int sec_attr,
+ unsigned int ns_device_access);
+void tzc400_configure_region(unsigned int filters,
+ unsigned int region,
+ unsigned long long region_base,
+ unsigned long long region_top,
+ unsigned int sec_attr,
+ unsigned int nsaid_permissions);
+void tzc400_update_filters(unsigned int region, unsigned int filters);
+void tzc400_set_action(unsigned int action);
+void tzc400_enable_filters(void);
+void tzc400_disable_filters(void);
+
+#endif /* TZC400_H */
diff --git a/arch/arm/mach-layerscape/xload-qspi.c b/arch/arm/mach-layerscape/xload-qspi.c
index 192aea64b4..608434bf1f 100644
--- a/arch/arm/mach-layerscape/xload-qspi.c
+++ b/arch/arm/mach-layerscape/xload-qspi.c
@@ -4,8 +4,8 @@
#include <soc/fsl/immap_lsch2.h>
#include <asm-generic/sections.h>
#include <asm/cache.h>
-#include <mach/xload.h>
-#include <mach/layerscape.h>
+#include <mach/layerscape/xload.h>
+#include <mach/layerscape/layerscape.h>
/*
* The offset of the 2nd stage image in the output file. This must match with the
@@ -13,18 +13,21 @@
*/
#define BAREBOX_START (128 * 1024)
-int ls1046a_qspi_start_image(unsigned long r0, unsigned long r1,
- unsigned long r2)
+struct layerscape_base_addr {
+ void *qspi_reg_base;
+ void *membase;
+ void *qspi_mem_base;
+};
+
+static int layerscape_qspi_start_image(struct layerscape_base_addr *base,
+ unsigned long r0, unsigned long r1, unsigned long r2)
{
- void *qspi_reg_base = IOMEM(LSCH2_QSPI0_BASE_ADDR);
- void *membase = (void *)LS1046A_DDR_SDRAM_BASE;
- void *qspi_mem_base = IOMEM(0x40000000);
- void (*barebox)(unsigned long, unsigned long, unsigned long) = membase;
+ void (*barebox)(unsigned long, unsigned long, unsigned long) = base->membase;
/* Switch controller into little endian mode */
- out_be32(qspi_reg_base, 0x000f400c);
+ out_be32(base->qspi_reg_base, 0x000f400c);
- memcpy(membase, qspi_mem_base + BAREBOX_START, barebox_image_size);
+ memcpy(base->membase, base->qspi_mem_base + BAREBOX_START, barebox_image_size);
sync_caches_for_execution();
@@ -36,3 +39,27 @@ int ls1046a_qspi_start_image(unsigned long r0, unsigned long r1,
return -EIO;
}
+
+int ls1046a_qspi_start_image(unsigned long r0, unsigned long r1,
+ unsigned long r2)
+{
+ struct layerscape_base_addr base;
+
+ base.qspi_reg_base = IOMEM(LSCH2_QSPI0_BASE_ADDR);
+ base.membase = IOMEM(LS1046A_DDR_SDRAM_BASE);
+ base.qspi_mem_base = IOMEM(0x40000000);
+
+ return layerscape_qspi_start_image(&base, r0, r1, r2);
+}
+
+int ls1021a_qspi_start_image(unsigned long r0, unsigned long r1,
+ unsigned long r2)
+{
+ struct layerscape_base_addr base;
+
+ base.qspi_reg_base = IOMEM(LSCH2_QSPI0_BASE_ADDR);
+ base.membase = IOMEM(LS1021A_DDR_SDRAM_BASE);
+ base.qspi_mem_base = IOMEM(0x40000000);
+
+ return layerscape_qspi_start_image(&base, r0, r1, r2);
+}
diff --git a/arch/arm/mach-layerscape/xload.c b/arch/arm/mach-layerscape/xload.c
index 54495d7f97..32ff158b1b 100644
--- a/arch/arm/mach-layerscape/xload.c
+++ b/arch/arm/mach-layerscape/xload.c
@@ -2,21 +2,39 @@
#include <common.h>
#include <bootsource.h>
-#include <mach/layerscape.h>
-#include <mach/xload.h>
+#include <mach/layerscape/layerscape.h>
+#include <mach/layerscape/xload.h>
int ls1046a_xload_start_image(unsigned long r0, unsigned long r1,
unsigned long r2)
{
enum bootsource src;
- src = ls1046_bootsource_get();
+ src = ls1046a_bootsource_get();
switch (src) {
case BOOTSOURCE_SPI_NOR:
return ls1046a_qspi_start_image(r0, r1, r2);
+#if defined(CONFIG_MCI_IMX_ESDHC_PBL)
case BOOTSOURCE_MMC:
return ls1046a_esdhc_start_image(r0, r1, r2);
+#endif
+ default:
+ pr_err("Unknown bootsource\n");
+ return -EINVAL;
+ }
+}
+
+int ls1021a_xload_start_image(unsigned long r0, unsigned long r1,
+ unsigned long r2)
+{
+ enum bootsource src;
+
+ src = ls1021a_bootsource_get();
+
+ switch (src) {
+ case BOOTSOURCE_SPI_NOR:
+ return ls1021a_qspi_start_image(r0, r1, r2);
default:
pr_err("Unknown bootsource\n");
return -EINVAL;