1 /* $NetBSD: mq200machdep.c,v 1.1 2001/03/25 13:06:53 takemura Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 TAKEMURA Shin 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 32 #ifdef _KERNEL 33 #include <sys/param.h> 34 #include <sys/kernel.h> 35 #include <sys/systm.h> 36 #include <sys/device.h> 37 #else 38 #include <stdio.h> 39 #endif 40 #include <sys/types.h> 41 42 #include <machine/platid.h> 43 #include <machine/platid_mask.h> 44 45 #include "opt_mq200.h" 46 #include "mq200var.h" 47 #include "mq200reg.h" 48 #include "mq200priv.h" 49 50 #if MQ200_SETUPREGS 51 #define OP_(n) (((n) << 2) | 1) 52 #define OP_END OP_(1) 53 #define OP_MASK OP_(2) 54 #define OP_LOADPLLPARAM OP_(3) 55 #define OP_LOADFROMREG OP_(4) 56 #define OP_STORETOREG OP_(5) 57 #define OP_LOADIMM OP_(6) 58 #define OP_OR OP_(7) 59 60 static void mq200_setupregs(struct mq200_softc *sc, u_int32_t *ops); 61 62 static u_int32_t mcr530_init_ops[] = { 63 MQ200_PMCR, 0, /* power management control */ 64 MQ200_DCMISCR, MQ200_DCMISC_OSC_ENABLE | 65 MQ200_DCMISC_FASTPOWSEQ_DISABLE | 66 MQ200_DCMISC_OSCFREQ_12_25, 67 OP_END 68 }; 69 #endif /* MQ200_SETUPREGS */ 70 71 static struct mq200_clock_setting mcr530_clocks[] = { 72 /* CRT: off FP: off */ 73 { 74 MQ200_CLOCK_PLL1, /* memory clock */ 75 MQ200_CLOCK_PLL1, /* graphics engine clock */ 76 { 77 0, /* GC1(CRT) clock */ 78 0, /* GC2(FP) clock */ 79 }, 80 30000, /* PLL1 30MHz */ 81 0, /* PLL2 disable */ 82 0, /* PLL3 disable */ 83 }, 84 /* CRT: on FP: off */ 85 { 86 MQ200_CLOCK_PLL1, /* memory clock */ 87 MQ200_CLOCK_PLL2, /* graphics engine clock */ 88 { 89 MQ200_CLOCK_PLL3, /* GC1(CRT) clock */ 90 0, /* GC2(FP) clock */ 91 }, 92 83000, /* PLL1 83MHz */ 93 30000, /* PLL2 30MHz */ 94 -1, /* PLL3 will be set by GC1 */ 95 }, 96 /* CRT: off FP: on */ 97 { 98 MQ200_CLOCK_PLL1, /* memory clock */ 99 MQ200_CLOCK_PLL2, /* graphics engine clock */ 100 { 101 0, /* GC1(CRT) clock */ 102 MQ200_CLOCK_PLL2, /* GC2(FP) clock */ 103 }, 104 30000, /* PLL1 30MHz */ 105 18800, /* PLL2 18.8MHz */ 106 0, /* PLL3 disable */ 107 }, 108 /* CRT: on FP: on */ 109 { 110 MQ200_CLOCK_PLL1, /* memory clock */ 111 MQ200_CLOCK_PLL2, /* graphics engine clock */ 112 { 113 MQ200_CLOCK_PLL3, /* GC1(CRT) clock */ 114 MQ200_CLOCK_PLL2, /* GC2(FP) clock */ 115 }, 116 83000, /* PLL1 83MHz */ 117 18800, /* PLL2 18.8MHz */ 118 -1, /* PLL3 will be set by GC1 */ 119 }, 120 }; 121 122 static struct mq200_md_param machdep_params[] = { 123 { 124 &platid_mask_MACH_NEC_MCR_530, 125 640, 240, /* flat panel size */ 126 12288, /* base clock is 12.288 MHz */ 127 MQ200_MD_HAVECRT | MQ200_MD_HAVEFP, 128 #if MQ200_SETUPREGS 129 mcr530_init_ops, 130 #else 131 NULL, 132 #endif /* MQ200_SETUPREGS */ 133 mcr530_clocks, 134 /* DCMISC */ 135 MQ200_DCMISC_OSC_ENABLE | 136 MQ200_DCMISC_FASTPOWSEQ_DISABLE | 137 MQ200_DCMISC_OSCFREQ_12_25, 138 /* PMC */ 139 0, 140 /* MM01 */ 141 MQ200_MM01_DRAM_AUTO_REFRESH_EN | 142 MQ200_MM01_GE_PB_EN | 143 MQ200_MM01_CPU_PB_EN | 144 MQ200_MM01_SLOW_REFRESH_EN | 145 (0x143e << MQ200_MM01_REFRESH_SHIFT), 146 }, 147 }; 148 149 void 150 mq200_mdsetup(struct mq200_softc *sc) 151 { 152 const struct mq200_md_param *mdp; 153 154 sc->sc_md = NULL; 155 for (mdp = machdep_params; mdp->md_platform != NULL; mdp++) { 156 platid_mask_t mask; 157 mask = PLATID_DEREF(mdp->md_platform); 158 if (platid_match(&platid, &mask)) { 159 sc->sc_md = mdp; 160 break; 161 } 162 } 163 164 if (sc->sc_md) { 165 sc->sc_width[MQ200_GC2] = mdp->md_fp_width; 166 sc->sc_height[MQ200_GC2] = mdp->md_fp_height; 167 sc->sc_baseclock = mdp->md_baseclock; 168 169 sc->sc_regctxs[MQ200_I_DCMISC ].val = mdp->md_init_dcmisc; 170 sc->sc_regctxs[MQ200_I_PMC ].val = mdp->md_init_pmc; 171 sc->sc_regctxs[MQ200_I_MM01 ].val = mdp->md_init_mm01; 172 173 #if MQ200_SETUPREGS 174 mq200_setupregs(sc, mdp->md_init_ops); 175 #endif 176 } 177 } 178 179 #if MQ200_SETUPREGS 180 static void 181 mq200_setupregs(struct mq200_softc *sc, u_int32_t *ops) 182 { 183 u_int32_t reg, mask, accum; 184 185 while (1) { 186 switch (ops[0] & 0x3) { 187 case 0: 188 if (mask == ~0) { 189 mq200_write(sc, ops[0], ops[1]); 190 } else { 191 reg = mq200_read(sc, ops[0]); 192 reg = (reg & ~mask) | (ops[1] & mask); 193 mq200_write(sc, ops[0], reg); 194 } 195 break; 196 case 1: 197 switch (ops[0]) { 198 case OP_END: 199 return; 200 case OP_MASK: 201 mask = ops[1]; 202 break; 203 case OP_LOADPLLPARAM: 204 mq200_pllparam(ops[1], &accum); 205 break; 206 case OP_LOADFROMREG: 207 reg = mq200_read(sc, ops[1]); 208 accum = (accum & ~mask) | (reg & mask); 209 break; 210 case OP_STORETOREG: 211 if (mask == ~0) { 212 mq200_write(sc, ops[1], accum); 213 } else { 214 reg = mq200_read(sc, ops[1]); 215 reg = (reg & ~mask) | (accum & mask); 216 mq200_write(sc, ops[1], reg); 217 } 218 break; 219 case OP_LOADIMM: 220 accum = (accum & ~mask) | (ops[1] & mask); 221 break; 222 case OP_OR: 223 accum = (accum | ops[1]); 224 break; 225 } 226 break; 227 } 228 if (ops[0] != OP_MASK) 229 mask = ~0; 230 ops += 2; 231 } 232 } 233 #endif /* MQ200_SETUPREGS */ 234