xref: /netbsd-src/sys/arch/hpcmips/dev/mq200machdep.c (revision d974db0adae7638e51d0b459a9c2efece6ded7e4)
1 /*	$NetBSD: mq200machdep.c,v 1.6 2007/10/17 19:54:28 garbled 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/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: mq200machdep.c,v 1.6 2007/10/17 19:54:28 garbled Exp $");
35 
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/systm.h>
39 #include <sys/device.h>
40 #else
41 #include <stdio.h>
42 #endif
43 #include <sys/types.h>
44 
45 #include <machine/platid.h>
46 #include <machine/platid_mask.h>
47 
48 #include "opt_mq200.h"
49 #include "mq200var.h"
50 #include "mq200reg.h"
51 #include "mq200priv.h"
52 
53 #if MQ200_SETUPREGS
54 #define OP_(n)          (((n) << 2) | 1)
55 #define OP_END		OP_(1)
56 #define OP_MASK		OP_(2)
57 #define OP_LOADPLLPARAM	OP_(3)
58 #define OP_LOADFROMREG	OP_(4)
59 #define OP_STORETOREG	OP_(5)
60 #define OP_LOADIMM	OP_(6)
61 #define OP_OR		OP_(7)
62 
63 static void mq200_setupregs(struct mq200_softc *sc, u_int32_t *ops);
64 
65 static u_int32_t mcr530_init_ops[] = {
66 	MQ200_PMCR,	0,	/* power management control */
67 	MQ200_DCMISCR,	MQ200_DCMISC_OSC_ENABLE |
68 			MQ200_DCMISC_FASTPOWSEQ_DISABLE |
69 			MQ200_DCMISC_OSCFREQ_12_25,
70 	OP_END
71 };
72 #endif /* MQ200_SETUPREGS */
73 
74 static struct mq200_clock_setting mcr530_clocks[] = {
75 	/* CRT: off	FP: off	*/
76 	{
77 		MQ200_CLOCK_PLL1,	/* memory clock			*/
78 		MQ200_CLOCK_PLL1,	/* graphics engine clock	*/
79 		{
80 		0,			/* GC1(CRT)	clock		*/
81 		0,			/* GC2(FP)	clock		*/
82 		},
83 		30000,			/* PLL1	30MHz			*/
84 		0,			/* PLL2	disable			*/
85 		0,			/* PLL3	disable			*/
86 	},
87 	/* CRT: on	FP: off	*/
88 	{
89 		MQ200_CLOCK_PLL1,	/* memory clock			*/
90 		MQ200_CLOCK_PLL2,	/* graphics engine clock	*/
91 		{
92 		MQ200_CLOCK_PLL3,	/* GC1(CRT)	clock		*/
93 		0,			/* GC2(FP)	clock		*/
94 		},
95 		83000,			/* PLL1	83MHz			*/
96 		30000,			/* PLL2	30MHz			*/
97 		-1,			/* PLL3	will be set by GC1	*/
98 	},
99 	/* CRT: off	FP: on	*/
100 	{
101 		MQ200_CLOCK_PLL1,	/* memory clock			*/
102 		MQ200_CLOCK_PLL2,	/* graphics engine clock	*/
103 		{
104 		0,			/* GC1(CRT)	clock		*/
105 		MQ200_CLOCK_PLL2,	/* GC2(FP)	clock		*/
106 		},
107 		30000,			/* PLL1	30MHz			*/
108 		18800,			/* PLL2	18.8MHz			*/
109 		0,			/* PLL3	disable			*/
110 	},
111 	/* CRT: on	FP: on	*/
112 	{
113 		MQ200_CLOCK_PLL1,	/* memory clock			*/
114 		MQ200_CLOCK_PLL2,	/* graphics engine clock	*/
115 		{
116 		MQ200_CLOCK_PLL3,	/* GC1(CRT)	clock		*/
117 		MQ200_CLOCK_PLL2,	/* GC2(FP)	clock		*/
118 		},
119 		83000,			/* PLL1	83MHz			*/
120 		18800,			/* PLL2	18.8MHz			*/
121 		-1,			/* PLL3	will be set by GC1	*/
122 	},
123 };
124 
125 static struct mq200_md_param machdep_params[] = {
126 	{
127 		&platid_mask_MACH_NEC_MCR_530,
128 		640, 240,	/* flat panel size		*/
129 		12288,		/* base clock is 12.288 MHz	*/
130 		MQ200_MD_HAVECRT | MQ200_MD_HAVEFP,
131 #if MQ200_SETUPREGS
132 		mcr530_init_ops,
133 #else
134 		NULL,
135 #endif /* MQ200_SETUPREGS */
136 		mcr530_clocks,
137 		/* DCMISC	*/
138 		MQ200_DCMISC_OSC_ENABLE |
139 		MQ200_DCMISC_FASTPOWSEQ_DISABLE |
140 		MQ200_DCMISC_OSCFREQ_12_25,
141 		/* PMC		*/
142 		0,
143 		/* MM01		*/
144 		MQ200_MM01_DRAM_AUTO_REFRESH_EN |
145 		MQ200_MM01_GE_PB_EN |
146 		MQ200_MM01_CPU_PB_EN |
147 		MQ200_MM01_SLOW_REFRESH_EN |
148 		(0x143e << MQ200_MM01_REFRESH_SHIFT),
149 	},
150 	{
151 		&platid_mask_MACH_NEC_MCR_530A,
152 		640, 240,	/* flat panel size		*/
153 		12288,		/* base clock is 12.288 MHz	*/
154 		MQ200_MD_HAVECRT | MQ200_MD_HAVEFP,
155 #if MQ200_SETUPREGS
156 		mcr530_init_ops,
157 #else
158 		NULL,
159 #endif /* MQ200_SETUPREGS */
160 		mcr530_clocks,
161 		/* DCMISC	*/
162 		MQ200_DCMISC_OSC_ENABLE |
163 		MQ200_DCMISC_FASTPOWSEQ_DISABLE |
164 		MQ200_DCMISC_OSCFREQ_12_25,
165 		/* PMC		*/
166 		0,
167 		/* MM01		*/
168 		MQ200_MM01_DRAM_AUTO_REFRESH_EN |
169 		MQ200_MM01_GE_PB_EN |
170 		MQ200_MM01_CPU_PB_EN |
171 		MQ200_MM01_SLOW_REFRESH_EN |
172 		(0x143e << MQ200_MM01_REFRESH_SHIFT),
173 	},
174 	{
175 		NULL		/* md_platform */
176 	}
177 };
178 
179 void
mq200_mdsetup(struct mq200_softc * sc)180 mq200_mdsetup(struct mq200_softc *sc)
181 {
182 	const struct mq200_md_param *mdp;
183 
184 	sc->sc_md = NULL;
185 	for (mdp = machdep_params; mdp->md_platform != NULL; mdp++) {
186 		platid_mask_t mask;
187 		mask = PLATID_DEREF(mdp->md_platform);
188 		if (platid_match(&platid, &mask)) {
189 			sc->sc_md = mdp;
190 			break;
191 		}
192 	}
193 
194 	if (sc->sc_md) {
195 		sc->sc_width[MQ200_GC2] = mdp->md_fp_width;
196 		sc->sc_height[MQ200_GC2] = mdp->md_fp_height;
197 		sc->sc_baseclock = mdp->md_baseclock;
198 
199 		sc->sc_regctxs[MQ200_I_DCMISC	].val = mdp->md_init_dcmisc;
200 		sc->sc_regctxs[MQ200_I_PMC	].val = mdp->md_init_pmc;
201 		sc->sc_regctxs[MQ200_I_MM01	].val = mdp->md_init_mm01;
202 
203 #if MQ200_SETUPREGS
204 		mq200_setupregs(sc, mdp->md_init_ops);
205 #endif
206 	}
207 }
208 
209 #if MQ200_SETUPREGS
210 static void
mq200_setupregs(struct mq200_softc * sc,u_int32_t * ops)211 mq200_setupregs(struct mq200_softc *sc, u_int32_t *ops)
212 {
213 	u_int32_t reg, mask, accum;
214 
215 	while (1) {
216 		switch (ops[0] & 0x3) {
217 		case 0:
218 			if (mask == ~0) {
219 				mq200_write(sc, ops[0], ops[1]);
220 			} else {
221 				reg = mq200_read(sc, ops[0]);
222 				reg = (reg & ~mask) | (ops[1] & mask);
223 				mq200_write(sc, ops[0], reg);
224 			}
225 			break;
226 		case 1:
227 			switch (ops[0]) {
228 			case OP_END:
229 				return;
230 			case OP_MASK:
231 				mask = ops[1];
232 				break;
233 			case OP_LOADPLLPARAM:
234 				mq200_pllparam(ops[1], &accum);
235 				break;
236 			case OP_LOADFROMREG:
237 				reg = mq200_read(sc, ops[1]);
238 				accum = (accum & ~mask) | (reg & mask);
239 				break;
240 			case OP_STORETOREG:
241 				if (mask == ~0) {
242 					mq200_write(sc, ops[1], accum);
243 				} else {
244 					reg = mq200_read(sc, ops[1]);
245 					reg = (reg & ~mask) | (accum & mask);
246 					mq200_write(sc, ops[1], reg);
247 				}
248 				break;
249 			case OP_LOADIMM:
250 				accum = (accum & ~mask) | (ops[1] & mask);
251 				break;
252 			case OP_OR:
253 				accum = (accum | ops[1]);
254 				break;
255 			}
256 			break;
257 		}
258 		if (ops[0] != OP_MASK)
259 			mask = ~0;
260 		ops += 2;
261 	}
262 }
263 #endif /* MQ200_SETUPREGS */
264