162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * viking.h:  Defines specific to the GNU/Viking MBUS module.
462306a36Sopenharmony_ci *            This is SRMMU stuff.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#ifndef _SPARC_VIKING_H
962306a36Sopenharmony_ci#define _SPARC_VIKING_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <asm/asi.h>
1262306a36Sopenharmony_ci#include <asm/mxcc.h>
1362306a36Sopenharmony_ci#include <asm/pgtable.h>
1462306a36Sopenharmony_ci#include <asm/pgtsrmmu.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/* Bits in the SRMMU control register for GNU/Viking modules.
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci * -----------------------------------------------------------
1962306a36Sopenharmony_ci * |impl-vers| RSV |TC|AC|SP|BM|PC|MBM|SB|IC|DC|PSO|RSV|NF|ME|
2062306a36Sopenharmony_ci * -----------------------------------------------------------
2162306a36Sopenharmony_ci *  31     24 23-17 16 15 14 13 12 11  10  9  8  7  6-2  1  0
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * TC: Tablewalk Cacheable -- 0 = Twalks are not cacheable in E-cache
2462306a36Sopenharmony_ci *                            1 = Twalks are cacheable in E-cache
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * GNU/Viking will only cache tablewalks in the E-cache (mxcc) if present
2762306a36Sopenharmony_ci * and never caches them internally (or so states the docs).  Therefore
2862306a36Sopenharmony_ci * for machines lacking an E-cache (ie. in MBUS mode) this bit must
2962306a36Sopenharmony_ci * remain cleared.
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * AC: Alternate Cacheable -- 0 = Passthru physical accesses not cacheable
3262306a36Sopenharmony_ci *                            1 = Passthru physical accesses cacheable
3362306a36Sopenharmony_ci *
3462306a36Sopenharmony_ci * This indicates whether accesses are cacheable when no cachable bit
3562306a36Sopenharmony_ci * is present in the pte when the processor is in boot-mode or the
3662306a36Sopenharmony_ci * access does not need pte's for translation (ie. pass-thru ASI's).
3762306a36Sopenharmony_ci * "Cachable" is only referring to E-cache (if present) and not the
3862306a36Sopenharmony_ci * on chip split I/D caches of the GNU/Viking.
3962306a36Sopenharmony_ci *
4062306a36Sopenharmony_ci * SP: SnooP Enable -- 0 = bus snooping off, 1 = bus snooping on
4162306a36Sopenharmony_ci *
4262306a36Sopenharmony_ci * This enables snooping on the GNU/Viking bus.  This must be on
4362306a36Sopenharmony_ci * for the hardware cache consistency mechanisms of the GNU/Viking
4462306a36Sopenharmony_ci * to work at all.  On non-mxcc GNU/Viking modules the split I/D
4562306a36Sopenharmony_ci * caches will snoop regardless of whether they are enabled, this
4662306a36Sopenharmony_ci * takes care of the case where the I or D or both caches are turned
4762306a36Sopenharmony_ci * off yet still contain valid data.  Note also that this bit does
4862306a36Sopenharmony_ci * not affect GNU/Viking store-buffer snoops, those happen if the
4962306a36Sopenharmony_ci * store-buffer is enabled no matter what.
5062306a36Sopenharmony_ci *
5162306a36Sopenharmony_ci * BM: Boot Mode -- 0 = not in boot mode, 1 = in boot mode
5262306a36Sopenharmony_ci *
5362306a36Sopenharmony_ci * This indicates whether the GNU/Viking is in boot-mode or not,
5462306a36Sopenharmony_ci * if it is then all instruction fetch physical addresses are
5562306a36Sopenharmony_ci * computed as 0xff0000000 + low 28 bits of requested address.
5662306a36Sopenharmony_ci * GNU/Viking boot-mode does not affect data accesses.  Also,
5762306a36Sopenharmony_ci * in boot mode instruction accesses bypass the split on chip I/D
5862306a36Sopenharmony_ci * caches, they may be cached by the GNU/MXCC if present and enabled.
5962306a36Sopenharmony_ci *
6062306a36Sopenharmony_ci * MBM: MBus Mode -- 0 = not in MBus mode, 1 = in MBus mode
6162306a36Sopenharmony_ci *
6262306a36Sopenharmony_ci * This indicated the GNU/Viking configuration present.  If in
6362306a36Sopenharmony_ci * MBUS mode, the GNU/Viking lacks a GNU/MXCC E-cache.  If it is
6462306a36Sopenharmony_ci * not then the GNU/Viking is on a module VBUS connected directly
6562306a36Sopenharmony_ci * to a GNU/MXCC cache controller.  The GNU/MXCC can be thus connected
6662306a36Sopenharmony_ci * to either an GNU/MBUS (sun4m) or the packet-switched GNU/XBus (sun4d).
6762306a36Sopenharmony_ci *
6862306a36Sopenharmony_ci * SB: StoreBuffer enable -- 0 = store buffer off, 1 = store buffer on
6962306a36Sopenharmony_ci *
7062306a36Sopenharmony_ci * The GNU/Viking store buffer allows the chip to continue execution
7162306a36Sopenharmony_ci * after a store even if the data cannot be placed in one of the
7262306a36Sopenharmony_ci * caches during that cycle.  If disabled, all stores operations
7362306a36Sopenharmony_ci * occur synchronously.
7462306a36Sopenharmony_ci *
7562306a36Sopenharmony_ci * IC: Instruction Cache -- 0 = off, 1 = on
7662306a36Sopenharmony_ci * DC: Data Cache -- 0 = off, 1 = 0n
7762306a36Sopenharmony_ci *
7862306a36Sopenharmony_ci * These bits enable the on-cpu GNU/Viking split I/D caches.  Note,
7962306a36Sopenharmony_ci * as mentioned above, these caches will snoop the bus in GNU/MBUS
8062306a36Sopenharmony_ci * configurations even when disabled to avoid data corruption.
8162306a36Sopenharmony_ci *
8262306a36Sopenharmony_ci * NF: No Fault -- 0 = faults generate traps, 1 = faults don't trap
8362306a36Sopenharmony_ci * ME: MMU enable -- 0 = mmu not translating, 1 = mmu translating
8462306a36Sopenharmony_ci *
8562306a36Sopenharmony_ci */
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci#define VIKING_MMUENABLE    0x00000001
8862306a36Sopenharmony_ci#define VIKING_NOFAULT      0x00000002
8962306a36Sopenharmony_ci#define VIKING_PSO          0x00000080
9062306a36Sopenharmony_ci#define VIKING_DCENABLE     0x00000100   /* Enable data cache */
9162306a36Sopenharmony_ci#define VIKING_ICENABLE     0x00000200   /* Enable instruction cache */
9262306a36Sopenharmony_ci#define VIKING_SBENABLE     0x00000400   /* Enable store buffer */
9362306a36Sopenharmony_ci#define VIKING_MMODE        0x00000800   /* MBUS mode */
9462306a36Sopenharmony_ci#define VIKING_PCENABLE     0x00001000   /* Enable parity checking */
9562306a36Sopenharmony_ci#define VIKING_BMODE        0x00002000
9662306a36Sopenharmony_ci#define VIKING_SPENABLE     0x00004000   /* Enable bus cache snooping */
9762306a36Sopenharmony_ci#define VIKING_ACENABLE     0x00008000   /* Enable alternate caching */
9862306a36Sopenharmony_ci#define VIKING_TCENABLE     0x00010000   /* Enable table-walks to be cached */
9962306a36Sopenharmony_ci#define VIKING_DPENABLE     0x00040000   /* Enable the data prefetcher */
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci/*
10262306a36Sopenharmony_ci * GNU/Viking Breakpoint Action Register fields.
10362306a36Sopenharmony_ci */
10462306a36Sopenharmony_ci#define VIKING_ACTION_MIX   0x00001000   /* Enable multiple instructions */
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci/*
10762306a36Sopenharmony_ci * GNU/Viking Cache Tags.
10862306a36Sopenharmony_ci */
10962306a36Sopenharmony_ci#define VIKING_PTAG_VALID   0x01000000   /* Cache block is valid */
11062306a36Sopenharmony_ci#define VIKING_PTAG_DIRTY   0x00010000   /* Block has been modified */
11162306a36Sopenharmony_ci#define VIKING_PTAG_SHARED  0x00000100   /* Shared with some other cache */
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci#ifndef __ASSEMBLY__
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic inline void viking_flush_icache(void)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	__asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"
11862306a36Sopenharmony_ci			     : /* no outputs */
11962306a36Sopenharmony_ci			     : "i" (ASI_M_IC_FLCLEAR)
12062306a36Sopenharmony_ci			     : "memory");
12162306a36Sopenharmony_ci}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cistatic inline void viking_flush_dcache(void)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	__asm__ __volatile__("sta %%g0, [%%g0] %0\n\t"
12662306a36Sopenharmony_ci			     : /* no outputs */
12762306a36Sopenharmony_ci			     : "i" (ASI_M_DC_FLCLEAR)
12862306a36Sopenharmony_ci			     : "memory");
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistatic inline void viking_unlock_icache(void)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	__asm__ __volatile__("sta %%g0, [%0] %1\n\t"
13462306a36Sopenharmony_ci			     : /* no outputs */
13562306a36Sopenharmony_ci			     : "r" (0x80000000), "i" (ASI_M_IC_FLCLEAR)
13662306a36Sopenharmony_ci			     : "memory");
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic inline void viking_unlock_dcache(void)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	__asm__ __volatile__("sta %%g0, [%0] %1\n\t"
14262306a36Sopenharmony_ci			     : /* no outputs */
14362306a36Sopenharmony_ci			     : "r" (0x80000000), "i" (ASI_M_DC_FLCLEAR)
14462306a36Sopenharmony_ci			     : "memory");
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic inline void viking_set_bpreg(unsigned long regval)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	__asm__ __volatile__("sta %0, [%%g0] %1\n\t"
15062306a36Sopenharmony_ci			     : /* no outputs */
15162306a36Sopenharmony_ci			     : "r" (regval), "i" (ASI_M_ACTION)
15262306a36Sopenharmony_ci			     : "memory");
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic inline unsigned long viking_get_bpreg(void)
15662306a36Sopenharmony_ci{
15762306a36Sopenharmony_ci	unsigned long regval;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	__asm__ __volatile__("lda [%%g0] %1, %0\n\t"
16062306a36Sopenharmony_ci			     : "=r" (regval)
16162306a36Sopenharmony_ci			     : "i" (ASI_M_ACTION));
16262306a36Sopenharmony_ci	return regval;
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistatic inline void viking_get_dcache_ptag(int set, int block,
16662306a36Sopenharmony_ci					      unsigned long *data)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	unsigned long ptag = ((set & 0x7f) << 5) | ((block & 0x3) << 26) |
16962306a36Sopenharmony_ci			     0x80000000;
17062306a36Sopenharmony_ci	unsigned long info, page;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	__asm__ __volatile__ ("ldda [%2] %3, %%g2\n\t"
17362306a36Sopenharmony_ci			      "or %%g0, %%g2, %0\n\t"
17462306a36Sopenharmony_ci			      "or %%g0, %%g3, %1\n\t"
17562306a36Sopenharmony_ci			      : "=r" (info), "=r" (page)
17662306a36Sopenharmony_ci			      : "r" (ptag), "i" (ASI_M_DATAC_TAG)
17762306a36Sopenharmony_ci			      : "g2", "g3");
17862306a36Sopenharmony_ci	data[0] = info;
17962306a36Sopenharmony_ci	data[1] = page;
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cistatic inline void viking_mxcc_turn_off_parity(unsigned long *mregp,
18362306a36Sopenharmony_ci						   unsigned long *mxcc_cregp)
18462306a36Sopenharmony_ci{
18562306a36Sopenharmony_ci	unsigned long mreg = *mregp;
18662306a36Sopenharmony_ci	unsigned long mxcc_creg = *mxcc_cregp;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	mreg &= ~(VIKING_PCENABLE);
18962306a36Sopenharmony_ci	mxcc_creg &= ~(MXCC_CTL_PARE);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	__asm__ __volatile__ ("set 1f, %%g2\n\t"
19262306a36Sopenharmony_ci			      "andcc %%g2, 4, %%g0\n\t"
19362306a36Sopenharmony_ci			      "bne 2f\n\t"
19462306a36Sopenharmony_ci			      " nop\n"
19562306a36Sopenharmony_ci			      "1:\n\t"
19662306a36Sopenharmony_ci			      "sta %0, [%%g0] %3\n\t"
19762306a36Sopenharmony_ci			      "sta %1, [%2] %4\n\t"
19862306a36Sopenharmony_ci			      "b 1f\n\t"
19962306a36Sopenharmony_ci			      " nop\n\t"
20062306a36Sopenharmony_ci			      "nop\n"
20162306a36Sopenharmony_ci			      "2:\n\t"
20262306a36Sopenharmony_ci			      "sta %0, [%%g0] %3\n\t"
20362306a36Sopenharmony_ci			      "sta %1, [%2] %4\n"
20462306a36Sopenharmony_ci			      "1:\n\t"
20562306a36Sopenharmony_ci			      : /* no output */
20662306a36Sopenharmony_ci			      : "r" (mreg), "r" (mxcc_creg),
20762306a36Sopenharmony_ci			        "r" (MXCC_CREG), "i" (ASI_M_MMUREGS),
20862306a36Sopenharmony_ci			        "i" (ASI_M_MXCC)
20962306a36Sopenharmony_ci			      : "g2", "memory", "cc");
21062306a36Sopenharmony_ci	*mregp = mreg;
21162306a36Sopenharmony_ci	*mxcc_cregp = mxcc_creg;
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_cistatic inline unsigned long viking_hwprobe(unsigned long vaddr)
21562306a36Sopenharmony_ci{
21662306a36Sopenharmony_ci	unsigned long val;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	vaddr &= PAGE_MASK;
21962306a36Sopenharmony_ci	/* Probe all MMU entries. */
22062306a36Sopenharmony_ci	__asm__ __volatile__("lda [%1] %2, %0\n\t"
22162306a36Sopenharmony_ci			     : "=r" (val)
22262306a36Sopenharmony_ci			     : "r" (vaddr | 0x400), "i" (ASI_M_FLUSH_PROBE));
22362306a36Sopenharmony_ci	if (!val)
22462306a36Sopenharmony_ci		return 0;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	/* Probe region. */
22762306a36Sopenharmony_ci	__asm__ __volatile__("lda [%1] %2, %0\n\t"
22862306a36Sopenharmony_ci			     : "=r" (val)
22962306a36Sopenharmony_ci			     : "r" (vaddr | 0x200), "i" (ASI_M_FLUSH_PROBE));
23062306a36Sopenharmony_ci	if ((val & SRMMU_ET_MASK) == SRMMU_ET_PTE) {
23162306a36Sopenharmony_ci		vaddr &= ~PGDIR_MASK;
23262306a36Sopenharmony_ci		vaddr >>= PAGE_SHIFT;
23362306a36Sopenharmony_ci		return val | (vaddr << 8);
23462306a36Sopenharmony_ci	}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	/* Probe segment. */
23762306a36Sopenharmony_ci	__asm__ __volatile__("lda [%1] %2, %0\n\t"
23862306a36Sopenharmony_ci			     : "=r" (val)
23962306a36Sopenharmony_ci			     : "r" (vaddr | 0x100), "i" (ASI_M_FLUSH_PROBE));
24062306a36Sopenharmony_ci	if ((val & SRMMU_ET_MASK) == SRMMU_ET_PTE) {
24162306a36Sopenharmony_ci		vaddr &= ~PMD_MASK;
24262306a36Sopenharmony_ci		vaddr >>= PAGE_SHIFT;
24362306a36Sopenharmony_ci		return val | (vaddr << 8);
24462306a36Sopenharmony_ci	}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	/* Probe page. */
24762306a36Sopenharmony_ci	__asm__ __volatile__("lda [%1] %2, %0\n\t"
24862306a36Sopenharmony_ci			     : "=r" (val)
24962306a36Sopenharmony_ci			     : "r" (vaddr), "i" (ASI_M_FLUSH_PROBE));
25062306a36Sopenharmony_ci	return val;
25162306a36Sopenharmony_ci}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci#endif /* !(_SPARC_VIKING_H) */
256