summaryrefslogtreecommitdiffstats
path: root/arch/arm/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mm')
-rw-r--r--arch/arm/mm/Kconfig4
-rw-r--r--arch/arm/mm/cache-l2x0.c34
-rw-r--r--arch/arm/mm/cache-v7.S6
-rw-r--r--arch/arm/mm/dma-mapping.c63
-rw-r--r--arch/arm/mm/mmu.c2
-rw-r--r--arch/arm/mm/proc-v7.S71
6 files changed, 144 insertions, 36 deletions
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 94186b6c685..3fd629d5a51 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -352,6 +352,10 @@ config CPU_PJ4
select ARM_THUMBEE
select CPU_V7
+config CPU_PJ4B
+ bool
+ select CPU_V7
+
# ARMv6
config CPU_V6
bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 6911b8b2745..c2f37390308 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -352,7 +352,8 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
/* Unmapped register. */
sync_reg_offset = L2X0_DUMMY_REG;
#endif
- outer_cache.set_debug = pl310_set_debug;
+ if ((cache_id & L2X0_CACHE_ID_RTL_MASK) <= L2X0_CACHE_ID_RTL_R3P0)
+ outer_cache.set_debug = pl310_set_debug;
break;
case L2X0_CACHE_ID_PART_L210:
ways = (aux >> 13) & 0xf;
@@ -459,8 +460,8 @@ static void aurora_pa_range(unsigned long start, unsigned long end,
unsigned long flags;
raw_spin_lock_irqsave(&l2x0_lock, flags);
- writel(start, l2x0_base + AURORA_RANGE_BASE_ADDR_REG);
- writel(end, l2x0_base + offset);
+ writel_relaxed(start, l2x0_base + AURORA_RANGE_BASE_ADDR_REG);
+ writel_relaxed(end, l2x0_base + offset);
raw_spin_unlock_irqrestore(&l2x0_lock, flags);
cache_sync();
@@ -505,15 +506,21 @@ static void aurora_clean_range(unsigned long start, unsigned long end)
static void aurora_flush_range(unsigned long start, unsigned long end)
{
- if (!l2_wt_override) {
- start &= ~(CACHE_LINE_SIZE - 1);
- end = ALIGN(end, CACHE_LINE_SIZE);
- while (start != end) {
- unsigned long range_end = calc_range_end(start, end);
+ start &= ~(CACHE_LINE_SIZE - 1);
+ end = ALIGN(end, CACHE_LINE_SIZE);
+ while (start != end) {
+ unsigned long range_end = calc_range_end(start, end);
+ /*
+ * If L2 is forced to WT, the L2 will always be clean and we
+ * just need to invalidate.
+ */
+ if (l2_wt_override)
aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
- AURORA_FLUSH_RANGE_REG);
- start = range_end;
- }
+ AURORA_INVAL_RANGE_REG);
+ else
+ aurora_pa_range(start, range_end - CACHE_LINE_SIZE,
+ AURORA_FLUSH_RANGE_REG);
+ start = range_end;
}
}
@@ -668,8 +675,9 @@ static void pl310_resume(void)
static void aurora_resume(void)
{
if (!(readl(l2x0_base + L2X0_CTRL) & L2X0_CTRL_EN)) {
- writel(l2x0_saved_regs.aux_ctrl, l2x0_base + L2X0_AUX_CTRL);
- writel(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL);
+ writel_relaxed(l2x0_saved_regs.aux_ctrl,
+ l2x0_base + L2X0_AUX_CTRL);
+ writel_relaxed(l2x0_saved_regs.ctrl, l2x0_base + L2X0_CTRL);
}
}
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index cd956647c21..7539ec27506 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -44,8 +44,10 @@ ENDPROC(v7_flush_icache_all)
ENTRY(v7_flush_dcache_louis)
dmb @ ensure ordering with previous memory accesses
mrc p15, 1, r0, c0, c0, 1 @ read clidr, r0 = clidr
- ands r3, r0, #0xe00000 @ extract LoUIS from clidr
- mov r3, r3, lsr #20 @ r3 = LoUIS * 2
+ ALT_SMP(ands r3, r0, #(7 << 21)) @ extract LoUIS from clidr
+ ALT_UP(ands r3, r0, #(7 << 27)) @ extract LoUU from clidr
+ ALT_SMP(mov r3, r3, lsr #20) @ r3 = LoUIS * 2
+ ALT_UP(mov r3, r3, lsr #26) @ r3 = LoUU * 2
moveq pc, lr @ return if level == 0
mov r10, #0 @ r10 (starting level) = 0
b flush_levels @ start flushing cache levels
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 58bc3e4d3bd..076c26d4386 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -124,8 +124,6 @@ static void arm_dma_sync_single_for_device(struct device *dev,
__dma_page_cpu_to_dev(page, offset, size, dir);
}
-static int arm_dma_set_mask(struct device *dev, u64 dma_mask);
-
struct dma_map_ops arm_dma_ops = {
.alloc = arm_dma_alloc,
.free = arm_dma_free,
@@ -776,25 +774,27 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
size_t size, enum dma_data_direction dir,
void (*op)(const void *, size_t, int))
{
+ unsigned long pfn;
+ size_t left = size;
+
+ pfn = page_to_pfn(page) + offset / PAGE_SIZE;
+ offset %= PAGE_SIZE;
+
/*
* A single sg entry may refer to multiple physically contiguous
* pages. But we still need to process highmem pages individually.
* If highmem is not configured then the bulk of this loop gets
* optimized out.
*/
- size_t left = size;
do {
size_t len = left;
void *vaddr;
+ page = pfn_to_page(pfn);
+
if (PageHighMem(page)) {
- if (len + offset > PAGE_SIZE) {
- if (offset >= PAGE_SIZE) {
- page += offset / PAGE_SIZE;
- offset %= PAGE_SIZE;
- }
+ if (len + offset > PAGE_SIZE)
len = PAGE_SIZE - offset;
- }
vaddr = kmap_high_get(page);
if (vaddr) {
vaddr += offset;
@@ -811,7 +811,7 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
op(vaddr, len, dir);
}
offset = 0;
- page++;
+ pfn++;
left -= len;
} while (left);
}
@@ -971,7 +971,7 @@ int dma_supported(struct device *dev, u64 mask)
}
EXPORT_SYMBOL(dma_supported);
-static int arm_dma_set_mask(struct device *dev, u64 dma_mask)
+int arm_dma_set_mask(struct device *dev, u64 dma_mask)
{
if (!dev->dma_mask || !dma_supported(dev, dma_mask))
return -EIO;
@@ -1036,7 +1036,8 @@ static inline void __free_iova(struct dma_iommu_mapping *mapping,
spin_unlock_irqrestore(&mapping->lock, flags);
}
-static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t gfp)
+static struct page **__iommu_alloc_buffer(struct device *dev, size_t size,
+ gfp_t gfp, struct dma_attrs *attrs)
{
struct page **pages;
int count = size >> PAGE_SHIFT;
@@ -1050,6 +1051,23 @@ static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t
if (!pages)
return NULL;
+ if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs))
+ {
+ unsigned long order = get_order(size);
+ struct page *page;
+
+ page = dma_alloc_from_contiguous(dev, count, order);
+ if (!page)
+ goto error;
+
+ __dma_clear_buffer(page, size);
+
+ for (i = 0; i < count; i++)
+ pages[i] = page + i;
+
+ return pages;
+ }
+
while (count) {
int j, order = __fls(count);
@@ -1083,14 +1101,21 @@ error:
return NULL;
}
-static int __iommu_free_buffer(struct device *dev, struct page **pages, size_t size)
+static int __iommu_free_buffer(struct device *dev, struct page **pages,
+ size_t size, struct dma_attrs *attrs)
{
int count = size >> PAGE_SHIFT;
int array_size = count * sizeof(struct page *);
int i;
- for (i = 0; i < count; i++)
- if (pages[i])
- __free_pages(pages[i], 0);
+
+ if (dma_get_attr(DMA_ATTR_FORCE_CONTIGUOUS, attrs)) {
+ dma_release_from_contiguous(dev, pages[0], count);
+ } else {
+ for (i = 0; i < count; i++)
+ if (pages[i])
+ __free_pages(pages[i], 0);
+ }
+
if (array_size <= PAGE_SIZE)
kfree(pages);
else
@@ -1252,7 +1277,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
if (gfp & GFP_ATOMIC)
return __iommu_alloc_atomic(dev, size, handle);
- pages = __iommu_alloc_buffer(dev, size, gfp);
+ pages = __iommu_alloc_buffer(dev, size, gfp, attrs);
if (!pages)
return NULL;
@@ -1273,7 +1298,7 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
err_mapping:
__iommu_remove_mapping(dev, *handle, size);
err_buffer:
- __iommu_free_buffer(dev, pages, size);
+ __iommu_free_buffer(dev, pages, size, attrs);
return NULL;
}
@@ -1329,7 +1354,7 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
}
__iommu_remove_mapping(dev, handle, size);
- __iommu_free_buffer(dev, pages, size);
+ __iommu_free_buffer(dev, pages, size, attrs);
}
static int arm_iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 9f0610243bd..ce328c7f5c9 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -283,7 +283,7 @@ static struct mem_type mem_types[] = {
},
[MT_MEMORY_SO] = {
.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
- L_PTE_MT_UNCACHED,
+ L_PTE_MT_UNCACHED | L_PTE_XN,
.prot_l1 = PMD_TYPE_TABLE,
.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S |
PMD_SECT_UNCACHED | PMD_SECT_XN,
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 42cc833aa02..3a3c015f8d5 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -169,6 +169,64 @@ __v7_ca15mp_setup:
orreq r0, r0, r10 @ Enable CPU-specific SMP bits
mcreq p15, 0, r0, c1, c0, 1
#endif
+ b __v7_setup
+
+__v7_pj4b_setup:
+#ifdef CONFIG_CPU_PJ4B
+
+/* Auxiliary Debug Modes Control 1 Register */
+#define PJ4B_STATIC_BP (1 << 2) /* Enable Static BP */
+#define PJ4B_INTER_PARITY (1 << 8) /* Disable Internal Parity Handling */
+#define PJ4B_BCK_OFF_STREX (1 << 5) /* Enable the back off of STREX instr */
+#define PJ4B_CLEAN_LINE (1 << 16) /* Disable data transfer for clean line */
+
+/* Auxiliary Debug Modes Control 2 Register */
+#define PJ4B_FAST_LDR (1 << 23) /* Disable fast LDR */
+#define PJ4B_SNOOP_DATA (1 << 25) /* Do not interleave write and snoop data */
+#define PJ4B_CWF (1 << 27) /* Disable Critical Word First feature */
+#define PJ4B_OUTSDNG_NC (1 << 29) /* Disable outstanding non cacheable rqst */
+#define PJ4B_L1_REP_RR (1 << 30) /* L1 replacement - Strict round robin */
+#define PJ4B_AUX_DBG_CTRL2 (PJ4B_SNOOP_DATA | PJ4B_CWF |\
+ PJ4B_OUTSDNG_NC | PJ4B_L1_REP_RR)
+
+/* Auxiliary Functional Modes Control Register 0 */
+#define PJ4B_SMP_CFB (1 << 1) /* Set SMP mode. Join the coherency fabric */
+#define PJ4B_L1_PAR_CHK (1 << 2) /* Support L1 parity checking */
+#define PJ4B_BROADCAST_CACHE (1 << 8) /* Broadcast Cache and TLB maintenance */
+
+/* Auxiliary Debug Modes Control 0 Register */
+#define PJ4B_WFI_WFE (1 << 22) /* WFI/WFE - serve the DVM and back to idle */
+
+ /* Auxiliary Debug Modes Control 1 Register */
+ mrc p15, 1, r0, c15, c1, 1
+ orr r0, r0, #PJ4B_CLEAN_LINE
+ orr r0, r0, #PJ4B_BCK_OFF_STREX
+ orr r0, r0, #PJ4B_INTER_PARITY
+ bic r0, r0, #PJ4B_STATIC_BP
+ mcr p15, 1, r0, c15, c1, 1
+
+ /* Auxiliary Debug Modes Control 2 Register */
+ mrc p15, 1, r0, c15, c1, 2
+ bic r0, r0, #PJ4B_FAST_LDR
+ orr r0, r0, #PJ4B_AUX_DBG_CTRL2
+ mcr p15, 1, r0, c15, c1, 2
+
+ /* Auxiliary Functional Modes Control Register 0 */
+ mrc p15, 1, r0, c15, c2, 0
+#ifdef CONFIG_SMP
+ orr r0, r0, #PJ4B_SMP_CFB
+#endif
+ orr r0, r0, #PJ4B_L1_PAR_CHK
+ orr r0, r0, #PJ4B_BROADCAST_CACHE
+ mcr p15, 1, r0, c15, c2, 0
+
+ /* Auxiliary Debug Modes Control 0 Register */
+ mrc p15, 1, r0, c15, c1, 0
+ orr r0, r0, #PJ4B_WFI_WFE
+ mcr p15, 1, r0, c15, c1, 0
+
+#endif /* CONFIG_CPU_PJ4B */
+
__v7_setup:
adr r12, __v7_setup_stack @ the local stack
stmia r12, {r0-r5, r7, r9, r11, lr}
@@ -188,7 +246,8 @@ __v7_setup:
ldr r10, =0x00000c08 @ Cortex-A8 primary part number
teq r0, r10
bne 2f
-#ifdef CONFIG_ARM_ERRATA_430973
+#if defined(CONFIG_ARM_ERRATA_430973) && !defined(CONFIG_ARCH_MULTIPLATFORM)
+
teq r5, #0x00100000 @ only present in r1p*
mrceq p15, 0, r10, c1, c0, 1 @ read aux control register
orreq r10, r10, #(1 << 6) @ set IBE to 1
@@ -342,6 +401,16 @@ __v7_ca9mp_proc_info:
.long 0xff0ffff0
__v7_proc __v7_ca9mp_setup
.size __v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
+
+ /*
+ * Marvell PJ4B processor.
+ */
+ .type __v7_pj4b_proc_info, #object
+__v7_pj4b_proc_info:
+ .long 0x562f5840
+ .long 0xfffffff0
+ __v7_proc __v7_pj4b_setup
+ .size __v7_pj4b_proc_info, . - __v7_pj4b_proc_info
#endif /* CONFIG_ARM_LPAE */
/*