10c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt/*
20c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt * arch/sh/mm/pmb.c
30c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt *
40c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt * Privileged Space Mapping Buffer (PMB) Support.
50c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt *
6d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundt * Copyright (C) 2005 - 2011  Paul Mundt
73d467676abf5f01f5ee99056273a58486968e252Matt Fleming * Copyright (C) 2010  Matt Fleming
80c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt *
90c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt * This file is subject to the terms and conditions of the GNU General Public
100c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt * License.  See the file "COPYING" in the main directory of this archive
110c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt * for more details.
120c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt */
130c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt#include <linux/init.h>
140c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt#include <linux/kernel.h>
15d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundt#include <linux/syscore_ops.h>
16a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZI#include <linux/cpu.h>
170c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt#include <linux/module.h>
180c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt#include <linux/bitops.h>
190c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt#include <linux/debugfs.h>
200c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt#include <linux/fs.h>
210c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt#include <linux/seq_file.h>
220c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt#include <linux/err.h>
2351becfd96287b3913b13075699433730984e2f4fPaul Mundt#include <linux/io.h>
24d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt#include <linux/spinlock.h>
2590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt#include <linux/vmalloc.h>
26281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt#include <asm/cacheflush.h>
2751becfd96287b3913b13075699433730984e2f4fPaul Mundt#include <asm/sizes.h>
280c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt#include <asm/uaccess.h>
29d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt#include <asm/pgtable.h>
307bdda6209f224aa784a036df54b22cb338d2e859Paul Mundt#include <asm/page.h>
310c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt#include <asm/mmu.h>
32eddeeb32fe303910c58c4e3c27fde4b6f1503350Stuart Menefy#include <asm/mmu_context.h>
330c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
34d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundtstruct pmb_entry;
35d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
36d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundtstruct pmb_entry {
37d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	unsigned long vpn;
38d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	unsigned long ppn;
39d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	unsigned long flags;
40d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	unsigned long size;
41d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
42f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt	raw_spinlock_t lock;
43d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
44d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	/*
45d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	 * 0 .. NR_PMB_ENTRIES for specific entry selection, or
46d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	 * PMB_NO_ENTRY to search for a free one
47d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	 */
48d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	int entry;
49d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
50d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	/* Adjacent entry link for contiguous multi-entry mappings */
51d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	struct pmb_entry *link;
52d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt};
53d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
5490e7d649d86f21d478dc134f74c88e19dd472393Paul Mundtstatic struct {
5590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	unsigned long size;
5690e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	int flag;
5790e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt} pmb_sizes[] = {
5890e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	{ .size	= SZ_512M, .flag = PMB_SZ_512M, },
5990e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	{ .size = SZ_128M, .flag = PMB_SZ_128M, },
6090e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	{ .size = SZ_64M,  .flag = PMB_SZ_64M,  },
6190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	{ .size = SZ_16M,  .flag = PMB_SZ_16M,  },
6290e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt};
6390e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
64d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundtstatic void pmb_unmap_entry(struct pmb_entry *, int depth);
65fc2bdefdde89b54d8fcde7bbf7d0adc0ce5cb044Matt Fleming
66d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundtstatic DEFINE_RWLOCK(pmb_rwlock);
67edd7de803c79c7df117bf3f0e22ffdba1b1ef256Matt Flemingstatic struct pmb_entry pmb_entry_list[NR_PMB_ENTRIES];
6851becfd96287b3913b13075699433730984e2f4fPaul Mundtstatic DECLARE_BITMAP(pmb_map, NR_PMB_ENTRIES);
690c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
704cfa8e75d6854699597e21fd570721d63f899934Paul Mundtstatic unsigned int pmb_iomapping_enabled;
714cfa8e75d6854699597e21fd570721d63f899934Paul Mundt
7251becfd96287b3913b13075699433730984e2f4fPaul Mundtstatic __always_inline unsigned long mk_pmb_entry(unsigned int entry)
730c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt{
740c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	return (entry & PMB_E_MASK) << PMB_E_SHIFT;
750c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt}
760c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
7751becfd96287b3913b13075699433730984e2f4fPaul Mundtstatic __always_inline unsigned long mk_pmb_addr(unsigned int entry)
780c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt{
790c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	return mk_pmb_entry(entry) | PMB_ADDR;
800c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt}
810c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8251becfd96287b3913b13075699433730984e2f4fPaul Mundtstatic __always_inline unsigned long mk_pmb_data(unsigned int entry)
830c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt{
840c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	return mk_pmb_entry(entry) | PMB_DATA;
850c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt}
860c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8790e7d649d86f21d478dc134f74c88e19dd472393Paul Mundtstatic __always_inline unsigned int pmb_ppn_in_range(unsigned long ppn)
8890e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt{
8990e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	return ppn >= __pa(memory_start) && ppn < __pa(memory_end);
9090e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt}
9190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
9290e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt/*
9390e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt * Ensure that the PMB entries match our cache configuration.
9490e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt *
9590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt * When we are in 32-bit address extended mode, CCR.CB becomes
9690e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt * invalid, so care must be taken to manually adjust cacheable
9790e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt * translations.
9890e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt */
9990e7d649d86f21d478dc134f74c88e19dd472393Paul Mundtstatic __always_inline unsigned long pmb_cache_flags(void)
10090e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt{
10190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	unsigned long flags = 0;
10290e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
10390e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt#if defined(CONFIG_CACHE_OFF)
10490e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	flags |= PMB_WT | PMB_UB;
10590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt#elif defined(CONFIG_CACHE_WRITETHROUGH)
10690e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	flags |= PMB_C | PMB_WT | PMB_UB;
10790e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt#elif defined(CONFIG_CACHE_WRITEBACK)
10890e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	flags |= PMB_C;
10990e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt#endif
11090e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
11190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	return flags;
11290e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt}
11390e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
11490e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt/*
11590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt * Convert typical pgprot value to the PMB equivalent
11690e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt */
11790e7d649d86f21d478dc134f74c88e19dd472393Paul Mundtstatic inline unsigned long pgprot_to_pmb_flags(pgprot_t prot)
11890e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt{
11990e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	unsigned long pmb_flags = 0;
12090e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	u64 flags = pgprot_val(prot);
12190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
12290e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	if (flags & _PAGE_CACHABLE)
12390e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt		pmb_flags |= PMB_C;
12490e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	if (flags & _PAGE_WT)
12590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt		pmb_flags |= PMB_WT | PMB_UB;
12690e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
12790e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	return pmb_flags;
12890e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt}
12990e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
130a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundtstatic inline bool pmb_can_merge(struct pmb_entry *a, struct pmb_entry *b)
13190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt{
13290e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	return (b->vpn == (a->vpn + a->size)) &&
13390e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	       (b->ppn == (a->ppn + a->size)) &&
13490e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	       (b->flags == a->flags);
13590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt}
13690e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
137a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundtstatic bool pmb_mapping_exists(unsigned long vaddr, phys_addr_t phys,
138a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			       unsigned long size)
139a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt{
140a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt	int i;
141a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt
142a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt	read_lock(&pmb_rwlock);
143a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt
144a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt	for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
145a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		struct pmb_entry *pmbe, *iter;
146a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		unsigned long span;
147a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt
148a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		if (!test_bit(i, pmb_map))
149a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			continue;
150a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt
151a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		pmbe = &pmb_entry_list[i];
152a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt
153a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		/*
154a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		 * See if VPN and PPN are bounded by an existing mapping.
155a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		 */
156a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		if ((vaddr < pmbe->vpn) || (vaddr >= (pmbe->vpn + pmbe->size)))
157a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			continue;
158a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		if ((phys < pmbe->ppn) || (phys >= (pmbe->ppn + pmbe->size)))
159a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			continue;
160a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt
161a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		/*
162a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		 * Now see if we're in range of a simple mapping.
163a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		 */
164a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		if (size <= pmbe->size) {
165a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			read_unlock(&pmb_rwlock);
166a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			return true;
167a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		}
168a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt
169a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		span = pmbe->size;
170a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt
171a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		/*
172a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		 * Finally for sizes that involve compound mappings, walk
173a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		 * the chain.
174a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		 */
175a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		for (iter = pmbe->link; iter; iter = iter->link)
176a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			span += iter->size;
177a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt
178a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		/*
179a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		 * Nothing else to do if the range requirements are met.
180a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		 */
181a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		if (size <= span) {
182a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			read_unlock(&pmb_rwlock);
183a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			return true;
184a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		}
185a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt	}
186a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt
187a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt	read_unlock(&pmb_rwlock);
188a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt	return false;
189a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt}
190a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt
19190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundtstatic bool pmb_size_valid(unsigned long size)
19290e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt{
19390e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	int i;
19490e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
19590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
19690e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt		if (pmb_sizes[i].size == size)
19790e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt			return true;
19890e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
19990e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	return false;
20090e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt}
20190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
20290e7d649d86f21d478dc134f74c88e19dd472393Paul Mundtstatic inline bool pmb_addr_valid(unsigned long addr, unsigned long size)
20390e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt{
20490e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	return (addr >= P1SEG && (addr + size - 1) < P3SEG);
20590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt}
20690e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
20790e7d649d86f21d478dc134f74c88e19dd472393Paul Mundtstatic inline bool pmb_prot_valid(pgprot_t prot)
20890e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt{
20990e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	return (pgprot_val(prot) & _PAGE_USER) == 0;
21090e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt}
21190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
21290e7d649d86f21d478dc134f74c88e19dd472393Paul Mundtstatic int pmb_size_to_flags(unsigned long size)
21390e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt{
21490e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	int i;
21590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
21690e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
21790e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt		if (pmb_sizes[i].size == size)
21890e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt			return pmb_sizes[i].flag;
21990e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
22090e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	return 0;
22190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt}
22290e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
223067784f6239e08a084b4d8d597e14435331eae51Matt Flemingstatic int pmb_alloc_entry(void)
224067784f6239e08a084b4d8d597e14435331eae51Matt Fleming{
225d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	int pos;
226067784f6239e08a084b4d8d597e14435331eae51Matt Fleming
22751becfd96287b3913b13075699433730984e2f4fPaul Mundt	pos = find_first_zero_bit(pmb_map, NR_PMB_ENTRIES);
228d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	if (pos >= 0 && pos < NR_PMB_ENTRIES)
229d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt		__set_bit(pos, pmb_map);
230d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	else
231d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt		pos = -ENOSPC;
232067784f6239e08a084b4d8d597e14435331eae51Matt Fleming
233067784f6239e08a084b4d8d597e14435331eae51Matt Fleming	return pos;
234067784f6239e08a084b4d8d597e14435331eae51Matt Fleming}
235067784f6239e08a084b4d8d597e14435331eae51Matt Fleming
2368386aebb9e15a94137693ea4f4df84207f71cc75Matt Flemingstatic struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
23720b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming				   unsigned long flags, int entry)
2380c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt{
2390c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	struct pmb_entry *pmbe;
240d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	unsigned long irqflags;
241d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	void *ret = NULL;
242067784f6239e08a084b4d8d597e14435331eae51Matt Fleming	int pos;
243067784f6239e08a084b4d8d597e14435331eae51Matt Fleming
244d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	write_lock_irqsave(&pmb_rwlock, irqflags);
245d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
24620b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming	if (entry == PMB_NO_ENTRY) {
24720b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming		pos = pmb_alloc_entry();
248d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt		if (unlikely(pos < 0)) {
249d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt			ret = ERR_PTR(pos);
250d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt			goto out;
251d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt		}
25220b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming	} else {
253d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt		if (__test_and_set_bit(entry, pmb_map)) {
254d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt			ret = ERR_PTR(-ENOSPC);
255d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt			goto out;
256d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt		}
257d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
25820b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming		pos = entry;
25920b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming	}
2600c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
261d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	write_unlock_irqrestore(&pmb_rwlock, irqflags);
262d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
263edd7de803c79c7df117bf3f0e22ffdba1b1ef256Matt Fleming	pmbe = &pmb_entry_list[pos];
264d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
265d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	memset(pmbe, 0, sizeof(struct pmb_entry));
266d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
267f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt	raw_spin_lock_init(&pmbe->lock);
2680c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
2690c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	pmbe->vpn	= vpn;
2700c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	pmbe->ppn	= ppn;
2710c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	pmbe->flags	= flags;
272067784f6239e08a084b4d8d597e14435331eae51Matt Fleming	pmbe->entry	= pos;
2730c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
2740c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	return pmbe;
275d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
276d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundtout:
277d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	write_unlock_irqrestore(&pmb_rwlock, irqflags);
278d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	return ret;
2790c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt}
2800c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
2818386aebb9e15a94137693ea4f4df84207f71cc75Matt Flemingstatic void pmb_free(struct pmb_entry *pmbe)
2820c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt{
283d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	__clear_bit(pmbe->entry, pmb_map);
284d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
285d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	pmbe->entry	= PMB_NO_ENTRY;
286d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	pmbe->link	= NULL;
2870c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt}
2880c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
2890c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt/*
29051becfd96287b3913b13075699433730984e2f4fPaul Mundt * Must be run uncached.
2910c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt */
292d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundtstatic void __set_pmb_entry(struct pmb_entry *pmbe)
2930c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt{
294281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	unsigned long addr, data;
295281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt
296281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	addr = mk_pmb_addr(pmbe->entry);
297281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	data = mk_pmb_data(pmbe->entry);
298281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt
299281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	jump_to_uncached();
300281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt
30190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	/* Set V-bit */
302281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	__raw_writel(pmbe->vpn | PMB_V, addr);
303281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	__raw_writel(pmbe->ppn | pmbe->flags | PMB_V, data);
304281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt
305281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	back_to_cached();
3060c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt}
3070c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
308d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundtstatic void __clear_pmb_entry(struct pmb_entry *pmbe)
3090c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt{
3102e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt	unsigned long addr, data;
3112e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt	unsigned long addr_val, data_val;
3120c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
3132e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt	addr = mk_pmb_addr(pmbe->entry);
3142e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt	data = mk_pmb_data(pmbe->entry);
3150c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
3162e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt	addr_val = __raw_readl(addr);
3172e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt	data_val = __raw_readl(data);
3180c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
3192e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt	/* Clear V-bit */
3202e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt	writel_uncached(addr_val & ~PMB_V, addr);
3212e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt	writel_uncached(data_val & ~PMB_V, data);
3220c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt}
3230c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
3243fe0f36c7edcd20af0a3cafc68bdd62534c0a7f0Matt Fleming#ifdef CONFIG_PM
325d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundtstatic void set_pmb_entry(struct pmb_entry *pmbe)
326d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt{
327d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	unsigned long flags;
328d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
329f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt	raw_spin_lock_irqsave(&pmbe->lock, flags);
330d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	__set_pmb_entry(pmbe);
331f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt	raw_spin_unlock_irqrestore(&pmbe->lock, flags);
332d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt}
3333fe0f36c7edcd20af0a3cafc68bdd62534c0a7f0Matt Fleming#endif /* CONFIG_PM */
334d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
33590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundtint pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys,
33690e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt		     unsigned long size, pgprot_t prot)
33790e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt{
338fc2bdefdde89b54d8fcde7bbf7d0adc0ce5cb044Matt Fleming	struct pmb_entry *pmbp, *pmbe;
339281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	unsigned long orig_addr, orig_size;
340a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt	unsigned long flags, pmb_flags;
34190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	int i, mapped;
34290e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt
343dfbca89987b74c34d9b1a2414b0e5ccee65347e0Paul Mundt	if (size < SZ_16M)
344dfbca89987b74c34d9b1a2414b0e5ccee65347e0Paul Mundt		return -EINVAL;
3456eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	if (!pmb_addr_valid(vaddr, size))
3466eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt		return -EFAULT;
347a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt	if (pmb_mapping_exists(vaddr, phys, size))
348a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		return 0;
3497bdda6209f224aa784a036df54b22cb338d2e859Paul Mundt
350281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	orig_addr = vaddr;
351281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	orig_size = size;
352281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt
353281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	flush_tlb_kernel_range(vaddr, vaddr + size);
354281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt
35590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	pmb_flags = pgprot_to_pmb_flags(prot);
3566eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	pmbp = NULL;
357d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt
358a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt	do {
359a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		for (i = mapped = 0; i < ARRAY_SIZE(pmb_sizes); i++) {
360a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			if (size < pmb_sizes[i].size)
361a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt				continue;
362d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt
363a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			pmbe = pmb_alloc(vaddr, phys, pmb_flags |
364a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt					 pmb_sizes[i].flag, PMB_NO_ENTRY);
365a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			if (IS_ERR(pmbe)) {
366a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt				pmb_unmap_entry(pmbp, mapped);
367a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt				return PTR_ERR(pmbe);
368a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			}
369d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
370f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt			raw_spin_lock_irqsave(&pmbe->lock, flags);
371d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt
372a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			pmbe->size = pmb_sizes[i].size;
373d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt
374a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			__set_pmb_entry(pmbe);
375d7813bc9e8e384f5a293b05c095c799d41af3668Paul Mundt
376a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			phys	+= pmbe->size;
377a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			vaddr	+= pmbe->size;
378a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			size	-= pmbe->size;
379d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt
380a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			/*
381a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			 * Link adjacent entries that span multiple PMB
382a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			 * entries for easier tear-down.
383a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			 */
384a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			if (likely(pmbp)) {
385f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt				raw_spin_lock_nested(&pmbp->lock,
386f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt						     SINGLE_DEPTH_NESTING);
387a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt				pmbp->link = pmbe;
388f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt				raw_spin_unlock(&pmbp->lock);
389a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			}
390a2767cfb1d9d97c3f861743f1ad595a80b75ec99Matt Fleming
391a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			pmbp = pmbe;
392d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
393a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			/*
394a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			 * Instead of trying smaller sizes on every
395a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			 * iteration (even if we succeed in allocating
396a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			 * space), try using pmb_sizes[i].size again.
397a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			 */
398a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			i--;
399a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt			mapped++;
400d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt
401f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt			raw_spin_unlock_irqrestore(&pmbe->lock, flags);
402a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt		}
403a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt	} while (size >= SZ_16M);
404d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt
405281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	flush_cache_vmap(orig_addr, orig_addr + orig_size);
406281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt
4076eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	return 0;
4086eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt}
4096eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt
4106eb3c735d29e799810ce82118f9260d0044327b7Paul Mundtvoid __iomem *pmb_remap_caller(phys_addr_t phys, unsigned long size,
4116eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt			       pgprot_t prot, void *caller)
4126eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt{
413281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	unsigned long vaddr;
4146eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	phys_addr_t offset, last_addr;
4156eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	phys_addr_t align_mask;
4166eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	unsigned long aligned;
4176eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	struct vm_struct *area;
4186eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	int i, ret;
4196eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt
4206eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	if (!pmb_iomapping_enabled)
4216eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt		return NULL;
4226eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt
4236eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	/*
4246eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	 * Small mappings need to go through the TLB.
4256eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	 */
4266eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	if (size < SZ_16M)
4276eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt		return ERR_PTR(-EINVAL);
4286eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	if (!pmb_prot_valid(prot))
4296eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt		return ERR_PTR(-EINVAL);
4306eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt
4316eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
4326eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt		if (size >= pmb_sizes[i].size)
4336eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt			break;
4346eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt
4356eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	last_addr = phys + size;
4366eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	align_mask = ~(pmb_sizes[i].size - 1);
4376eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	offset = phys & ~align_mask;
4386eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	phys &= align_mask;
4396eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	aligned = ALIGN(last_addr, pmb_sizes[i].size) - phys;
4406eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt
441281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	/*
442281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	 * XXX: This should really start from uncached_end, but this
443281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	 * causes the MMU to reset, so for now we restrict it to the
444281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	 * 0xb000...0xc000 range.
445281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	 */
446281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	area = __get_vm_area_caller(aligned, VM_IOREMAP, 0xb0000000,
4476eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt				    P3SEG, caller);
4486eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	if (!area)
4496eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt		return NULL;
4506eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt
4516eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	area->phys_addr = phys;
452281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	vaddr = (unsigned long)area->addr;
4536eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt
4546eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt	ret = pmb_bolt_mapping(vaddr, phys, size, prot);
455a1042aa248e4ea7f39d5ce13f080cbf3b6c42618Paul Mundt	if (unlikely(ret != 0))
4566eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt		return ERR_PTR(ret);
4576eb3c735d29e799810ce82118f9260d0044327b7Paul Mundt
458281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt	return (void __iomem *)(offset + (char *)vaddr);
459d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt}
460d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt
46190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundtint pmb_unmap(void __iomem *addr)
462d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt{
463d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	struct pmb_entry *pmbe = NULL;
46490e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	unsigned long vaddr = (unsigned long __force)addr;
46590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	int i, found = 0;
466d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt
467d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	read_lock(&pmb_rwlock);
468d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
469edd7de803c79c7df117bf3f0e22ffdba1b1ef256Matt Fleming	for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
47051becfd96287b3913b13075699433730984e2f4fPaul Mundt		if (test_bit(i, pmb_map)) {
471edd7de803c79c7df117bf3f0e22ffdba1b1ef256Matt Fleming			pmbe = &pmb_entry_list[i];
47290e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt			if (pmbe->vpn == vaddr) {
47390e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt				found = 1;
474edd7de803c79c7df117bf3f0e22ffdba1b1ef256Matt Fleming				break;
47590e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt			}
476edd7de803c79c7df117bf3f0e22ffdba1b1ef256Matt Fleming		}
477edd7de803c79c7df117bf3f0e22ffdba1b1ef256Matt Fleming	}
478d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
479d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	read_unlock(&pmb_rwlock);
480d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
48190e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	if (found) {
48290e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt		pmb_unmap_entry(pmbe, NR_PMB_ENTRIES);
48390e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt		return 0;
48490e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	}
485d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt
48690e7d649d86f21d478dc134f74c88e19dd472393Paul Mundt	return -EINVAL;
487d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt}
488d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
489d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundtstatic void __pmb_unmap_entry(struct pmb_entry *pmbe, int depth)
490d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt{
491d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt	do {
492d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt		struct pmb_entry *pmblink = pmbe;
493d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt
494067784f6239e08a084b4d8d597e14435331eae51Matt Fleming		/*
495067784f6239e08a084b4d8d597e14435331eae51Matt Fleming		 * We may be called before this pmb_entry has been
496067784f6239e08a084b4d8d597e14435331eae51Matt Fleming		 * entered into the PMB table via set_pmb_entry(), but
497067784f6239e08a084b4d8d597e14435331eae51Matt Fleming		 * that's OK because we've allocated a unique slot for
498067784f6239e08a084b4d8d597e14435331eae51Matt Fleming		 * this entry in pmb_alloc() (even if we haven't filled
499067784f6239e08a084b4d8d597e14435331eae51Matt Fleming		 * it yet).
500067784f6239e08a084b4d8d597e14435331eae51Matt Fleming		 *
501d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt		 * Therefore, calling __clear_pmb_entry() is safe as no
502067784f6239e08a084b4d8d597e14435331eae51Matt Fleming		 * other mapping can be using that slot.
503067784f6239e08a084b4d8d597e14435331eae51Matt Fleming		 */
504d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt		__clear_pmb_entry(pmbe);
505fc2bdefdde89b54d8fcde7bbf7d0adc0ce5cb044Matt Fleming
506281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt		flush_cache_vunmap(pmbe->vpn, pmbe->vpn + pmbe->size);
507281983d6ff2674ca2e4868de628c65809d84fa4cPaul Mundt
508d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt		pmbe = pmblink->link;
509d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt
510d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt		pmb_free(pmblink);
511d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	} while (pmbe && --depth);
512d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt}
513d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
514d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundtstatic void pmb_unmap_entry(struct pmb_entry *pmbe, int depth)
515d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt{
516d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	unsigned long flags;
517d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
518d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	if (unlikely(!pmbe))
519d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		return;
520d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
521d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	write_lock_irqsave(&pmb_rwlock, flags);
522d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	__pmb_unmap_entry(pmbe, depth);
523d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt	write_unlock_irqrestore(&pmb_rwlock, flags);
524d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt}
525d7cdc9e8ac82c43fdcd4fde6b5b53d2dcba7f707Paul Mundt
526d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundtstatic void __init pmb_notify(void)
52720b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming{
528d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	int i;
52920b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming
530efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt	pr_info("PMB: boot mappings:\n");
53120b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming
532d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	read_lock(&pmb_rwlock);
533d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
534d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
535d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		struct pmb_entry *pmbe;
536d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
537d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		if (!test_bit(i, pmb_map))
538d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			continue;
539d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
540d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		pmbe = &pmb_entry_list[i];
541d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
542d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		pr_info("       0x%08lx -> 0x%08lx [ %4ldMB %2scached ]\n",
543d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			pmbe->vpn >> PAGE_SHIFT, pmbe->ppn >> PAGE_SHIFT,
544d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			pmbe->size >> 20, (pmbe->flags & PMB_C) ? "" : "un");
545d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	}
546d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
547d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	read_unlock(&pmb_rwlock);
548d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt}
549d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
550d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt/*
551d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt * Sync our software copy of the PMB mappings with those in hardware. The
552d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt * mappings in the hardware PMB were either set up by the bootloader or
553d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt * very early on by the kernel.
554d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt */
555d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundtstatic void __init pmb_synchronize(void)
556d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt{
557d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	struct pmb_entry *pmbp = NULL;
558d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	int i, j;
559d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
5603d467676abf5f01f5ee99056273a58486968e252Matt Fleming	/*
561efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt	 * Run through the initial boot mappings, log the established
562efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt	 * ones, and blow away anything that falls outside of the valid
563efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt	 * PPN range. Specifically, we only care about existing mappings
564efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt	 * that impact the cached/uncached sections.
5653d467676abf5f01f5ee99056273a58486968e252Matt Fleming	 *
566efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt	 * Note that touching these can be a bit of a minefield; the boot
567efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt	 * loader can establish multi-page mappings with the same caching
568efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt	 * attributes, so we need to ensure that we aren't modifying a
569efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt	 * mapping that we're presently executing from, or may execute
570efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt	 * from in the case of straddling page boundaries.
5713d467676abf5f01f5ee99056273a58486968e252Matt Fleming	 *
572efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt	 * In the future we will have to tidy up after the boot loader by
573efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt	 * jumping between the cached and uncached mappings and tearing
574efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt	 * down alternating mappings while executing from the other.
5753d467676abf5f01f5ee99056273a58486968e252Matt Fleming	 */
57651becfd96287b3913b13075699433730984e2f4fPaul Mundt	for (i = 0; i < NR_PMB_ENTRIES; i++) {
5773d467676abf5f01f5ee99056273a58486968e252Matt Fleming		unsigned long addr, data;
5783d467676abf5f01f5ee99056273a58486968e252Matt Fleming		unsigned long addr_val, data_val;
579efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt		unsigned long ppn, vpn, flags;
580d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt		unsigned long irqflags;
581d7813bc9e8e384f5a293b05c095c799d41af3668Paul Mundt		unsigned int size;
582efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt		struct pmb_entry *pmbe;
58320b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming
5843d467676abf5f01f5ee99056273a58486968e252Matt Fleming		addr = mk_pmb_addr(i);
5853d467676abf5f01f5ee99056273a58486968e252Matt Fleming		data = mk_pmb_data(i);
58620b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming
5873d467676abf5f01f5ee99056273a58486968e252Matt Fleming		addr_val = __raw_readl(addr);
5883d467676abf5f01f5ee99056273a58486968e252Matt Fleming		data_val = __raw_readl(data);
58920b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming
5903d467676abf5f01f5ee99056273a58486968e252Matt Fleming		/*
5913d467676abf5f01f5ee99056273a58486968e252Matt Fleming		 * Skip over any bogus entries
5923d467676abf5f01f5ee99056273a58486968e252Matt Fleming		 */
5933d467676abf5f01f5ee99056273a58486968e252Matt Fleming		if (!(data_val & PMB_V) || !(addr_val & PMB_V))
5943d467676abf5f01f5ee99056273a58486968e252Matt Fleming			continue;
59520b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming
5963d467676abf5f01f5ee99056273a58486968e252Matt Fleming		ppn = data_val & PMB_PFN_MASK;
5973d467676abf5f01f5ee99056273a58486968e252Matt Fleming		vpn = addr_val & PMB_PFN_MASK;
598a0ab36689a36e583b6e736f1c99ac8c9aebdad59Paul Mundt
5993d467676abf5f01f5ee99056273a58486968e252Matt Fleming		/*
6003d467676abf5f01f5ee99056273a58486968e252Matt Fleming		 * Only preserve in-range mappings.
6013d467676abf5f01f5ee99056273a58486968e252Matt Fleming		 */
602efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt		if (!pmb_ppn_in_range(ppn)) {
6033d467676abf5f01f5ee99056273a58486968e252Matt Fleming			/*
6043d467676abf5f01f5ee99056273a58486968e252Matt Fleming			 * Invalidate anything out of bounds.
6053d467676abf5f01f5ee99056273a58486968e252Matt Fleming			 */
6062e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt			writel_uncached(addr_val & ~PMB_V, addr);
6072e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt			writel_uncached(data_val & ~PMB_V, data);
608efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt			continue;
6093d467676abf5f01f5ee99056273a58486968e252Matt Fleming		}
610efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt
611efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt		/*
612efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt		 * Update the caching attributes if necessary
613efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt		 */
614efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt		if (data_val & PMB_C) {
6150065b96775f1eff167a2c3343a41582e8fab4c6cPaul Mundt			data_val &= ~PMB_CACHE_MASK;
6160065b96775f1eff167a2c3343a41582e8fab4c6cPaul Mundt			data_val |= pmb_cache_flags();
6172e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt
6182e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt			writel_uncached(data_val, data);
619efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt		}
620efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt
621d7813bc9e8e384f5a293b05c095c799d41af3668Paul Mundt		size = data_val & PMB_SZ_MASK;
622d7813bc9e8e384f5a293b05c095c799d41af3668Paul Mundt		flags = size | (data_val & PMB_CACHE_MASK);
623efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt
624efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt		pmbe = pmb_alloc(vpn, ppn, flags, i);
625efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt		if (IS_ERR(pmbe)) {
626efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt			WARN_ON_ONCE(1);
627efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt			continue;
628efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt		}
629efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt
630f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt		raw_spin_lock_irqsave(&pmbe->lock, irqflags);
631d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
632d7813bc9e8e384f5a293b05c095c799d41af3668Paul Mundt		for (j = 0; j < ARRAY_SIZE(pmb_sizes); j++)
633d7813bc9e8e384f5a293b05c095c799d41af3668Paul Mundt			if (pmb_sizes[j].flag == size)
634d7813bc9e8e384f5a293b05c095c799d41af3668Paul Mundt				pmbe->size = pmb_sizes[j].size;
635d7813bc9e8e384f5a293b05c095c799d41af3668Paul Mundt
636d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt		if (pmbp) {
637f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt			raw_spin_lock_nested(&pmbp->lock, SINGLE_DEPTH_NESTING);
638d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt			/*
639d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt			 * Compare the previous entry against the current one to
640d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt			 * see if the entries span a contiguous mapping. If so,
641d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			 * setup the entry links accordingly. Compound mappings
642d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			 * are later coalesced.
643d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt			 */
644d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			if (pmb_can_merge(pmbp, pmbe))
645d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt				pmbp->link = pmbe;
646f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt			raw_spin_unlock(&pmbp->lock);
647d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt		}
648d7813bc9e8e384f5a293b05c095c799d41af3668Paul Mundt
649d7813bc9e8e384f5a293b05c095c799d41af3668Paul Mundt		pmbp = pmbe;
650d7813bc9e8e384f5a293b05c095c799d41af3668Paul Mundt
651f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt		raw_spin_unlock_irqrestore(&pmbe->lock, irqflags);
652d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	}
653d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt}
654d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
655d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundtstatic void __init pmb_merge(struct pmb_entry *head)
656d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt{
657d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	unsigned long span, newsize;
658d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	struct pmb_entry *tail;
659d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	int i = 1, depth = 0;
660d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
661d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	span = newsize = head->size;
662efd54ea315f645ef318708aab5714a5f1f432d03Paul Mundt
663d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	tail = head->link;
664d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	while (tail) {
665d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		span += tail->size;
666d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
667d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		if (pmb_size_valid(span)) {
668d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			newsize = span;
669d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			depth = i;
670d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		}
671d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
672d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		/* This is the end of the line.. */
673d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		if (!tail->link)
674d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			break;
675d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
676d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		tail = tail->link;
677d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		i++;
678a0ab36689a36e583b6e736f1c99ac8c9aebdad59Paul Mundt	}
679a0ab36689a36e583b6e736f1c99ac8c9aebdad59Paul Mundt
680d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	/*
681d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	 * The merged page size must be valid.
682d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	 */
683c7b03fa0bdc04e00bfbdc4cc69da144b11108f37Matt Fleming	if (!depth || !pmb_size_valid(newsize))
684d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		return;
685d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
686d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	head->flags &= ~PMB_SZ_MASK;
687d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	head->flags |= pmb_size_to_flags(newsize);
688d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
689d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	head->size = newsize;
690d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
691d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	__pmb_unmap_entry(head->link, depth);
692d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	__set_pmb_entry(head);
693a0ab36689a36e583b6e736f1c99ac8c9aebdad59Paul Mundt}
694a0ab36689a36e583b6e736f1c99ac8c9aebdad59Paul Mundt
695d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundtstatic void __init pmb_coalesce(void)
696a0ab36689a36e583b6e736f1c99ac8c9aebdad59Paul Mundt{
697d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	unsigned long flags;
698d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	int i;
699d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
700d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	write_lock_irqsave(&pmb_rwlock, flags);
701d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
702d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
703d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		struct pmb_entry *pmbe;
704d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
705d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		if (!test_bit(i, pmb_map))
706d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			continue;
707d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
708d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		pmbe = &pmb_entry_list[i];
709d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
710d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		/*
711d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		 * We're only interested in compound mappings
712d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		 */
713d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		if (!pmbe->link)
714d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			continue;
715d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
716d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		/*
717d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		 * Nothing to do if it already uses the largest possible
718d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		 * page size.
719d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		 */
720d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		if (pmbe->size == SZ_512M)
721d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			continue;
722d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
723d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		pmb_merge(pmbe);
724d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	}
725d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
726d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	write_unlock_irqrestore(&pmb_rwlock, flags);
727d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt}
728d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
729d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt#ifdef CONFIG_UNCACHED_MAPPING
730d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundtstatic void __init pmb_resize(void)
731d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt{
732d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	int i;
733a0ab36689a36e583b6e736f1c99ac8c9aebdad59Paul Mundt
734a0ab36689a36e583b6e736f1c99ac8c9aebdad59Paul Mundt	/*
735d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	 * If the uncached mapping was constructed by the kernel, it will
736d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	 * already be a reasonable size.
737a0ab36689a36e583b6e736f1c99ac8c9aebdad59Paul Mundt	 */
738d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	if (uncached_size == SZ_16M)
739d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		return;
740d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
741d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	read_lock(&pmb_rwlock);
742d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
743d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
744d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		struct pmb_entry *pmbe;
745d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		unsigned long flags;
746d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
747d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		if (!test_bit(i, pmb_map))
748d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			continue;
749d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
750d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		pmbe = &pmb_entry_list[i];
751d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
752d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		if (pmbe->vpn != uncached_start)
753d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt			continue;
754d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
755d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		/*
756d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		 * Found it, now resize it.
757d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		 */
758f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt		raw_spin_lock_irqsave(&pmbe->lock, flags);
759d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
760d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		pmbe->size = SZ_16M;
761d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		pmbe->flags &= ~PMB_SZ_MASK;
762d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		pmbe->flags |= pmb_size_to_flags(pmbe->size);
763d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
764d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		uncached_resize(pmbe->size);
765d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
766d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt		__set_pmb_entry(pmbe);
767d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
768f7fcec93b619337feb9da829b8a9ab6ba86393bcPaul Mundt		raw_spin_unlock_irqrestore(&pmbe->lock, flags);
769d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	}
770d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
7710e6f989ba83e6fa64e979d3488f01670b8be7959Julia Lawall	read_unlock(&pmb_rwlock);
772d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt}
773d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt#endif
774d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
7754cfa8e75d6854699597e21fd570721d63f899934Paul Mundtstatic int __init early_pmb(char *p)
7764cfa8e75d6854699597e21fd570721d63f899934Paul Mundt{
7774cfa8e75d6854699597e21fd570721d63f899934Paul Mundt	if (!p)
7784cfa8e75d6854699597e21fd570721d63f899934Paul Mundt		return 0;
7794cfa8e75d6854699597e21fd570721d63f899934Paul Mundt
7804cfa8e75d6854699597e21fd570721d63f899934Paul Mundt	if (strstr(p, "iomap"))
7814cfa8e75d6854699597e21fd570721d63f899934Paul Mundt		pmb_iomapping_enabled = 1;
7824cfa8e75d6854699597e21fd570721d63f899934Paul Mundt
7834cfa8e75d6854699597e21fd570721d63f899934Paul Mundt	return 0;
7844cfa8e75d6854699597e21fd570721d63f899934Paul Mundt}
7854cfa8e75d6854699597e21fd570721d63f899934Paul Mundtearly_param("pmb", early_pmb);
7864cfa8e75d6854699597e21fd570721d63f899934Paul Mundt
787d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundtvoid __init pmb_init(void)
788d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt{
789d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	/* Synchronize software state */
790d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	pmb_synchronize();
791d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
792d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	/* Attempt to combine compound mappings */
793d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	pmb_coalesce();
794d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
795d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt#ifdef CONFIG_UNCACHED_MAPPING
796d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	/* Resize initial mappings, if necessary */
797d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	pmb_resize();
798d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt#endif
799d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt
800d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	/* Log them */
801d01447b3197c2c470a14666be2c640407bbbfec7Paul Mundt	pmb_notify();
8023d467676abf5f01f5ee99056273a58486968e252Matt Fleming
8032e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt	writel_uncached(0, PMB_IRMCR);
804a0ab36689a36e583b6e736f1c99ac8c9aebdad59Paul Mundt
805a0ab36689a36e583b6e736f1c99ac8c9aebdad59Paul Mundt	/* Flush out the TLB */
806b5b6c7eea1124de5b110a48ac62650a690ed2419Matt Fleming	local_flush_tlb_all();
8072e450643d70b62e0192577681b227d7d5d2efa45Paul Mundt	ctrl_barrier();
80820b5014b3e5fe7b874a3f6a1dc03b0c21cb222cdMatt Fleming}
8090c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8102efa53b269ec1e9289a108e1506f53f6f1de440bPaul Mundtbool __in_29bit_mode(void)
8112efa53b269ec1e9289a108e1506f53f6f1de440bPaul Mundt{
8122efa53b269ec1e9289a108e1506f53f6f1de440bPaul Mundt        return (__raw_readl(PMB_PASCR) & PASCR_SE) == 0;
8132efa53b269ec1e9289a108e1506f53f6f1de440bPaul Mundt}
8142efa53b269ec1e9289a108e1506f53f6f1de440bPaul Mundt
8150c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundtstatic int pmb_seq_show(struct seq_file *file, void *iter)
8160c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt{
8170c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	int i;
8180c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8190c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	seq_printf(file, "V: Valid, C: Cacheable, WT: Write-Through\n"
8200c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt			 "CB: Copy-Back, B: Buffered, UB: Unbuffered\n");
8210c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	seq_printf(file, "ety   vpn  ppn  size   flags\n");
8220c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8230c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	for (i = 0; i < NR_PMB_ENTRIES; i++) {
8240c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt		unsigned long addr, data;
8250c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt		unsigned int size;
8260c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt		char *sz_str = NULL;
8270c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8289d56dd3b083a3bec56e9da35ce07baca81030b03Paul Mundt		addr = __raw_readl(mk_pmb_addr(i));
8299d56dd3b083a3bec56e9da35ce07baca81030b03Paul Mundt		data = __raw_readl(mk_pmb_data(i));
8300c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8310c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt		size = data & PMB_SZ_MASK;
8320c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt		sz_str = (size == PMB_SZ_16M)  ? " 16MB":
8330c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt			 (size == PMB_SZ_64M)  ? " 64MB":
8340c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt			 (size == PMB_SZ_128M) ? "128MB":
8350c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt					         "512MB";
8360c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8370c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt		/* 02: V 0x88 0x08 128MB C CB  B */
8380c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt		seq_printf(file, "%02d: %c 0x%02lx 0x%02lx %s %c %s %s\n",
8390c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt			   i, ((addr & PMB_V) && (data & PMB_V)) ? 'V' : ' ',
8400c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt			   (addr >> 24) & 0xff, (data >> 24) & 0xff,
8410c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt			   sz_str, (data & PMB_C) ? 'C' : ' ',
8420c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt			   (data & PMB_WT) ? "WT" : "CB",
8430c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt			   (data & PMB_UB) ? "UB" : " B");
8440c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	}
8450c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8460c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	return 0;
8470c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt}
8480c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8490c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundtstatic int pmb_debugfs_open(struct inode *inode, struct file *file)
8500c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt{
8510c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	return single_open(file, pmb_seq_show, NULL);
8520c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt}
8530c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8545dfe4c964a0dd7bb3a1d64a4166835a153146207Arjan van de Venstatic const struct file_operations pmb_debugfs_fops = {
8550c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	.owner		= THIS_MODULE,
8560c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	.open		= pmb_debugfs_open,
8570c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	.read		= seq_read,
8580c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	.llseek		= seq_lseek,
85945dabf1427a0a876f733b07239ade1bdb0e06010Li Zefan	.release	= single_release,
8600c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt};
8610c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8620c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundtstatic int __init pmb_debugfs_init(void)
8630c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt{
8640c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	struct dentry *dentry;
8650c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8660c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	dentry = debugfs_create_file("pmb", S_IFREG | S_IRUGO,
8673f224f4e057ce67713f3e7a8890f2fbe12d047a5Paul Mundt				     arch_debugfs_dir, NULL, &pmb_debugfs_fops);
86825627c7fd71269e2658b6872eef65719ee80b9aaZhaolei	if (!dentry)
86925627c7fd71269e2658b6872eef65719ee80b9aaZhaolei		return -ENOMEM;
8700c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt
8710c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt	return 0;
8720c7b1df69c62209db19d1279dd882b37c04c5c2fPaul Mundt}
87362c8cbbfc2367e706317f56ac21959120ae72773Pawel Mollsubsys_initcall(pmb_debugfs_init);
874a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZI
875a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZI#ifdef CONFIG_PM
876d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundtstatic void pmb_syscore_resume(void)
877a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZI{
878d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundt	struct pmb_entry *pmbe;
879edd7de803c79c7df117bf3f0e22ffdba1b1ef256Matt Fleming	int i;
880a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZI
881d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundt	read_lock(&pmb_rwlock);
882d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
883d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundt	for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
884d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundt		if (test_bit(i, pmb_map)) {
885d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundt			pmbe = &pmb_entry_list[i];
886d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundt			set_pmb_entry(pmbe);
887edd7de803c79c7df117bf3f0e22ffdba1b1ef256Matt Fleming		}
888a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZI	}
889d53a0d33bc3a50ea0e8dd1680a2e8435770b162aPaul Mundt
890d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundt	read_unlock(&pmb_rwlock);
891a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZI}
892a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZI
893d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundtstatic struct syscore_ops pmb_syscore_ops = {
894d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundt	.resume = pmb_syscore_resume,
895a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZI};
896a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZI
897a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZIstatic int __init pmb_sysdev_init(void)
898a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZI{
899d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundt	register_syscore_ops(&pmb_syscore_ops);
900d4cc183f7b9f639a048291e9cd95f0c255664b98Paul Mundt	return 0;
901a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZI}
902a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZIsubsys_initcall(pmb_sysdev_init);
903a83c0b739f3ad1887704cfa9f1ee5ee208cf1532Francesco VIRLINZI#endif
904