// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Modifications by Matt Porter (mporter@mvista.com) to support
 * PPC44x Book E processors.
 *
 * This file contains the routines for initializing the MMU
 * on the 4xx series of chips.
 *  -- paulus
 *
 *  Derived from arch/ppc/mm/init.c:
 *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
 *
 *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
 *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
 *    Copyright (C) 1996 Paul Mackerras
 *
 *  Derived from "arch/i386/mm/init.c"
 *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
 */

#include <linux/init.h>
#include <linux/memblock.h>

#include <asm/mmu.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
#include <asm/code-patching.h>
#include <asm/smp.h>

#include <mm/mmu_decl.h>

/* Used by the 44x TLB replacement exception handler.
 * Just needed it declared someplace.
 */
unsigned int tlb_44x_index; /* = 0 */
unsigned int tlb_44x_hwater = PPC44x_TLB_SIZE - 1 - PPC44x_EARLY_TLBS;
int icache_44x_need_flush;

unsigned long tlb_47x_boltmap[1024/8];

static void __init ppc44x_update_tlb_hwater(void)
{
	/* The TLB miss handlers hard codes the watermark in a cmpli
	 * instruction to improve performances rather than loading it
	 * from the global variable. Thus, we patch the instructions
	 * in the 2 TLB miss handlers when updating the value
	 */
	modify_instruction_site(&patch__tlb_44x_hwater_D, 0xffff, tlb_44x_hwater);
	modify_instruction_site(&patch__tlb_44x_hwater_I, 0xffff, tlb_44x_hwater);
}

/*
 * "Pins" a 256MB TLB entry in AS0 for kernel lowmem for 44x type MMU
 */
static void __init ppc44x_pin_tlb(unsigned int virt, unsigned int phys)
{
	unsigned int entry = tlb_44x_hwater--;

	ppc44x_update_tlb_hwater();

	mtspr(SPRN_MMUCR, 0);

	__asm__ __volatile__(
		"tlbwe	%2,%3,%4\n"
		"tlbwe	%1,%3,%5\n"
		"tlbwe	%0,%3,%6\n"
	:
	: "r" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G),
	  "r" (phys),
	  "r" (virt | PPC44x_TLB_VALID | PPC44x_TLB_256M),
	  "r" (entry),
	  "i" (PPC44x_TLB_PAGEID),
	  "i" (PPC44x_TLB_XLAT),
	  "i" (PPC44x_TLB_ATTRIB));
}

static int __init ppc47x_find_free_bolted(void)
{
	unsigned int mmube0 = mfspr(SPRN_MMUBE0);
	unsigned int mmube1 = mfspr(SPRN_MMUBE1);

	if (!(mmube0 & MMUBE0_VBE0))
		return 0;
	if (!(mmube0 & MMUBE0_VBE1))
		return 1;
	if (!(mmube0 & MMUBE0_VBE2))
		return 2;
	if (!(mmube1 & MMUBE1_VBE3))
		return 3;
	if (!(mmube1 & MMUBE1_VBE4))
		return 4;
	if (!(mmube1 & MMUBE1_VBE5))
		return 5;
	return -1;
}

static void __init ppc47x_update_boltmap(void)
{
	unsigned int mmube0 = mfspr(SPRN_MMUBE0);
	unsigned int mmube1 = mfspr(SPRN_MMUBE1);

	if (mmube0 & MMUBE0_VBE0)
		__set_bit((mmube0 >> MMUBE0_IBE0_SHIFT) & 0xff,
			  tlb_47x_boltmap);
	if (mmube0 & MMUBE0_VBE1)
		__set_bit((mmube0 >> MMUBE0_IBE1_SHIFT) & 0xff,
			  tlb_47x_boltmap);
	if (mmube0 & MMUBE0_VBE2)
		__set_bit((mmube0 >> MMUBE0_IBE2_SHIFT) & 0xff,
			  tlb_47x_boltmap);
	if (mmube1 & MMUBE1_VBE3)
		__set_bit((mmube1 >> MMUBE1_IBE3_SHIFT) & 0xff,
			  tlb_47x_boltmap);
	if (mmube1 & MMUBE1_VBE4)
		__set_bit((mmube1 >> MMUBE1_IBE4_SHIFT) & 0xff,
			  tlb_47x_boltmap);
	if (mmube1 & MMUBE1_VBE5)
		__set_bit((mmube1 >> MMUBE1_IBE5_SHIFT) & 0xff,
			  tlb_47x_boltmap);
}

/*
 * "Pins" a 256MB TLB entry in AS0 for kernel lowmem for 47x type MMU
 */
static void __init ppc47x_pin_tlb(unsigned int virt, unsigned int phys)
{
	unsigned int rA;
	int bolted;

	/* Base rA is HW way select, way 0, bolted bit set */
	rA = 0x88000000;

	/* Look for a bolted entry slot */
	bolted = ppc47x_find_free_bolted();
	BUG_ON(bolted < 0);

	/* Insert bolted slot number */
	rA |= bolted << 24;

	pr_debug("256M TLB entry for 0x%08x->0x%08x in bolt slot %d\n",
		 virt, phys, bolted);

	mtspr(SPRN_MMUCR, 0);

	__asm__ __volatile__(
		"tlbwe	%2,%3,0\n"
		"tlbwe	%1,%3,1\n"
		"tlbwe	%0,%3,2\n"
		:
		: "r" (PPC47x_TLB2_SW | PPC47x_TLB2_SR |
		       PPC47x_TLB2_SX
#ifdef CONFIG_SMP
		       | PPC47x_TLB2_M
#endif
		       ),
		  "r" (phys),
		  "r" (virt | PPC47x_TLB0_VALID | PPC47x_TLB0_256M),
		  "r" (rA));
}

void __init MMU_init_hw(void)
{
	/* This is not useful on 47x but won't hurt either */
	ppc44x_update_tlb_hwater();

	flush_instruction_cache();
}

unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
{
	unsigned long addr;
	unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1);

	/* Pin in enough TLBs to cover any lowmem not covered by the
	 * initial 256M mapping established in head_44x.S */
	for (addr = memstart + PPC_PIN_SIZE; addr < lowmem_end_addr;
	     addr += PPC_PIN_SIZE) {
		if (mmu_has_feature(MMU_FTR_TYPE_47x))
			ppc47x_pin_tlb(addr + PAGE_OFFSET, addr);
		else
			ppc44x_pin_tlb(addr + PAGE_OFFSET, addr);
	}
	if (mmu_has_feature(MMU_FTR_TYPE_47x)) {
		ppc47x_update_boltmap();

#ifdef DEBUG
		{
			int i;

			printk(KERN_DEBUG "bolted entries: ");
			for (i = 0; i < 255; i++) {
				if (test_bit(i, tlb_47x_boltmap))
					printk("%d ", i);
			}
			printk("\n");
		}
#endif /* DEBUG */
	}
	return total_lowmem;
}

void setup_initial_memory_limit(phys_addr_t first_memblock_base,
				phys_addr_t first_memblock_size)
{
	u64 size;

#ifndef CONFIG_NONSTATIC_KERNEL
	/* We don't currently support the first MEMBLOCK not mapping 0
	 * physical on those processors
	 */
	BUG_ON(first_memblock_base != 0);
#endif

	/* 44x has a 256M TLB entry pinned at boot */
	size = (min_t(u64, first_memblock_size, PPC_PIN_SIZE));
	memblock_set_current_limit(first_memblock_base + size);
}

#ifdef CONFIG_SMP
void __init mmu_init_secondary(int cpu)
{
	unsigned long addr;
	unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1);

	/* Pin in enough TLBs to cover any lowmem not covered by the
	 * initial 256M mapping established in head_44x.S
	 *
	 * WARNING: This is called with only the first 256M of the
	 * linear mapping in the TLB and we can't take faults yet
	 * so beware of what this code uses. It runs off a temporary
	 * stack. current (r2) isn't initialized, smp_processor_id()
	 * will not work, current thread info isn't accessible, ...
	 */
	for (addr = memstart + PPC_PIN_SIZE; addr < lowmem_end_addr;
	     addr += PPC_PIN_SIZE) {
		if (mmu_has_feature(MMU_FTR_TYPE_47x))
			ppc47x_pin_tlb(addr + PAGE_OFFSET, addr);
		else
			ppc44x_pin_tlb(addr + PAGE_OFFSET, addr);
	}
}
#endif /* CONFIG_SMP */
