Commit 77f36fcc authored by Paul Mundt's avatar Paul Mundt

Merge branch 'sh/pmb-dynamic'

parents 838a4a9d d01447b3
......@@ -117,7 +117,7 @@ void decompress_kernel(void)
output_addr = (CONFIG_MEMORY_START + 0x2000);
#else
output_addr = __pa((unsigned long)&_text+PAGE_SIZE);
#if defined(CONFIG_29BIT) || defined(CONFIG_PMB_LEGACY)
#if defined(CONFIG_29BIT)
output_addr |= P2SEG;
#endif
#endif
......
......@@ -133,6 +133,28 @@ static inline void ctrl_delay(void)
__raw_readw(generic_io_base);
}
#define __BUILD_UNCACHED_IO(bwlq, type) \
static inline type read##bwlq##_uncached(unsigned long addr) \
{ \
type ret; \
jump_to_uncached(); \
ret = __raw_read##bwlq(addr); \
back_to_cached(); \
return ret; \
} \
\
static inline void write##bwlq##_uncached(type v, unsigned long addr) \
{ \
jump_to_uncached(); \
__raw_write##bwlq(v, addr); \
back_to_cached(); \
}
__BUILD_UNCACHED_IO(b, u8)
__BUILD_UNCACHED_IO(w, u16)
__BUILD_UNCACHED_IO(l, u32)
__BUILD_UNCACHED_IO(q, u64)
#define __BUILD_MEMORY_STRING(bwlq, type) \
\
static inline void __raw_writes##bwlq(volatile void __iomem *mem, \
......
......@@ -11,7 +11,9 @@
#define PMB_ADDR 0xf6100000
#define PMB_DATA 0xf7100000
#define PMB_ENTRY_MAX 16
#define NR_PMB_ENTRIES 16
#define PMB_E_MASK 0x0000000f
#define PMB_E_SHIFT 8
......@@ -25,6 +27,7 @@
#define PMB_C 0x00000008
#define PMB_WT 0x00000001
#define PMB_UB 0x00000200
#define PMB_CACHE_MASK (PMB_C | PMB_WT | PMB_UB)
#define PMB_V 0x00000100
#define PMB_NO_ENTRY (-1)
......@@ -32,6 +35,7 @@
#ifndef __ASSEMBLY__
#include <linux/errno.h>
#include <linux/threads.h>
#include <asm/page.h>
/* Default "unsigned long" context */
typedef unsigned long mm_context_id_t[NR_CPUS];
......@@ -49,46 +53,22 @@ typedef struct {
#endif
} mm_context_t;
struct pmb_entry;
struct pmb_entry {
unsigned long vpn;
unsigned long ppn;
unsigned long flags;
/*
* 0 .. NR_PMB_ENTRIES for specific entry selection, or
* PMB_NO_ENTRY to search for a free one
*/
int entry;
struct pmb_entry *next;
/* Adjacent entry link for contiguous multi-entry mappings */
struct pmb_entry *link;
};
#ifdef CONFIG_PMB
/* arch/sh/mm/pmb.c */
long pmb_remap(unsigned long virt, unsigned long phys,
unsigned long size, unsigned long flags);
unsigned long size, pgprot_t prot);
void pmb_unmap(unsigned long addr);
int pmb_init(void);
void pmb_init(void);
bool __in_29bit_mode(void);
#else
static inline long pmb_remap(unsigned long virt, unsigned long phys,
unsigned long size, unsigned long flags)
unsigned long size, pgprot_t prot)
{
return -EINVAL;
}
static inline void pmb_unmap(unsigned long addr)
{
}
static inline int pmb_init(void)
{
return -ENODEV;
}
#define pmb_unmap(addr) do { } while (0)
#define pmb_init(addr) do { } while (0)
#ifdef CONFIG_29BIT
#define __in_29bit_mode() (1)
......
......@@ -45,6 +45,7 @@
#endif
#ifndef __ASSEMBLY__
#include <asm/uncached.h>
extern unsigned long shm_align_mask;
extern unsigned long max_low_pfn, min_low_pfn;
......@@ -56,7 +57,6 @@ pages_do_alias(unsigned long addr1, unsigned long addr2)
return (addr1 ^ addr2) & shm_align_mask;
}
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
extern void copy_page(void *to, void *from);
......@@ -127,12 +127,7 @@ typedef struct page *pgtable_t;
* is not visible (it is part of the PMB mapping) and so needs to be
* added or subtracted as required.
*/
#if defined(CONFIG_PMB_LEGACY)
/* phys = virt - PAGE_OFFSET - (__MEMORY_START & 0xe0000000) */
#define PMB_OFFSET (PAGE_OFFSET - PXSEG(__MEMORY_START))
#define __pa(x) ((unsigned long)(x) - PMB_OFFSET)
#define __va(x) ((void *)((unsigned long)(x) + PMB_OFFSET))
#elif defined(CONFIG_32BIT)
#ifdef CONFIG_PMB
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET+__MEMORY_START)
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET-__MEMORY_START))
#else
......@@ -140,6 +135,14 @@ typedef struct page *pgtable_t;
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
#endif
#ifdef CONFIG_UNCACHED_MAPPING
#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + uncached_start)
#define CAC_ADDR(addr) ((addr) - uncached_start + PAGE_OFFSET)
#else
#define UNCAC_ADDR(addr) ((addr))
#define CAC_ADDR(addr) ((addr))
#endif
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
......
......@@ -139,15 +139,8 @@ static inline unsigned long profile_pc(struct pt_regs *regs)
{
unsigned long pc = instruction_pointer(regs);
#ifdef CONFIG_UNCACHED_MAPPING
/*
* If PC points in to the uncached mapping, fix it up and hand
* back the cached equivalent.
*/
if ((pc >= (memory_start + cached_to_uncached)) &&
(pc < (memory_start + cached_to_uncached + uncached_size)))
pc -= cached_to_uncached;
#endif
if (virt_addr_uncached(pc))
return CAC_ADDR(pc);
return pc;
}
......
#ifndef __ASM_SH_UNCACHED_H
#define __ASM_SH_UNCACHED_H
#include <linux/bug.h>
#ifdef CONFIG_UNCACHED_MAPPING
extern unsigned long uncached_start, uncached_end;
extern int virt_addr_uncached(unsigned long kaddr);
extern void uncached_init(void);
extern void uncached_resize(unsigned long size);
#else
#define virt_addr_uncached(kaddr) (0)
#define uncached_init() do { } while (0)
#define uncached_resize(size) BUG()
#endif
#endif /* __ASM_SH_UNCACHED_H */
......@@ -12,6 +12,7 @@
#define __ASM_CPU_SH4_SQ_H
#include <asm/addrspace.h>
#include <asm/page.h>
/*
* Store queues range from e0000000-e3fffffc, allowing approx. 64MB to be
......@@ -28,7 +29,7 @@
/* arch/sh/kernel/cpu/sh4/sq.c */
unsigned long sq_remap(unsigned long phys, unsigned int size,
const char *name, unsigned long flags);
const char *name, pgprot_t prot);
void sq_unmap(unsigned long vaddr);
void sq_flush_range(unsigned long start, unsigned int len);
......
......@@ -24,6 +24,7 @@
#include <asm/elf.h>
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/sh_bios.h>
#ifdef CONFIG_SH_FPU
#define cpu_has_fpu 1
......@@ -342,9 +343,21 @@ asmlinkage void __init sh_cpu_init(void)
speculative_execution_init();
expmask_init();
/*
* Boot processor to setup the FP and extended state context info.
*/
if (raw_smp_processor_id() == 0)
/* Do the rest of the boot processor setup */
if (raw_smp_processor_id() == 0) {
/* Save off the BIOS VBR, if there is one */
sh_bios_vbr_init();
/*
* Setup VBR for boot CPU. Secondary CPUs do this through
* start_secondary().
*/
per_cpu_trap_init();
/*
* Boot processor to setup the FP and extended state
* context info.
*/
init_thread_xstate();
}
}
......@@ -100,7 +100,7 @@ static inline void sq_mapping_list_del(struct sq_mapping *map)
spin_unlock_irq(&sq_mapping_lock);
}
static int __sq_remap(struct sq_mapping *map, unsigned long flags)
static int __sq_remap(struct sq_mapping *map, pgprot_t prot)
{
#if defined(CONFIG_MMU)
struct vm_struct *vma;
......@@ -113,7 +113,7 @@ static int __sq_remap(struct sq_mapping *map, unsigned long flags)
if (ioremap_page_range((unsigned long)vma->addr,
(unsigned long)vma->addr + map->size,
vma->phys_addr, __pgprot(flags))) {
vma->phys_addr, prot)) {
vunmap(vma->addr);
return -EAGAIN;
}
......@@ -135,14 +135,14 @@ static int __sq_remap(struct sq_mapping *map, unsigned long flags)
* @phys: Physical address of mapping.
* @size: Length of mapping.
* @name: User invoking mapping.
* @flags: Protection flags.
* @prot: Protection bits.
*
* Remaps the physical address @phys through the next available store queue
* address of @size length. @name is logged at boot time as well as through
* the sysfs interface.
*/
unsigned long sq_remap(unsigned long phys, unsigned int size,
const char *name, unsigned long flags)
const char *name, pgprot_t prot)
{
struct sq_mapping *map;
unsigned long end;
......@@ -177,7 +177,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size,
map->sq_addr = P4SEG_STORE_QUE + (page << PAGE_SHIFT);
ret = __sq_remap(map, pgprot_val(PAGE_KERNEL_NOCACHE) | flags);
ret = __sq_remap(map, prot);
if (unlikely(ret != 0))
goto out;
......@@ -309,8 +309,7 @@ static ssize_t mapping_store(const char *buf, size_t count)
return -EIO;
if (likely(len)) {
int ret = sq_remap(base, len, "Userspace",
pgprot_val(PAGE_SHARED));
int ret = sq_remap(base, len, "Userspace", PAGE_SHARED);
if (ret < 0)
return ret;
} else
......
......@@ -85,7 +85,7 @@ ENTRY(_stext)
ldc r0, r7_bank ! ... and initial thread_info
#endif
#if defined(CONFIG_PMB) && !defined(CONFIG_PMB_LEGACY)
#ifdef CONFIG_PMB
/*
* Reconfigure the initial PMB mappings setup by the hardware.
*
......@@ -139,7 +139,6 @@ ENTRY(_stext)
mov.l r0, @r1
mov.l .LMEMORY_SIZE, r5
mov r5, r7
mov #PMB_E_SHIFT, r0
mov #0x1, r4
......@@ -150,8 +149,43 @@ ENTRY(_stext)
mov.l .LFIRST_ADDR_ENTRY, r2
mov.l .LPMB_ADDR, r3
/*
* First we need to walk the PMB and figure out if there are any
* existing mappings that match the initial mappings VPN/PPN.
* If these have already been established by the bootloader, we
* don't bother setting up new entries here, and let the late PMB
* initialization take care of things instead.
*
* Note that we may need to coalesce and merge entries in order
* to reclaim more available PMB slots, which is much more than
* we want to do at this early stage.
*/
mov #0, r10
mov #NR_PMB_ENTRIES, r9
mov r1, r7 /* temporary PMB_DATA iter */
.Lvalidate_existing_mappings:
mov.l @r7, r8
and r0, r8
cmp/eq r0, r8 /* Check for valid __MEMORY_START mappings */
bt .Lpmb_done
add #1, r10 /* Increment the loop counter */
cmp/eq r9, r10
bf/s .Lvalidate_existing_mappings
add r4, r7 /* Increment to the next PMB_DATA entry */
/*
* If we've fallen through, continue with setting up the initial
* mappings.
*/
mov r5, r7 /* cached_to_uncached */
mov #0, r10
#ifdef CONFIG_UNCACHED_MAPPING
/*
* Uncached mapping
*/
......@@ -171,6 +205,7 @@ ENTRY(_stext)
add r4, r1
add r4, r3
add #1, r10
#endif
/*
* Iterate over all of the available sizes from largest to
......@@ -216,6 +251,7 @@ ENTRY(_stext)
__PMB_ITER_BY_SIZE(64)
__PMB_ITER_BY_SIZE(16)
#ifdef CONFIG_UNCACHED_MAPPING
/*
* Now that we can access it, update cached_to_uncached and
* uncached_size.
......@@ -228,6 +264,7 @@ ENTRY(_stext)
shll16 r7
shll8 r7
mov.l r7, @r0
#endif
/*
* Clear the remaining PMB entries.
......@@ -236,7 +273,7 @@ ENTRY(_stext)
* r10 = number of entries we've setup so far
*/
mov #0, r1
mov #PMB_ENTRY_MAX, r0
mov #NR_PMB_ENTRIES, r0
.Lagain:
mov.l r1, @r3 /* Clear PMB_ADDR entry */
......@@ -248,7 +285,8 @@ ENTRY(_stext)
mov.l 6f, r0
icbi @r0
#endif /* !CONFIG_PMB_LEGACY */
.Lpmb_done:
#endif /* CONFIG_PMB */
#ifndef CONFIG_SH_NO_BSS_INIT
/*
......@@ -300,13 +338,15 @@ ENTRY(stack_start)
6: .long sh_cpu_init
7: .long init_thread_union
#if defined(CONFIG_PMB) && !defined(CONFIG_PMB_LEGACY)
#ifdef CONFIG_PMB
.LPMB_ADDR: .long PMB_ADDR
.LPMB_DATA: .long PMB_DATA
.LFIRST_ADDR_ENTRY: .long PAGE_OFFSET | PMB_V
.LFIRST_DATA_ENTRY: .long __MEMORY_START | PMB_V
.LMMUCR: .long MMUCR
.LMEMORY_SIZE: .long __MEMORY_SIZE
#ifdef CONFIG_UNCACHED_MAPPING
.Lcached_to_uncached: .long cached_to_uncached
.Luncached_size: .long uncached_size
.LMEMORY_SIZE: .long __MEMORY_SIZE
#endif
#endif
......@@ -421,6 +421,8 @@ void __init setup_arch(char **cmdline_p)
parse_early_param();
uncached_init();
plat_early_device_setup();
/* Let earlyprintk output early console messages */
......
......@@ -30,7 +30,6 @@
#include <asm/alignment.h>
#include <asm/fpu.h>
#include <asm/kprobes.h>
#include <asm/sh_bios.h>
#ifdef CONFIG_CPU_SH2
# define TRAP_RESERVED_INST 4
......@@ -848,12 +847,6 @@ void __init trap_init(void)
#ifdef TRAP_UBC
set_exception_table_vec(TRAP_UBC, breakpoint_trap_handler);
#endif
/* Save off the BIOS VBR, if there is one */
sh_bios_vbr_init();
/* Setup VBR for boot cpu */
per_cpu_trap_init();
}
void show_stack(struct task_struct *tsk, unsigned long *sp)
......
......@@ -14,11 +14,10 @@ OUTPUT_ARCH(sh)
#include <asm/cache.h>
#include <asm/vmlinux.lds.h>
#if defined(CONFIG_29BIT) || defined(CONFIG_SUPERH64) || \
defined(CONFIG_PMB_LEGACY)
#define MEMORY_OFFSET __MEMORY_START
#ifdef CONFIG_PMB
#define MEMORY_OFFSET 0
#else
#define MEMORY_OFFSET 0
#define MEMORY_OFFSET __MEMORY_START
#endif
ENTRY(_start)
......
......@@ -91,16 +91,6 @@ config PMB
32-bits through the SH-4A PMB. If this is not set, legacy
29-bit physical addressing will be used.
config PMB_LEGACY
bool "Support legacy boot mappings for PMB"
depends on PMB
select 32BIT
help
If this option is enabled, fixed PMB mappings are inherited
from the boot loader, and the kernel does not attempt dynamic
management. This is the closest to legacy 29-bit physical mode,
and allows systems to support up to 512MiB of system memory.
config X2TLB
def_bool y
depends on (CPU_SHX2 || CPU_SHX3) && MMU
......
......@@ -36,6 +36,7 @@ obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_PMB) += pmb.o
obj-$(CONFIG_NUMA) += numa.o
obj-$(CONFIG_IOREMAP_FIXED) += ioremap_fixed.o
obj-$(CONFIG_UNCACHED_MAPPING) += uncached.o
# Special flags for fault_64.o. This puts restrictions on the number of
# caller-save registers that the compiler can target when building this file.
......
......@@ -26,21 +26,6 @@
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
pgd_t swapper_pg_dir[PTRS_PER_PGD];
#ifdef CONFIG_UNCACHED_MAPPING
/*
* This is the offset of the uncached section from its cached alias.
*
* Legacy platforms handle trivial transitions between cached and
* uncached segments by making use of the 1:1 mapping relationship in
* 512MB lowmem, others via a special uncached mapping.
*
* Default value only valid in 29 bit mode, in 32bit mode this will be
* updated by the early PMB initialization code.
*/
unsigned long cached_to_uncached = 0x20000000;
unsigned long uncached_size = SZ_512M;
#endif
#ifdef CONFIG_MMU
static pte_t *__get_pte_phys(unsigned long addr)
{
......@@ -260,7 +245,6 @@ void __init mem_init(void)
memset(empty_zero_page, 0, PAGE_SIZE);
__flush_wback_region(empty_zero_page, PAGE_SIZE);
/* Initialize the vDSO */
vsyscall_init();
codesize = (unsigned long) &_etext - (unsigned long) &_text;
......@@ -303,9 +287,7 @@ void __init mem_init(void)
((unsigned long)high_memory - (unsigned long)memory_start) >> 20,
#ifdef CONFIG_UNCACHED_MAPPING
(unsigned long)memory_start + cached_to_uncached,
(unsigned long)memory_start + cached_to_uncached + uncached_size,
uncached_size >> 20,
uncached_start, uncached_end, uncached_size >> 20,
#endif
(unsigned long)&__init_begin, (unsigned long)&__init_end,
......
......@@ -80,7 +80,7 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size,
if (unlikely(phys_addr >= P1SEG)) {
unsigned long mapped;
mapped = pmb_remap(addr, phys_addr, size, pgprot_val(pgprot));
mapped = pmb_remap(addr, phys_addr, size, pgprot);
if (likely(mapped)) {
addr += mapped;
phys_addr += mapped;
......
This diff is collapsed.
#include <linux/init.h>
#include <asm/sizes.h>
#include <asm/page.h>
/*
* This is the offset of the uncached section from its cached alias.
*
* Legacy platforms handle trivial transitions between cached and
* uncached segments by making use of the 1:1 mapping relationship in
* 512MB lowmem, others via a special uncached mapping.
*
* Default value only valid in 29 bit mode, in 32bit mode this will be
* updated by the early PMB initialization code.
*/
unsigned long cached_to_uncached = SZ_512M;
unsigned long uncached_size = SZ_512M;
unsigned long uncached_start, uncached_end;
int virt_addr_uncached(unsigned long kaddr)
{
return (kaddr >= uncached_start) && (kaddr < uncached_end);
}
void __init uncached_init(void)
{
uncached_start = memory_end;
uncached_end = uncached_start + uncached_size;
}
void __init uncached_resize(unsigned long size)
{
uncached_size = size;
uncached_end = uncached_start + uncached_size;
}
......@@ -831,7 +831,7 @@ static int __devinit pvr2fb_common_init(void)
printk(KERN_NOTICE "fb%d: registering with SQ API\n", fb_info->node);
pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len,
fb_info->fix.id, pgprot_val(PAGE_SHARED));
fb_info->fix.id, PAGE_SHARED);
printk(KERN_NOTICE "fb%d: Mapped video memory to SQ addr 0x%lx\n",
fb_info->node, pvr2fb_map);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment