xref: /netbsd-src/sys/arch/hpcsh/dev/hd64465/hd64465.c (revision 8ac07aec990b9d2e483062509d0a9fa5b4f57cf2)
1 /*	$NetBSD: hd64465.c,v 1.12 2006/03/04 02:26:33 uwe Exp $	*/
2 
3 /*-
4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by UCHIYAMA Yasushi.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: hd64465.c,v 1.12 2006/03/04 02:26:33 uwe Exp $");
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/device.h>
45 #include <sys/boot_flag.h>
46 
47 #include <machine/bus.h>
48 #include <machine/intr.h>
49 #include <machine/debug.h>
50 
51 #include <sh3/intcreg.h>
52 #include <hpcsh/dev/hd64465/hd64465var.h>
53 #include <hpcsh/dev/hd64465/hd64465reg.h>
54 #include <hpcsh/dev/hd64465/hd64465intcreg.h>
55 
56 /* HD64465 modules. */
57 STATIC const struct hd64465_module {
58 	const char *name;
59 } hd64465_modules[] = {
60 	[HD64465_MODULE_PS2IF]		= { "hd64465ps2if" },
61 	[HD64465_MODULE_PCMCIA]		= { "hd64465pcmcia" },
62 	[HD64465_MODULE_AFE]		= { "hd64465afe" },
63 	[HD64465_MODULE_GPIO]		= { "hd64465gpio" },
64 	[HD64465_MODULE_KBC]		= { "hd64465kbc" },
65 	[HD64465_MODULE_IRDA]		= { "hd64465irda" },
66 	[HD64465_MODULE_UART]		= { "hd64465uart" },
67 	[HD64465_MODULE_PARALEL]	= { "hd64465paralel" },
68 	[HD64465_MODULE_CODEC]		= { "hd64465codec" },
69 	[HD64465_MODULE_OHCI]		= { "hd64465ohci" },
70 	[HD64465_MODULE_ADC]		= { "hd64465adc" }
71 };
72 #define HD64465_NMODULE							\
73 	(sizeof hd64465_modules / sizeof(struct hd64465_module))
74 
75 STATIC int hd64465_match(struct device *, struct cfdata *, void *);
76 STATIC void hd64465_attach(struct device *, struct device *, void *);
77 STATIC int hd64465_print(void *, const char *);
78 #ifdef DEBUG
79 STATIC void hd64465_info(void);
80 #endif
81 
82 CFATTACH_DECL(hd64465if, sizeof(struct device),
83     hd64465_match, hd64465_attach, NULL, NULL);
84 
85 int
86 hd64465_match(struct device *parent, struct cfdata *cf, void *aux)
87 {
88 
89 	if (strcmp("hd64465if", cf->cf_name))
90 		return (0);
91 
92 	if (hd64465_reg_read_2(HD64465_SDIDR) != 0x8122) {
93 		/* not HD64465 */
94 		return (0);
95 	}
96 
97 	return (1);
98 }
99 
100 void
101 hd64465_attach(struct device *parent, struct device *self, void *aux)
102 {
103 	const struct hd64465_module *module;
104 	struct hd64465_attach_args ha;
105 	uint16_t r;
106 	int i;
107 
108 	printf("\n");
109 #ifdef DEBUG
110 	if (bootverbose)
111 		hd64465_info();
112 #endif
113 
114 	r = hd64465_reg_read_2(HD64465_SRR);
115 	printf("%s: HITACHI HD64465 rev. %d.%d\n", self->dv_xname,
116 	    (r >> 8) & 0xff, r & 0xff);
117 
118 	/* Mask all interrupt */
119 	hd64465_reg_write_2(HD64465_NIMR, 0xffff);
120 	/* Edge trigger mode to clear pending interrupt. */
121 	hd64465_reg_write_2(HD64465_NITR, 0xffff);
122 	/* Clear pending interrupt */
123 	hd64465_reg_write_2(HD64465_NIRR, 0x0000);
124 
125 	/* Attach all sub modules */
126 	for (i = 0, module = hd64465_modules; i < HD64465_NMODULE;
127 	    i++, module++) {
128 		if (module->name == 0)
129 			continue;
130 		ha.ha_module_id = i;
131 		config_found(self, &ha, hd64465_print);
132 	}
133 }
134 
135 int
136 hd64465_print(void *aux, const char *pnp)
137 {
138 	struct hd64465_attach_args *ha = aux;
139 
140 	if (pnp)
141 		aprint_normal("%s at %s",
142 		    hd64465_modules[ha->ha_module_id].name, pnp);
143 
144 	return (UNCONF);
145 }
146 
147 void *
148 hd64465_intr_establish(int irq, int mode, int level,
149     int (*func)(void *), void *arg)
150 {
151 	uint16_t r;
152 	int s;
153 
154 	s = splhigh();
155 	/* Trigger type */
156 	r = hd64465_reg_read_2(HD64465_NITR);
157 	switch (mode) {
158 	case IST_PULSE:
159 		/* FALLTHROUGH */
160 	case IST_EDGE:
161 		r |= irq;
162 		break;
163 	case IST_LEVEL:
164 		r &= ~irq;
165 		break;
166 	}
167 	hd64465_reg_write_2(HD64465_NITR, r);
168 
169 	hd6446x_intr_establish(irq, mode, level, func, arg);
170 	splx(s);
171 
172 	return (void *)irq;
173 }
174 
175 void
176 hd64465_intr_disestablish(void *handle)
177 {
178 
179 	hd6446x_intr_disestablish(handle);
180 }
181 
182 /* For the sake of Windows CE reboot clearly. */
183 void
184 hd64465_shutdown()
185 {
186 
187 	/* Enable all interrupt */
188 	hd64465_reg_write_2(HD64465_NIMR, 0x0000);
189 
190 	/* Level trigger mode */
191 	hd64465_reg_write_2(HD64465_NITR, 0x0000);
192 }
193 
194 void
195 hd64465_info()
196 {
197 	uint16_t r;
198 
199 	dbg_bit_print_msg(_reg_read_2(SH4_ICR), "SH4_ICR");
200 	r = hd64465_reg_read_2(HD64465_NIMR);
201 	dbg_bit_print_msg(r, "NIMR");
202 	r = hd64465_reg_read_2(HD64465_NIRR);
203 	dbg_bit_print_msg(r, "NIRR");
204 	r = hd64465_reg_read_2(HD64465_NITR);
205 	dbg_bit_print_msg(r, "NITR");
206 }
207