sh: PMB tidying.
Some overdue cleanup of the PMB code, killing off unused functionality and duplication sprinkled about the tree. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
parent
7bdda6209f
commit
51becfd962
|
@ -11,7 +11,9 @@
|
||||||
|
|
||||||
#define PMB_ADDR 0xf6100000
|
#define PMB_ADDR 0xf6100000
|
||||||
#define PMB_DATA 0xf7100000
|
#define PMB_DATA 0xf7100000
|
||||||
#define PMB_ENTRY_MAX 16
|
|
||||||
|
#define NR_PMB_ENTRIES 16
|
||||||
|
|
||||||
#define PMB_E_MASK 0x0000000f
|
#define PMB_E_MASK 0x0000000f
|
||||||
#define PMB_E_SHIFT 8
|
#define PMB_E_SHIFT 8
|
||||||
|
|
||||||
|
|
|
@ -236,7 +236,7 @@ ENTRY(_stext)
|
||||||
* r10 = number of entries we've setup so far
|
* r10 = number of entries we've setup so far
|
||||||
*/
|
*/
|
||||||
mov #0, r1
|
mov #0, r1
|
||||||
mov #PMB_ENTRY_MAX, r0
|
mov #NR_PMB_ENTRIES, r0
|
||||||
|
|
||||||
.Lagain:
|
.Lagain:
|
||||||
mov.l r1, @r3 /* Clear PMB_ADDR entry */
|
mov.l r1, @r3 /* Clear PMB_ADDR entry */
|
||||||
|
|
|
@ -21,32 +21,31 @@
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <asm/sizes.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/mmu.h>
|
#include <asm/mmu.h>
|
||||||
#include <asm/io.h>
|
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
|
|
||||||
#define NR_PMB_ENTRIES 16
|
static void pmb_unmap_entry(struct pmb_entry *);
|
||||||
|
|
||||||
static void __pmb_unmap(struct pmb_entry *);
|
|
||||||
|
|
||||||
static struct pmb_entry pmb_entry_list[NR_PMB_ENTRIES];
|
static struct pmb_entry pmb_entry_list[NR_PMB_ENTRIES];
|
||||||
static unsigned long pmb_map;
|
static DECLARE_BITMAP(pmb_map, NR_PMB_ENTRIES);
|
||||||
|
|
||||||
static inline unsigned long mk_pmb_entry(unsigned int entry)
|
static __always_inline unsigned long mk_pmb_entry(unsigned int entry)
|
||||||
{
|
{
|
||||||
return (entry & PMB_E_MASK) << PMB_E_SHIFT;
|
return (entry & PMB_E_MASK) << PMB_E_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long mk_pmb_addr(unsigned int entry)
|
static __always_inline unsigned long mk_pmb_addr(unsigned int entry)
|
||||||
{
|
{
|
||||||
return mk_pmb_entry(entry) | PMB_ADDR;
|
return mk_pmb_entry(entry) | PMB_ADDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long mk_pmb_data(unsigned int entry)
|
static __always_inline unsigned long mk_pmb_data(unsigned int entry)
|
||||||
{
|
{
|
||||||
return mk_pmb_entry(entry) | PMB_DATA;
|
return mk_pmb_entry(entry) | PMB_DATA;
|
||||||
}
|
}
|
||||||
|
@ -56,12 +55,12 @@ static int pmb_alloc_entry(void)
|
||||||
unsigned int pos;
|
unsigned int pos;
|
||||||
|
|
||||||
repeat:
|
repeat:
|
||||||
pos = find_first_zero_bit(&pmb_map, NR_PMB_ENTRIES);
|
pos = find_first_zero_bit(pmb_map, NR_PMB_ENTRIES);
|
||||||
|
|
||||||
if (unlikely(pos > NR_PMB_ENTRIES))
|
if (unlikely(pos > NR_PMB_ENTRIES))
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
|
|
||||||
if (test_and_set_bit(pos, &pmb_map))
|
if (test_and_set_bit(pos, pmb_map))
|
||||||
goto repeat;
|
goto repeat;
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
|
@ -78,7 +77,7 @@ static struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
|
||||||
if (pos < 0)
|
if (pos < 0)
|
||||||
return ERR_PTR(pos);
|
return ERR_PTR(pos);
|
||||||
} else {
|
} else {
|
||||||
if (test_and_set_bit(entry, &pmb_map))
|
if (test_and_set_bit(entry, pmb_map))
|
||||||
return ERR_PTR(-ENOSPC);
|
return ERR_PTR(-ENOSPC);
|
||||||
pos = entry;
|
pos = entry;
|
||||||
}
|
}
|
||||||
|
@ -104,16 +103,17 @@ static void pmb_free(struct pmb_entry *pmbe)
|
||||||
pmbe->flags = 0;
|
pmbe->flags = 0;
|
||||||
pmbe->entry = 0;
|
pmbe->entry = 0;
|
||||||
|
|
||||||
clear_bit(pos, &pmb_map);
|
clear_bit(pos, pmb_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Must be in P2 for __set_pmb_entry()
|
* Must be run uncached.
|
||||||
*/
|
*/
|
||||||
static void __set_pmb_entry(unsigned long vpn, unsigned long ppn,
|
static void set_pmb_entry(struct pmb_entry *pmbe)
|
||||||
unsigned long flags, int pos)
|
|
||||||
{
|
{
|
||||||
__raw_writel(vpn | PMB_V, mk_pmb_addr(pos));
|
jump_to_uncached();
|
||||||
|
|
||||||
|
__raw_writel(pmbe->vpn | PMB_V, mk_pmb_addr(pmbe->entry));
|
||||||
|
|
||||||
#ifdef CONFIG_CACHE_WRITETHROUGH
|
#ifdef CONFIG_CACHE_WRITETHROUGH
|
||||||
/*
|
/*
|
||||||
|
@ -121,17 +121,12 @@ static void __set_pmb_entry(unsigned long vpn, unsigned long ppn,
|
||||||
* invalid, so care must be taken to manually adjust cacheable
|
* invalid, so care must be taken to manually adjust cacheable
|
||||||
* translations.
|
* translations.
|
||||||
*/
|
*/
|
||||||
if (likely(flags & PMB_C))
|
if (likely(pmbe->flags & PMB_C))
|
||||||
flags |= PMB_WT;
|
pmbe->flags |= PMB_WT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__raw_writel(ppn | flags | PMB_V, mk_pmb_data(pos));
|
__raw_writel(pmbe->ppn | pmbe->flags | PMB_V, mk_pmb_data(pmbe->entry));
|
||||||
}
|
|
||||||
|
|
||||||
static void set_pmb_entry(struct pmb_entry *pmbe)
|
|
||||||
{
|
|
||||||
jump_to_uncached();
|
|
||||||
__set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, pmbe->entry);
|
|
||||||
back_to_cached();
|
back_to_cached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,9 +135,6 @@ static void clear_pmb_entry(struct pmb_entry *pmbe)
|
||||||
unsigned int entry = pmbe->entry;
|
unsigned int entry = pmbe->entry;
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
|
|
||||||
if (unlikely(entry >= NR_PMB_ENTRIES))
|
|
||||||
return;
|
|
||||||
|
|
||||||
jump_to_uncached();
|
jump_to_uncached();
|
||||||
|
|
||||||
/* Clear V-bit */
|
/* Clear V-bit */
|
||||||
|
@ -155,15 +147,14 @@ static void clear_pmb_entry(struct pmb_entry *pmbe)
|
||||||
back_to_cached();
|
back_to_cached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
int flag;
|
int flag;
|
||||||
} pmb_sizes[] = {
|
} pmb_sizes[] = {
|
||||||
{ .size = 0x20000000, .flag = PMB_SZ_512M, },
|
{ .size = SZ_512M, .flag = PMB_SZ_512M, },
|
||||||
{ .size = 0x08000000, .flag = PMB_SZ_128M, },
|
{ .size = SZ_128M, .flag = PMB_SZ_128M, },
|
||||||
{ .size = 0x04000000, .flag = PMB_SZ_64M, },
|
{ .size = SZ_64M, .flag = PMB_SZ_64M, },
|
||||||
{ .size = 0x01000000, .flag = PMB_SZ_16M, },
|
{ .size = SZ_16M, .flag = PMB_SZ_16M, },
|
||||||
};
|
};
|
||||||
|
|
||||||
long pmb_remap(unsigned long vaddr, unsigned long phys,
|
long pmb_remap(unsigned long vaddr, unsigned long phys,
|
||||||
|
@ -230,34 +221,36 @@ again:
|
||||||
return wanted - size;
|
return wanted - size;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (pmbp)
|
pmb_unmap_entry(pmbp);
|
||||||
__pmb_unmap(pmbp);
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pmb_unmap(unsigned long addr)
|
void pmb_unmap(unsigned long addr)
|
||||||
{
|
{
|
||||||
struct pmb_entry *pmbe = NULL;
|
struct pmb_entry *pmbe;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
|
for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
|
||||||
if (test_bit(i, &pmb_map)) {
|
if (test_bit(i, pmb_map)) {
|
||||||
pmbe = &pmb_entry_list[i];
|
pmbe = &pmb_entry_list[i];
|
||||||
if (pmbe->vpn == addr)
|
if (pmbe->vpn == addr) {
|
||||||
|
pmb_unmap_entry(pmbe);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pmb_unmap_entry(struct pmb_entry *pmbe)
|
||||||
|
{
|
||||||
if (unlikely(!pmbe))
|
if (unlikely(!pmbe))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
__pmb_unmap(pmbe);
|
if (!test_bit(pmbe->entry, pmb_map)) {
|
||||||
}
|
WARN_ON(1);
|
||||||
|
return;
|
||||||
static void __pmb_unmap(struct pmb_entry *pmbe)
|
}
|
||||||
{
|
|
||||||
BUG_ON(!test_bit(pmbe->entry, &pmb_map));
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
struct pmb_entry *pmblink = pmbe;
|
struct pmb_entry *pmblink = pmbe;
|
||||||
|
@ -326,7 +319,7 @@ static int pmb_synchronize_mappings(void)
|
||||||
* jumping between the cached and uncached mappings and tearing
|
* jumping between the cached and uncached mappings and tearing
|
||||||
* down alternating mappings while executing from the other.
|
* down alternating mappings while executing from the other.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < PMB_ENTRY_MAX; i++) {
|
for (i = 0; i < NR_PMB_ENTRIES; i++) {
|
||||||
unsigned long addr, data;
|
unsigned long addr, data;
|
||||||
unsigned long addr_val, data_val;
|
unsigned long addr_val, data_val;
|
||||||
unsigned long ppn, vpn, flags;
|
unsigned long ppn, vpn, flags;
|
||||||
|
@ -494,7 +487,7 @@ static int pmb_sysdev_suspend(struct sys_device *dev, pm_message_t state)
|
||||||
prev_state.event == PM_EVENT_FREEZE) {
|
prev_state.event == PM_EVENT_FREEZE) {
|
||||||
struct pmb_entry *pmbe;
|
struct pmb_entry *pmbe;
|
||||||
for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
|
for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
|
||||||
if (test_bit(i, &pmb_map)) {
|
if (test_bit(i, pmb_map)) {
|
||||||
pmbe = &pmb_entry_list[i];
|
pmbe = &pmb_entry_list[i];
|
||||||
set_pmb_entry(pmbe);
|
set_pmb_entry(pmbe);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue