@@ -81,6 +81,13 @@
#define CTRL_BLOCK 0x7
#define CTRL_DISABLE 0x0
+#define CFG_LRU 0x1
+#define CFG_QOS(n) ((n & 0xF) << 7)
+#define CFG_MASK 0x0150FFFF /* Selecting bit 0-15, 20, 22 and 24 */
+#define CFG_ACGEN (1 << 24) /* System MMU 3.3 only */
+#define CFG_SYSSEL (1 << 22) /* System MMU 3.2 only */
+#define CFG_FLPDCACHE (1 << 20) /* System MMU 3.2+ only */
+
#define REG_MMU_CTRL 0x000
#define REG_MMU_CFG 0x004
#define REG_MMU_STATUS 0x008
@@ -97,6 +104,12 @@
#define REG_MMU_VERSION 0x034
+#define MMU_MAJ_VER(val) ((val) >> 7)
+#define MMU_MIN_VER(val) ((val) & 0x7F)
+#define MMU_RAW_VER(reg) (((reg) >> 21) & ((1 << 11) - 1)) /* 11 bits */
+
+#define MAKE_MMU_VER(maj, min) ((((maj) & 0xF) << 7) | ((min) & 0x7F))
+
#define REG_PB0_SADDR 0x04C
#define REG_PB0_EADDR 0x050
#define REG_PB1_SADDR 0x054
@@ -206,6 +219,29 @@ static void sysmmu_unblock(void __iomem *sfrbase)
__raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL);
}
+static unsigned int __raw_sysmmu_version(struct sysmmu_drvdata *data)
+{
+ return MMU_RAW_VER(__raw_readl(data->sfrbase + REG_MMU_VERSION));
+}
+
+static unsigned int __sysmmu_version(struct sysmmu_drvdata *data,
+ unsigned int *minor)
+{
+ unsigned int ver = 0;
+
+ ver = __raw_sysmmu_version(data);
+ if (ver > MAKE_MMU_VER(3, 3)) {
+ dev_err(data->sysmmu, "%s: version(%d.%d) is higher than 3.3\n",
+ __func__, MMU_MAJ_VER(ver), MMU_MIN_VER(ver));
+ BUG();
+ }
+
+ if (minor)
+ *minor = MMU_MIN_VER(ver);
+
+ return MMU_MAJ_VER(ver);
+}
+
static bool sysmmu_block(void __iomem *sfrbase)
{
int i = 120;
@@ -360,7 +396,21 @@ static bool __sysmmu_disable(struct sysmmu_drvdata *data)
static void __sysmmu_init_config(struct sysmmu_drvdata *data)
{
- unsigned long cfg = 0;
+ unsigned long cfg = CFG_LRU | CFG_QOS(15);
+ int maj, min = 0;
+
+ maj = __sysmmu_version(data, &min);
+ if (maj == 3) {
+ if (min >= 2) {
+ cfg |= CFG_FLPDCACHE;
+ if (min == 3) {
+ cfg |= CFG_ACGEN;
+ cfg &= ~CFG_LRU;
+ } else {
+ cfg |= CFG_SYSSEL;
+ }
+ }
+ }
__raw_writel(cfg, data->sfrbase + REG_MMU_CFG);
}