xref: /netbsd-src/sys/arch/hpcmips/dev/mq200machdep.c (revision fad4c9f71477ae11cea2ee75ec82151ac770a534)
1 /*	$NetBSD: mq200machdep.c,v 1.4 2005/12/11 12:17:33 christos 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.4 2005/12/11 12:17:33 christos 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 
176 void
177 mq200_mdsetup(struct mq200_softc *sc)
178 {
179 	const struct mq200_md_param *mdp;
180 
181 	sc->sc_md = NULL;
182 	for (mdp = machdep_params; mdp->md_platform != NULL; mdp++) {
183 		platid_mask_t mask;
184 		mask = PLATID_DEREF(mdp->md_platform);
185 		if (platid_match(&platid, &mask)) {
186 			sc->sc_md = mdp;
187 			break;
188 		}
189 	}
190 
191 	if (sc->sc_md) {
192 		sc->sc_width[MQ200_GC2] = mdp->md_fp_width;
193 		sc->sc_height[MQ200_GC2] = mdp->md_fp_height;
194 		sc->sc_baseclock = mdp->md_baseclock;
195 
196 		sc->sc_regctxs[MQ200_I_DCMISC	].val = mdp->md_init_dcmisc;
197 		sc->sc_regctxs[MQ200_I_PMC	].val = mdp->md_init_pmc;
198 		sc->sc_regctxs[MQ200_I_MM01	].val = mdp->md_init_mm01;
199 
200 #if MQ200_SETUPREGS
201 		mq200_setupregs(sc, mdp->md_init_ops);
202 #endif
203 	}
204 }
205 
206 #if MQ200_SETUPREGS
207 static void
208 mq200_setupregs(struct mq200_softc *sc, u_int32_t *ops)
209 {
210 	u_int32_t reg, mask, accum;
211 
212 	while (1) {
213 		switch (ops[0] & 0x3) {
214 		case 0:
215 			if (mask == ~0) {
216 				mq200_write(sc, ops[0], ops[1]);
217 			} else {
218 				reg = mq200_read(sc, ops[0]);
219 				reg = (reg & ~mask) | (ops[1] & mask);
220 				mq200_write(sc, ops[0], reg);
221 			}
222 			break;
223 		case 1:
224 			switch (ops[0]) {
225 			case OP_END:
226 				return;
227 			case OP_MASK:
228 				mask = ops[1];
229 				break;
230 			case OP_LOADPLLPARAM:
231 				mq200_pllparam(ops[1], &accum);
232 				break;
233 			case OP_LOADFROMREG:
234 				reg = mq200_read(sc, ops[1]);
235 				accum = (accum & ~mask) | (reg & mask);
236 				break;
237 			case OP_STORETOREG:
238 				if (mask == ~0) {
239 					mq200_write(sc, ops[1], accum);
240 				} else {
241 					reg = mq200_read(sc, ops[1]);
242 					reg = (reg & ~mask) | (accum & mask);
243 					mq200_write(sc, ops[1], reg);
244 				}
245 				break;
246 			case OP_LOADIMM:
247 				accum = (accum & ~mask) | (ops[1] & mask);
248 				break;
249 			case OP_OR:
250 				accum = (accum | ops[1]);
251 				break;
252 			}
253 			break;
254 		}
255 		if (ops[0] != OP_MASK)
256 			mask = ~0;
257 		ops += 2;
258 	}
259 }
260 #endif /* MQ200_SETUPREGS */
261