File Index
Files and directories
Sign in
FILE

spram.c

File preview with syntax highlighting.

linux-6.19.14/arch/mips/kernel/spram.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * MIPS SPRAM support
  4 *
  5 * Copyright (C) 2007, 2008 MIPS Technologies, Inc.
  6 */
  7#include <linux/kernel.h>
  8#include <linux/ptrace.h>
  9#include <linux/stddef.h>
 10
 11#include <asm/fpu.h>
 12#include <asm/mipsregs.h>
 13#include <asm/r4kcache.h>
 14#include <asm/hazards.h>
 15#include <asm/spram.h>
 16
 17/*
 18 * These definitions are correct for the 24K/34K/74K SPRAM sample
 19 * implementation. The 4KS interpreted the tags differently...
 20 */
 21#define SPRAM_TAG0_ENABLE	0x00000080
 22#define SPRAM_TAG0_PA_MASK	0xfffff000
 23#define SPRAM_TAG1_SIZE_MASK	0xfffff000
 24
 25#define SPRAM_TAG_STRIDE	8
 26
 27#define ERRCTL_SPRAM		(1 << 28)
 28
 29/*
 30 * Different semantics to the set_c0_* function built by __BUILD_SET_C0
 31 */
 32static unsigned int bis_c0_errctl(unsigned int set)
 33{
 34	unsigned int res;
 35	res = read_c0_errctl();
 36	write_c0_errctl(res | set);
 37	return res;
 38}
 39
 40static void ispram_store_tag(unsigned int offset, unsigned int data)
 41{
 42	unsigned int errctl;
 43
 44	/* enable SPRAM tag access */
 45	errctl = bis_c0_errctl(ERRCTL_SPRAM);
 46	ehb();
 47
 48	write_c0_taglo(data);
 49	ehb();
 50
 51	cache_op(Index_Store_Tag_I, CKSEG0|offset);
 52	ehb();
 53
 54	write_c0_errctl(errctl);
 55	ehb();
 56}
 57
 58
 59static unsigned int ispram_load_tag(unsigned int offset)
 60{
 61	unsigned int data;
 62	unsigned int errctl;
 63
 64	/* enable SPRAM tag access */
 65	errctl = bis_c0_errctl(ERRCTL_SPRAM);
 66	ehb();
 67	cache_op(Index_Load_Tag_I, CKSEG0 | offset);
 68	ehb();
 69	data = read_c0_taglo();
 70	ehb();
 71	write_c0_errctl(errctl);
 72	ehb();
 73
 74	return data;
 75}
 76
 77static void dspram_store_tag(unsigned int offset, unsigned int data)
 78{
 79	unsigned int errctl;
 80
 81	/* enable SPRAM tag access */
 82	errctl = bis_c0_errctl(ERRCTL_SPRAM);
 83	ehb();
 84	write_c0_dtaglo(data);
 85	ehb();
 86	cache_op(Index_Store_Tag_D, CKSEG0 | offset);
 87	ehb();
 88	write_c0_errctl(errctl);
 89	ehb();
 90}
 91
 92
 93static unsigned int dspram_load_tag(unsigned int offset)
 94{
 95	unsigned int data;
 96	unsigned int errctl;
 97
 98	errctl = bis_c0_errctl(ERRCTL_SPRAM);
 99	ehb();
100	cache_op(Index_Load_Tag_D, CKSEG0 | offset);
101	ehb();
102	data = read_c0_dtaglo();
103	ehb();
104	write_c0_errctl(errctl);
105	ehb();
106
107	return data;
108}
109
110static void probe_spram(char *type,
111	    unsigned int base,
112	    unsigned int (*read)(unsigned int),
113	    void (*write)(unsigned int, unsigned int))
114{
115	unsigned int firstsize = 0, lastsize = 0;
116	unsigned int firstpa = 0, lastpa = 0, pa = 0;
117	unsigned int offset = 0;
118	unsigned int size, tag0, tag1;
119	unsigned int enabled;
120	int i;
121
122	/*
123	 * The limit is arbitrary but avoids the loop running away if
124	 * the SPRAM tags are implemented differently
125	 */
126
127	for (i = 0; i < 8; i++) {
128		tag0 = read(offset);
129		tag1 = read(offset+SPRAM_TAG_STRIDE);
130		pr_debug("DBG %s%d: tag0=%08x tag1=%08x\n",
131			 type, i, tag0, tag1);
132
133		size = tag1 & SPRAM_TAG1_SIZE_MASK;
134
135		if (size == 0)
136			break;
137
138		if (i != 0) {
139			/* tags may repeat... */
140			if ((pa == firstpa && size == firstsize) ||
141			    (pa == lastpa && size == lastsize))
142				break;
143		}
144
145		/* Align base with size */
146		base = (base + size - 1) & ~(size-1);
147
148		/* reprogram the base address base address and enable */
149		tag0 = (base & SPRAM_TAG0_PA_MASK) | SPRAM_TAG0_ENABLE;
150		write(offset, tag0);
151
152		base += size;
153
154		/* reread the tag */
155		tag0 = read(offset);
156		pa = tag0 & SPRAM_TAG0_PA_MASK;
157		enabled = tag0 & SPRAM_TAG0_ENABLE;
158
159		if (i == 0) {
160			firstpa = pa;
161			firstsize = size;
162		}
163
164		lastpa = pa;
165		lastsize = size;
166
167		if (strcmp(type, "DSPRAM") == 0) {
168			unsigned int *vp = (unsigned int *)(CKSEG1 | pa);
169			unsigned int v;
170#define TDAT	0x5a5aa5a5
171			vp[0] = TDAT;
172			vp[1] = ~TDAT;
173
174			mb();
175
176			v = vp[0];
177			if (v != TDAT)
178				printk(KERN_ERR "vp=%p wrote=%08x got=%08x\n",
179				       vp, TDAT, v);
180			v = vp[1];
181			if (v != ~TDAT)
182				printk(KERN_ERR "vp=%p wrote=%08x got=%08x\n",
183				       vp+1, ~TDAT, v);
184		}
185
186		pr_info("%s%d: PA=%08x,Size=%08x%s\n",
187			type, i, pa, size, enabled ? ",enabled" : "");
188		offset += 2 * SPRAM_TAG_STRIDE;
189	}
190}
191void spram_config(void)
192{
193	unsigned int config0;
194
195	switch (current_cpu_type()) {
196	case CPU_24K:
197	case CPU_34K:
198	case CPU_74K:
199	case CPU_1004K:
200	case CPU_1074K:
201	case CPU_INTERAPTIV:
202	case CPU_PROAPTIV:
203	case CPU_P5600:
204	case CPU_QEMU_GENERIC:
205	case CPU_I6400:
206	case CPU_P6600:
207		config0 = read_c0_config();
208		/* FIXME: addresses are Malta specific */
209		if (config0 & MIPS_CONF_ISP) {
210			probe_spram("ISPRAM", 0x1c000000,
211				    &ispram_load_tag, &ispram_store_tag);
212		}
213		if (config0 & MIPS_CONF_DSP)
214			probe_spram("DSPRAM", 0x1c100000,
215				    &dspram_load_tag, &dspram_store_tag);
216	}
217}
~/ Read-only file preview.