1/*	$NetBSD: mq200machdep.c,v 1.4.38.1 2007/10/03 19:23:25 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.4.38.1 2007/10/03 19:23:25 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
63static void mq200_setupregs(struct mq200_softc *sc, u_int32_t *ops);
64
65static 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
74static 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
125static 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
179void
180mq200_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
210static void
211mq200_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