162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * High memory support for Xtensa architecture
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General
562306a36Sopenharmony_ci * Public License.  See the file "COPYING" in the main directory of
662306a36Sopenharmony_ci * this archive for more details.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Copyright (C) 2014 Cadence Design Systems Inc.
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/export.h>
1262306a36Sopenharmony_ci#include <linux/highmem.h>
1362306a36Sopenharmony_ci#include <asm/tlbflush.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#if DCACHE_WAY_SIZE > PAGE_SIZE
1662306a36Sopenharmony_ciunsigned int last_pkmap_nr_arr[DCACHE_N_COLORS];
1762306a36Sopenharmony_ciwait_queue_head_t pkmap_map_wait_arr[DCACHE_N_COLORS];
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistatic void __init kmap_waitqueues_init(void)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	unsigned int i;
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(pkmap_map_wait_arr); ++i)
2462306a36Sopenharmony_ci		init_waitqueue_head(pkmap_map_wait_arr + i);
2562306a36Sopenharmony_ci}
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistatic inline enum fixed_addresses kmap_idx(int type, unsigned long color)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	int idx = (type + KM_MAX_IDX * smp_processor_id()) * DCACHE_N_COLORS;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	/*
3262306a36Sopenharmony_ci	 * The fixmap operates top down, so the color offset needs to be
3362306a36Sopenharmony_ci	 * reverse as well.
3462306a36Sopenharmony_ci	 */
3562306a36Sopenharmony_ci	return idx + DCACHE_N_COLORS - 1 - color;
3662306a36Sopenharmony_ci}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cienum fixed_addresses kmap_local_map_idx(int type, unsigned long pfn)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	return kmap_idx(type, DCACHE_ALIAS(pfn << PAGE_SHIFT));
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cienum fixed_addresses kmap_local_unmap_idx(int type, unsigned long addr)
4462306a36Sopenharmony_ci{
4562306a36Sopenharmony_ci	return kmap_idx(type, DCACHE_ALIAS(addr));
4662306a36Sopenharmony_ci}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#else
4962306a36Sopenharmony_cistatic inline void kmap_waitqueues_init(void) { }
5062306a36Sopenharmony_ci#endif
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_civoid __init kmap_init(void)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	/* Check if this memory layout is broken because PKMAP overlaps
5562306a36Sopenharmony_ci	 * page table.
5662306a36Sopenharmony_ci	 */
5762306a36Sopenharmony_ci	BUILD_BUG_ON(PKMAP_BASE < TLBTEMP_BASE_1 + TLBTEMP_SIZE);
5862306a36Sopenharmony_ci	kmap_waitqueues_init();
5962306a36Sopenharmony_ci}
60