1 /* $NetBSD: hd64461.c,v 1.4 2002/01/29 18:53:23 uch Exp $ */ 2 3 /*- 4 * Copyright (c) 2001, 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/param.h> 40 #include <sys/systm.h> 41 #include <sys/device.h> 42 #include <sys/malloc.h> 43 #include <sys/boot_flag.h> 44 45 #include <machine/bus.h> 46 #include <machine/intr.h> 47 #include <sh3/shbvar.h> 48 49 #include <machine/debug.h> 50 51 #include <hpcsh/dev/hd64461/hd64461var.h> 52 #include <hpcsh/dev/hd64461/hd64461reg.h> 53 #include <hpcsh/dev/hd64461/hd64461intcreg.h> 54 #include <hpcsh/dev/hd64461/hd64461intcvar.h> 55 56 /* HD64461 modules. INTC, TIMER, POWER modules are included in hd64461if */ 57 STATIC struct hd64461_module { 58 const char *name; 59 } hd64461_modules[] = { 60 [HD64461_MODULE_VIDEO] = { "hd64461video" }, 61 [HD64461_MODULE_PCMCIA] = { "hd64461pcmcia" }, 62 [HD64461_MODULE_GPIO] = { "hd64461gpio" }, 63 [HD64461_MODULE_AFE] = { "hd64461afe" }, 64 [HD64461_MODULE_UART] = { "hd64461uart" }, 65 [HD64461_MODULE_FIR] = { "hd64461fir" }, 66 }; 67 #define HD64461_NMODULE \ 68 (sizeof hd64461_modules / sizeof(struct hd64461_module)) 69 70 struct hd64461_intr_entry { 71 int (*func)(void *); 72 void *arg; 73 int priority; 74 const u_int16_t mask; 75 } hd64461_intr_entry[] = { 76 #define IRQ_ENTRY(x) [HD64461_IRQ_##x] = { 0, 0, 0, HD64461_INTC_##x } 77 IRQ_ENTRY(PCC0), 78 IRQ_ENTRY(PCC1), 79 IRQ_ENTRY(AFE), 80 IRQ_ENTRY(GPIO), 81 IRQ_ENTRY(TMU0), 82 IRQ_ENTRY(TMU1), 83 IRQ_ENTRY(IRDA), 84 IRQ_ENTRY(UART) 85 #undef IRQ_ENTRY 86 }; 87 88 struct hd64461_softc { 89 struct device sc_dev; 90 }; 91 92 STATIC int hd64461_match(struct device *, struct cfdata *, void *); 93 STATIC void hd64461_attach(struct device *, struct device *, void *); 94 STATIC int hd64461_print(void *, const char *); 95 96 struct cfattach hd64461if_ca = { 97 sizeof(struct hd64461_softc), hd64461_match, hd64461_attach 98 }; 99 100 STATIC void hd64461_module_attach(struct hd64461_softc *); 101 STATIC int hd64461_intr(void *); 102 #ifdef DEBUG 103 STATIC void hd64461_info(struct hd64461_softc *); 104 #endif 105 106 int 107 hd64461_match(struct device *parent, struct cfdata *cf, void *aux) 108 { 109 static int match; 110 struct shb_attach_args *ia = aux; 111 112 if (match++) 113 return (0); /* only one instance */ 114 115 if (strcmp("hd64461if", cf->cf_driver->cd_name)) 116 return (0); 117 118 ia->ia_iobase = 0; 119 ia->ia_iosize = 0; 120 ia->ia_maddr = 0; 121 ia->ia_msize = 0; 122 123 return (1); 124 } 125 126 void 127 hd64461_attach(struct device *parent, struct device *self, void *aux) 128 { 129 struct shb_attach_args *ia = aux; 130 struct hd64461_softc *sc = (struct hd64461_softc *)self; 131 132 printf("\n"); 133 #ifdef DEBUG 134 if (bootverbose) 135 hd64461_info(sc); 136 #endif 137 /* mask all interrupt */ 138 hd64461_reg_write_2(HD64461_INTCNIMR_REG16, 0xffff); 139 140 shb_intr_establish(ia->ia_irq, IST_EDGE, IPL_TTY, hd64461_intr, sc); 141 142 hd64461_module_attach(sc); 143 } 144 145 void 146 hd64461_module_attach(struct hd64461_softc *sc) 147 { 148 struct hd64461_attach_args ha; 149 struct hd64461_module *module; 150 int i; 151 152 /* attach all sub modules */ 153 for (i = 0, module = hd64461_modules; i < HD64461_NMODULE; 154 i++, module++) { 155 if (module->name == 0) 156 continue; 157 ha.ha_module_id = i; 158 config_found(&sc->sc_dev, &ha, hd64461_print); 159 } 160 } 161 162 int 163 hd64461_print(void *aux, const char *pnp) 164 { 165 struct hd64461_attach_args *ha = aux; 166 167 if (pnp) 168 printf("%s at %s", 169 hd64461_modules[ha->ha_module_id].name, pnp); 170 171 return (UNCONF); 172 } 173 174 void * 175 hd64461_intr_establish(enum hd64461_irq irq, int mode, int level, 176 int (*func)(void *), void *arg) 177 { 178 struct hd64461_intr_entry *entry = &hd64461_intr_entry[irq]; 179 u_int16_t r; 180 int s; 181 182 s = splhigh(); 183 184 entry->func = func; 185 entry->arg = arg; 186 entry->priority = level; 187 188 /* enable interrupt */ 189 r = hd64461_reg_read_2(HD64461_INTCNIMR_REG16); 190 r &= ~entry->mask; 191 hd64461_reg_write_2(HD64461_INTCNIMR_REG16, r); 192 193 splx(s); 194 195 return (void *)irq; 196 } 197 198 void 199 hd64461_intr_disestablish(void *handle) 200 { 201 int irq = (int)handle; 202 struct hd64461_intr_entry *entry = &hd64461_intr_entry[irq]; 203 u_int16_t r; 204 int s; 205 206 s = splhigh(); 207 208 /* disable interrupt */ 209 r = hd64461_reg_read_2(HD64461_INTCNIMR_REG16); 210 r |= entry->mask; 211 hd64461_reg_write_2(HD64461_INTCNIMR_REG16, r); 212 213 entry->func = 0; 214 215 splx(s); 216 } 217 218 int 219 hd64461_intr(void *arg) 220 { 221 struct hd64461_intr_entry *entry = hd64461_intr_entry; 222 u_int16_t r, m, cause; 223 int i; 224 225 r = hd64461_reg_read_2(HD64461_INTCNIRR_REG16); 226 m = hd64461_reg_read_2(HD64461_INTCNIMR_REG16); 227 cause = r & ~m; 228 229 /* XXX priority */ 230 hd64461_reg_write_2(HD64461_INTCNIMR_REG16, 0xffff); 231 232 /* XXX priority */ 233 for (i = 0; i < HD64461_IRQ_MAX; i++, entry++) { 234 if (entry->func == 0) 235 continue; 236 if (cause & entry->mask) { 237 (*entry->func)(entry->arg); 238 } 239 } 240 241 hd64461_reg_write_2(HD64461_INTCNIMR_REG16, m); 242 243 return 0; 244 } 245 246 #ifdef DEBUG 247 void 248 hd64461_info(struct hd64461_softc *sc) 249 { 250 u_int16_t r16; 251 252 dbg_banner_function(); 253 254 /* 255 * System 256 */ 257 printf("STBCR (System Control Register)\n"); 258 r16 = hd64461_reg_read_2(HD64461_SYSSTBCR_REG16); 259 #define DBG_BITMASK_PRINT(r, m) dbg_bitmask_print(r, HD64461_SYSSTBCR_##m, #m) 260 DBG_BITMASK_PRINT(r16, CKIO_STBY); 261 DBG_BITMASK_PRINT(r16, SAFECKE_IST); 262 DBG_BITMASK_PRINT(r16, SLCKE_IST); 263 DBG_BITMASK_PRINT(r16, SAFECKE_OST); 264 DBG_BITMASK_PRINT(r16, SLCKE_OST); 265 DBG_BITMASK_PRINT(r16, SMIAST); 266 DBG_BITMASK_PRINT(r16, SLCDST); 267 DBG_BITMASK_PRINT(r16, SPC0ST); 268 DBG_BITMASK_PRINT(r16, SPC1ST); 269 DBG_BITMASK_PRINT(r16, SAFEST); 270 DBG_BITMASK_PRINT(r16, STM0ST); 271 DBG_BITMASK_PRINT(r16, STM1ST); 272 DBG_BITMASK_PRINT(r16, SIRST); 273 DBG_BITMASK_PRINT(r16, SURTSD); 274 #undef DBG_BITMASK_PRINT 275 printf("\n"); 276 277 printf("SYSCR (System Configuration Register)\n"); 278 r16 = hd64461_reg_read_2(HD64461_SYSSYSCR_REG16); 279 #define DBG_BITMASK_PRINT(r, m) dbg_bitmask_print(r, HD64461_SYSSYSCR_##m, #m) 280 DBG_BITMASK_PRINT(r16, SCPU_BUS_IGAT); 281 DBG_BITMASK_PRINT(r16, SPTA_IR); 282 DBG_BITMASK_PRINT(r16, SPTA_TM); 283 DBG_BITMASK_PRINT(r16, SPTB_UR); 284 DBG_BITMASK_PRINT(r16, WAIT_CTL_SEL); 285 DBG_BITMASK_PRINT(r16, SMODE1); 286 DBG_BITMASK_PRINT(r16, SMODE0); 287 #undef DBG_BITMASK_PRINT 288 printf("\n"); 289 290 printf("SCPUCR (CPU Data Bus Control Register)\n"); 291 r16 = hd64461_reg_read_2(HD64461_SYSSCPUCR_REG16); 292 #define DBG_BITMASK_PRINT(r, m) dbg_bitmask_print(r, HD64461_SYSSCPUCR_##m, #m) 293 DBG_BITMASK_PRINT(r16, SPDSTOF); 294 DBG_BITMASK_PRINT(r16, SPDSTIG); 295 DBG_BITMASK_PRINT(r16, SPCSTOF); 296 DBG_BITMASK_PRINT(r16, SPCSTIG); 297 DBG_BITMASK_PRINT(r16, SPBSTOF); 298 DBG_BITMASK_PRINT(r16, SPBSTIG); 299 DBG_BITMASK_PRINT(r16, SPASTOF); 300 DBG_BITMASK_PRINT(r16, SPASTIG); 301 DBG_BITMASK_PRINT(r16, SLCDSTIG); 302 DBG_BITMASK_PRINT(r16, SCPU_CS56_EP); 303 DBG_BITMASK_PRINT(r16, SCPU_CMD_EP); 304 DBG_BITMASK_PRINT(r16, SCPU_ADDR_EP); 305 DBG_BITMASK_PRINT(r16, SCPDPU); 306 DBG_BITMASK_PRINT(r16, SCPU_A2319_EP); 307 #undef DBG_BITMASK_PRINT 308 printf("\n"); 309 310 printf("\n"); 311 /* 312 * INTC 313 */ 314 printf("NIRR (Interrupt Request Register)\n"); 315 r16 = hd64461_reg_read_2(HD64461_INTCNIRR_REG16); 316 #define DBG_BITMASK_PRINT(r, m) dbg_bitmask_print(r, HD64461_INTCNIRR_##m, #m) 317 DBG_BITMASK_PRINT(r16, PCC0R); 318 DBG_BITMASK_PRINT(r16, PCC1R); 319 DBG_BITMASK_PRINT(r16, AFER); 320 DBG_BITMASK_PRINT(r16, GPIOR); 321 DBG_BITMASK_PRINT(r16, TMU0R); 322 DBG_BITMASK_PRINT(r16, TMU1R); 323 DBG_BITMASK_PRINT(r16, IRDAR); 324 DBG_BITMASK_PRINT(r16, UARTR); 325 #undef DBG_BITMASK_PRINT 326 printf("\n"); 327 328 printf("NIMR (Interrupt Mask Register)\n"); 329 r16 = hd64461_reg_read_2(HD64461_INTCNIMR_REG16); 330 #define DBG_BITMASK_PRINT(r, m) dbg_bitmask_print(r, HD64461_INTCNIMR_##m, #m) 331 DBG_BITMASK_PRINT(r16, PCC0M); 332 DBG_BITMASK_PRINT(r16, PCC1M); 333 DBG_BITMASK_PRINT(r16, AFEM); 334 DBG_BITMASK_PRINT(r16, GPIOM); 335 DBG_BITMASK_PRINT(r16, TMU0M); 336 DBG_BITMASK_PRINT(r16, TMU1M); 337 DBG_BITMASK_PRINT(r16, IRDAM); 338 DBG_BITMASK_PRINT(r16, UARTM); 339 #undef DBG_BITMASK_PRINT 340 printf("\n"); 341 342 dbg_banner_line(); 343 } 344 #endif /* DEBUG */ 345