xref: /openbmc/linux/arch/xtensa/mm/highmem.c (revision cdd38c5f1ce4398ec58fec95904b75824daab7b5)
165559100SMax Filippov /*
265559100SMax Filippov  * High memory support for Xtensa architecture
365559100SMax Filippov  *
465559100SMax Filippov  * This file is subject to the terms and conditions of the GNU General
565559100SMax Filippov  * Public License.  See the file "COPYING" in the main directory of
665559100SMax Filippov  * this archive for more details.
765559100SMax Filippov  *
865559100SMax Filippov  * Copyright (C) 2014 Cadence Design Systems Inc.
965559100SMax Filippov  */
1065559100SMax Filippov 
1165559100SMax Filippov #include <linux/export.h>
1265559100SMax Filippov #include <linux/highmem.h>
1365559100SMax Filippov #include <asm/tlbflush.h>
1465559100SMax Filippov 
158504b503SMax Filippov #if DCACHE_WAY_SIZE > PAGE_SIZE
168504b503SMax Filippov unsigned int last_pkmap_nr_arr[DCACHE_N_COLORS];
178504b503SMax Filippov wait_queue_head_t pkmap_map_wait_arr[DCACHE_N_COLORS];
188504b503SMax Filippov 
kmap_waitqueues_init(void)198504b503SMax Filippov static void __init kmap_waitqueues_init(void)
208504b503SMax Filippov {
218504b503SMax Filippov 	unsigned int i;
228504b503SMax Filippov 
238504b503SMax Filippov 	for (i = 0; i < ARRAY_SIZE(pkmap_map_wait_arr); ++i)
248504b503SMax Filippov 		init_waitqueue_head(pkmap_map_wait_arr + i);
258504b503SMax Filippov }
268504b503SMax Filippov 
kmap_idx(int type,unsigned long color)2732544d9cSMax Filippov static inline enum fixed_addresses kmap_idx(int type, unsigned long color)
2832544d9cSMax Filippov {
29*1eb0616cSThomas Gleixner 	int idx = (type + KM_MAX_IDX * smp_processor_id()) * DCACHE_N_COLORS;
30*1eb0616cSThomas Gleixner 
31*1eb0616cSThomas Gleixner 	/*
32*1eb0616cSThomas Gleixner 	 * The fixmap operates top down, so the color offset needs to be
33*1eb0616cSThomas Gleixner 	 * reverse as well.
34*1eb0616cSThomas Gleixner 	 */
35*1eb0616cSThomas Gleixner 	return idx + DCACHE_N_COLORS - 1 - color;
3632544d9cSMax Filippov }
3732544d9cSMax Filippov 
kmap_local_map_idx(int type,unsigned long pfn)38629ed3f7SThomas Gleixner enum fixed_addresses kmap_local_map_idx(int type, unsigned long pfn)
3965559100SMax Filippov {
40629ed3f7SThomas Gleixner 	return kmap_idx(type, DCACHE_ALIAS(pfn << PAGE_SHIFT));
4165559100SMax Filippov }
4265559100SMax Filippov 
kmap_local_unmap_idx(int type,unsigned long addr)43629ed3f7SThomas Gleixner enum fixed_addresses kmap_local_unmap_idx(int type, unsigned long addr)
4465559100SMax Filippov {
45629ed3f7SThomas Gleixner 	return kmap_idx(type, DCACHE_ALIAS(addr));
4665559100SMax Filippov }
4765559100SMax Filippov 
48*1eb0616cSThomas Gleixner #else
kmap_waitqueues_init(void)49*1eb0616cSThomas Gleixner static inline void kmap_waitqueues_init(void) { }
50*1eb0616cSThomas Gleixner #endif
51*1eb0616cSThomas Gleixner 
kmap_init(void)5265559100SMax Filippov void __init kmap_init(void)
5365559100SMax Filippov {
5421596872SIra Weiny 	/* Check if this memory layout is broken because PKMAP overlaps
5521596872SIra Weiny 	 * page table.
5621596872SIra Weiny 	 */
5721596872SIra Weiny 	BUILD_BUG_ON(PKMAP_BASE < TLBTEMP_BASE_1 + TLBTEMP_SIZE);
588504b503SMax Filippov 	kmap_waitqueues_init();
5965559100SMax Filippov }
60