Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * MIPS SPRAM support
0004  *
0005  * Copyright (C) 2007, 2008 MIPS Technologies, Inc.
0006  */
0007 #include <linux/kernel.h>
0008 #include <linux/ptrace.h>
0009 #include <linux/stddef.h>
0010 
0011 #include <asm/fpu.h>
0012 #include <asm/mipsregs.h>
0013 #include <asm/r4kcache.h>
0014 #include <asm/hazards.h>
0015 
0016 /*
0017  * These definitions are correct for the 24K/34K/74K SPRAM sample
0018  * implementation. The 4KS interpreted the tags differently...
0019  */
0020 #define SPRAM_TAG0_ENABLE   0x00000080
0021 #define SPRAM_TAG0_PA_MASK  0xfffff000
0022 #define SPRAM_TAG1_SIZE_MASK    0xfffff000
0023 
0024 #define SPRAM_TAG_STRIDE    8
0025 
0026 #define ERRCTL_SPRAM        (1 << 28)
0027 
0028 /* errctl access */
0029 #define read_c0_errctl(x) read_c0_ecc(x)
0030 #define write_c0_errctl(x) write_c0_ecc(x)
0031 
0032 /*
0033  * Different semantics to the set_c0_* function built by __BUILD_SET_C0
0034  */
0035 static unsigned int bis_c0_errctl(unsigned int set)
0036 {
0037     unsigned int res;
0038     res = read_c0_errctl();
0039     write_c0_errctl(res | set);
0040     return res;
0041 }
0042 
0043 static void ispram_store_tag(unsigned int offset, unsigned int data)
0044 {
0045     unsigned int errctl;
0046 
0047     /* enable SPRAM tag access */
0048     errctl = bis_c0_errctl(ERRCTL_SPRAM);
0049     ehb();
0050 
0051     write_c0_taglo(data);
0052     ehb();
0053 
0054     cache_op(Index_Store_Tag_I, CKSEG0|offset);
0055     ehb();
0056 
0057     write_c0_errctl(errctl);
0058     ehb();
0059 }
0060 
0061 
0062 static unsigned int ispram_load_tag(unsigned int offset)
0063 {
0064     unsigned int data;
0065     unsigned int errctl;
0066 
0067     /* enable SPRAM tag access */
0068     errctl = bis_c0_errctl(ERRCTL_SPRAM);
0069     ehb();
0070     cache_op(Index_Load_Tag_I, CKSEG0 | offset);
0071     ehb();
0072     data = read_c0_taglo();
0073     ehb();
0074     write_c0_errctl(errctl);
0075     ehb();
0076 
0077     return data;
0078 }
0079 
0080 static void dspram_store_tag(unsigned int offset, unsigned int data)
0081 {
0082     unsigned int errctl;
0083 
0084     /* enable SPRAM tag access */
0085     errctl = bis_c0_errctl(ERRCTL_SPRAM);
0086     ehb();
0087     write_c0_dtaglo(data);
0088     ehb();
0089     cache_op(Index_Store_Tag_D, CKSEG0 | offset);
0090     ehb();
0091     write_c0_errctl(errctl);
0092     ehb();
0093 }
0094 
0095 
0096 static unsigned int dspram_load_tag(unsigned int offset)
0097 {
0098     unsigned int data;
0099     unsigned int errctl;
0100 
0101     errctl = bis_c0_errctl(ERRCTL_SPRAM);
0102     ehb();
0103     cache_op(Index_Load_Tag_D, CKSEG0 | offset);
0104     ehb();
0105     data = read_c0_dtaglo();
0106     ehb();
0107     write_c0_errctl(errctl);
0108     ehb();
0109 
0110     return data;
0111 }
0112 
0113 static void probe_spram(char *type,
0114         unsigned int base,
0115         unsigned int (*read)(unsigned int),
0116         void (*write)(unsigned int, unsigned int))
0117 {
0118     unsigned int firstsize = 0, lastsize = 0;
0119     unsigned int firstpa = 0, lastpa = 0, pa = 0;
0120     unsigned int offset = 0;
0121     unsigned int size, tag0, tag1;
0122     unsigned int enabled;
0123     int i;
0124 
0125     /*
0126      * The limit is arbitrary but avoids the loop running away if
0127      * the SPRAM tags are implemented differently
0128      */
0129 
0130     for (i = 0; i < 8; i++) {
0131         tag0 = read(offset);
0132         tag1 = read(offset+SPRAM_TAG_STRIDE);
0133         pr_debug("DBG %s%d: tag0=%08x tag1=%08x\n",
0134              type, i, tag0, tag1);
0135 
0136         size = tag1 & SPRAM_TAG1_SIZE_MASK;
0137 
0138         if (size == 0)
0139             break;
0140 
0141         if (i != 0) {
0142             /* tags may repeat... */
0143             if ((pa == firstpa && size == firstsize) ||
0144                 (pa == lastpa && size == lastsize))
0145                 break;
0146         }
0147 
0148         /* Align base with size */
0149         base = (base + size - 1) & ~(size-1);
0150 
0151         /* reprogram the base address base address and enable */
0152         tag0 = (base & SPRAM_TAG0_PA_MASK) | SPRAM_TAG0_ENABLE;
0153         write(offset, tag0);
0154 
0155         base += size;
0156 
0157         /* reread the tag */
0158         tag0 = read(offset);
0159         pa = tag0 & SPRAM_TAG0_PA_MASK;
0160         enabled = tag0 & SPRAM_TAG0_ENABLE;
0161 
0162         if (i == 0) {
0163             firstpa = pa;
0164             firstsize = size;
0165         }
0166 
0167         lastpa = pa;
0168         lastsize = size;
0169 
0170         if (strcmp(type, "DSPRAM") == 0) {
0171             unsigned int *vp = (unsigned int *)(CKSEG1 | pa);
0172             unsigned int v;
0173 #define TDAT    0x5a5aa5a5
0174             vp[0] = TDAT;
0175             vp[1] = ~TDAT;
0176 
0177             mb();
0178 
0179             v = vp[0];
0180             if (v != TDAT)
0181                 printk(KERN_ERR "vp=%p wrote=%08x got=%08x\n",
0182                        vp, TDAT, v);
0183             v = vp[1];
0184             if (v != ~TDAT)
0185                 printk(KERN_ERR "vp=%p wrote=%08x got=%08x\n",
0186                        vp+1, ~TDAT, v);
0187         }
0188 
0189         pr_info("%s%d: PA=%08x,Size=%08x%s\n",
0190             type, i, pa, size, enabled ? ",enabled" : "");
0191         offset += 2 * SPRAM_TAG_STRIDE;
0192     }
0193 }
0194 void spram_config(void)
0195 {
0196     unsigned int config0;
0197 
0198     switch (current_cpu_type()) {
0199     case CPU_24K:
0200     case CPU_34K:
0201     case CPU_74K:
0202     case CPU_1004K:
0203     case CPU_1074K:
0204     case CPU_INTERAPTIV:
0205     case CPU_PROAPTIV:
0206     case CPU_P5600:
0207     case CPU_QEMU_GENERIC:
0208     case CPU_I6400:
0209     case CPU_P6600:
0210         config0 = read_c0_config();
0211         /* FIXME: addresses are Malta specific */
0212         if (config0 & MIPS_CONF_ISP) {
0213             probe_spram("ISPRAM", 0x1c000000,
0214                     &ispram_load_tag, &ispram_store_tag);
0215         }
0216         if (config0 & MIPS_CONF_DSP)
0217             probe_spram("DSPRAM", 0x1c100000,
0218                     &dspram_load_tag, &dspram_store_tag);
0219     }
0220 }