1 /* $NetBSD: vrip.c,v 1.33 2007/12/15 00:39:18 perry Exp $ */
4 * Copyright (c) 1999, 2002
5 * Shin Takemura and PocketBSD Project. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: vrip.c,v 1.33 2007/12/15 00:39:18 perry Exp $");
36 #include "opt_vr41xx.h"
37 #include "opt_tx39xx.h"
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/device.h>
42 #include <sys/reboot.h>
44 #include <machine/cpu.h>
45 #include <machine/bus.h>
46 #include <machine/autoconf.h>
47 #include <machine/platid.h>
48 #include <machine/platid_mask.h>
50 #include <hpcmips/vr/vr.h>
51 #include <hpcmips/vr/vrcpudef.h>
52 #include <hpcmips/vr/vripunit.h>
53 #include <hpcmips/vr/vripif.h>
54 #include <hpcmips/vr/vripreg.h>
55 #include <hpcmips/vr/vripvar.h>
56 #include <hpcmips/vr/icureg.h>
57 #include <hpcmips/vr/cmureg.h>
61 #define DPRINTF_ENABLE
62 #define DPRINTF_DEBUG vrip_debug
64 #define USE_HPC_DPRINTF
65 #include <machine/debug.h>
68 #define DBG_BIT_PRINT(reg) if (vrip_debug) dbg_bit_print(reg);
69 #define DUMP_LEVEL2MASK(sc,arg) if (vrip_debug) __vrip_dump_level2mask(sc,arg)
71 #define DBG_BIT_PRINT(arg)
72 #define DUMP_LEVEL2MASK(sc,arg)
75 #define VALID_UNIT(sc, unit) (0 <= (unit) && (unit) < (sc)->sc_nunits)
77 #ifdef SINGLE_VRIP_BASE
78 int vripmatch(struct device
*, struct cfdata
*, void *);
79 void vripattach(struct device
*, struct device
*, void *);
81 int vrip_print(void *, const char *);
82 int vrip_search(struct device
*, struct cfdata
*,
84 int vrip_intr(void *, u_int32_t
, u_int32_t
);
86 int __vrip_power(vrip_chipset_tag_t
, int, int);
87 vrip_intr_handle_t
__vrip_intr_establish(vrip_chipset_tag_t
, int, int,
88 int, int(*)(void*), void*);
89 void __vrip_intr_disestablish(vrip_chipset_tag_t
, vrip_intr_handle_t
);
90 void __vrip_intr_setmask1(vrip_chipset_tag_t
, vrip_intr_handle_t
, int);
91 void __vrip_intr_setmask2(vrip_chipset_tag_t
, vrip_intr_handle_t
,
93 void __vrip_intr_getstatus2(vrip_chipset_tag_t
, vrip_intr_handle_t
,
95 void __vrip_register_cmu(vrip_chipset_tag_t
, vrcmu_chipset_tag_t
);
96 void __vrip_register_gpio(vrip_chipset_tag_t
, hpcio_chip_t
);
97 void __vrip_register_dmaau(vrip_chipset_tag_t
, vrdmaau_chipset_tag_t
);
98 void __vrip_register_dcu(vrip_chipset_tag_t
, vrdcu_chipset_tag_t
);
99 void __vrip_dump_level2mask(vrip_chipset_tag_t
, void *);
101 struct vrip_softc
*the_vrip_sc
= NULL
;
103 static const struct vrip_chipset_tag vrip_chipset_methods
= {
104 .vc_power
= __vrip_power
,
105 .vc_intr_establish
= __vrip_intr_establish
,
106 .vc_intr_disestablish
= __vrip_intr_disestablish
,
107 .vc_intr_setmask1
= __vrip_intr_setmask1
,
108 .vc_intr_setmask2
= __vrip_intr_setmask2
,
109 .vc_intr_getstatus2
= __vrip_intr_getstatus2
,
110 .vc_register_cmu
= __vrip_register_cmu
,
111 .vc_register_gpio
= __vrip_register_gpio
,
112 .vc_register_dmaau
= __vrip_register_dmaau
,
113 .vc_register_dcu
= __vrip_register_dcu
,
116 #ifdef SINGLE_VRIP_BASE
117 CFATTACH_DECL(vrip
, sizeof(struct vrip_softc
),
118 vripmatch
, vripattach
, NULL
, NULL
);
120 static const struct vrip_unit vrip_units
[] = {
121 [VRIP_UNIT_PMU
] = { "pmu",
122 { VRIP_INTR_POWER
, VRIP_INTR_BAT
, }, },
123 [VRIP_UNIT_RTC
] = { "rtc",
124 { VRIP_INTR_RTCL1
, }, },
125 [VRIP_UNIT_PIU
] = { "piu",
128 ICUPIUINT_REG_W
, MPIUINT_REG_W
},
129 [VRIP_UNIT_KIU
] = { "kiu",
132 KIUINT_REG_W
, MKIUINT_REG_W
},
133 [VRIP_UNIT_SIU
] = { "siu",
134 { VRIP_INTR_SIU
, }, },
135 [VRIP_UNIT_GIU
] = { "giu",
138 GIUINT_L_REG_W
,MGIUINT_L_REG_W
,
139 GIUINT_H_REG_W
, MGIUINT_H_REG_W
},
140 [VRIP_UNIT_LED
] = { "led",
141 { VRIP_INTR_LED
, }, },
142 [VRIP_UNIT_AIU
] = { "aiu",
145 AIUINT_REG_W
, MAIUINT_REG_W
},
146 [VRIP_UNIT_FIR
] = { "fir",
149 FIRINT_REG_W
, MFIRINT_REG_W
},
150 [VRIP_UNIT_DSIU
]= { "dsiu",
153 DSIUINT_REG_W
, MDSIUINT_REG_W
},
154 [VRIP_UNIT_PCIU
]= { "pciu",
157 PCIINT_REG_W
, MPCIINT_REG_W
},
158 [VRIP_UNIT_SCU
] = { "scu",
161 SCUINT_REG_W
, MSCUINT_REG_W
},
162 [VRIP_UNIT_CSI
] = { "csi",
165 CSIINT_REG_W
, MCSIINT_REG_W
},
166 [VRIP_UNIT_BCU
] = { "bcu",
169 BCUINT_REG_W
, MBCUINT_REG_W
},
173 vripattach(struct device
*parent
, struct device
*self
, void *aux
)
175 struct vrip_softc
*sc
= (struct vrip_softc
*)self
;
179 sc
->sc_units
= vrip_units
;
180 sc
->sc_nunits
= sizeof(vrip_units
)/sizeof(struct vrip_unit
);
181 sc
->sc_icu_addr
= VRIP_ICU_ADDR
;
182 sc
->sc_sysint2
= SYSINT2_REG_W
;
183 sc
->sc_msysint2
= MSYSINT2_REG_W
;
185 vripattach_common(parent
, self
, aux
);
187 #endif /* SINGLE_VRIP_BASE */
190 vripmatch(struct device
*parent
, struct cfdata
*match
, void *aux
)
192 struct mainbus_attach_args
*ma
= aux
;
194 #if defined(SINGLE_VRIP_BASE) && defined(TX39XX)
195 if (!platid_match(&platid
, &platid_mask_CPU_MIPS_VR_41XX
))
197 #endif /* SINGLE_VRIP_BASE && TX39XX */
198 if (strcmp(ma
->ma_name
, match
->cf_name
))
205 vripattach_common(struct device
*parent
, struct device
*self
, void *aux
)
207 struct mainbus_attach_args
*ma
= aux
;
208 struct vrip_softc
*sc
= (struct vrip_softc
*)self
;
210 sc
->sc_chipset
= vrip_chipset_methods
; /* structure assignment */
211 sc
->sc_chipset
.vc_sc
= sc
;
214 if (sc
->sc_icu_addr
== 0 ||
215 sc
->sc_sysint2
== 0 ||
216 sc
->sc_msysint2
== 0)
217 panic("vripattach: missing register info.");
218 #endif /* DIAGNOSTIC */
221 * Map ICU (Interrupt Control Unit) register space.
223 sc
->sc_iot
= ma
->ma_iot
;
224 if (bus_space_map(sc
->sc_iot
, sc
->sc_icu_addr
,
225 0x20 /*XXX lower area only*/,
228 printf("vripattach: can't map ICU register.\n");
233 * Disable all Level 1 interrupts.
236 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, MSYSINT1_REG_W
, 0x0000);
237 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_msysint2
, 0x0000);
239 * Level 1 interrupts are redirected to HwInt0
241 vr_intr_establish(VR_INTR0
, vrip_intr
, self
);
244 * Attach each devices
245 * GIU CMU DMAAU DCU interface interface is used by other system
246 * device. so attach first
249 config_search_ia(vrip_search
, self
, "vripif", vrip_print
);
250 /* Other system devices. */
252 config_search_ia(vrip_search
, self
, "vripif", vrip_print
);
256 vrip_print(void *aux
, const char *hoge
)
258 struct vrip_attach_args
*va
= (struct vrip_attach_args
*)aux
;
259 bus_addr_t endaddr
, mask
;
261 if (va
->va_addr
!= VRIPIFCF_ADDR_DEFAULT
)
262 aprint_normal(" addr 0x%08lx", va
->va_addr
);
263 if (va
->va_size
!= VRIPIFCF_SIZE_DEFAULT
) {
264 endaddr
= (va
->va_addr
+ va
->va_size
- 1);
265 mask
= ((va
->va_addr
^ endaddr
) & 0xff0000) ? 0xffffff:0xffff;
266 aprint_normal("-%04lx", endaddr
& mask
);
268 if (va
->va_addr2
!= VRIPIFCF_ADDR2_DEFAULT
)
269 aprint_normal(", 0x%08lx", va
->va_addr2
);
270 if (va
->va_size2
!= VRIPIFCF_SIZE2_DEFAULT
)
271 aprint_normal("-%04lx",
272 (va
->va_addr2
+ va
->va_size2
- 1) & 0xffff);
278 vrip_search(struct device
*parent
, struct cfdata
*cf
,
279 const int *ldesc
, void *aux
)
281 struct vrip_softc
*sc
= (struct vrip_softc
*)parent
;
282 struct vrip_attach_args va
;
285 if (cf
->cf_loc
[VRIPIFCF_PLATFORM
] != VRIPIFCF_PLATFORM_DEFAULT
) {
286 mask
= PLATID_DEREF(cf
->cf_loc
[VRIPIFCF_PLATFORM
]);
287 if (platid_match(&platid
, &mask
) == 0)
291 memset(&va
, 0, sizeof(va
));
292 va
.va_vc
= &sc
->sc_chipset
;
293 va
.va_iot
= sc
->sc_iot
;
294 va
.va_unit
= cf
->cf_loc
[VRIPIFCF_UNIT
];
295 va
.va_addr
= cf
->cf_loc
[VRIPIFCF_ADDR
];
296 va
.va_size
= cf
->cf_loc
[VRIPIFCF_SIZE
];
297 va
.va_addr2
= cf
->cf_loc
[VRIPIFCF_ADDR2
];
298 va
.va_size2
= cf
->cf_loc
[VRIPIFCF_SIZE2
];
299 va
.va_gpio_chips
= sc
->sc_gpio_chips
;
300 va
.va_cc
= sc
->sc_chipset
.vc_cc
;
301 va
.va_ac
= sc
->sc_chipset
.vc_ac
;
302 va
.va_dc
= sc
->sc_chipset
.vc_dc
;
303 if ((config_match(parent
, cf
, &va
) == sc
->sc_pri
))
304 config_attach(parent
, cf
, &va
, vrip_print
);
310 __vrip_power(vrip_chipset_tag_t vc
, int unit
, int onoff
)
312 struct vrip_softc
*sc
= vc
->vc_sc
;
313 const struct vrip_unit
*vu
;
315 if (sc
->sc_chipset
.vc_cc
== NULL
)
316 return (0); /* You have no clock mask unit yet. */
317 if (!VALID_UNIT(sc
, unit
))
319 vu
= &sc
->sc_units
[unit
];
321 return (*sc
->sc_chipset
.vc_cc
->cc_clock
)(sc
->sc_chipset
.vc_cc
,
322 vu
->vu_clkmask
, onoff
);
326 __vrip_intr_establish(vrip_chipset_tag_t vc
, int unit
, int line
, int level
,
327 int (*ih_fun
)(void *), void *ih_arg
)
329 struct vrip_softc
*sc
= vc
->vc_sc
;
330 const struct vrip_unit
*vu
;
333 if (!VALID_UNIT(sc
, unit
))
335 vu
= &sc
->sc_units
[unit
];
336 ih
= &sc
->sc_intrhands
[vu
->vu_intr
[line
]];
337 if (ih
->ih_fun
) /* Can't share level 1 interrupt */
343 /* Mask level 2 interrupt mask register. (disable interrupt) */
344 vrip_intr_setmask2(vc
, ih
, ~0, 0);
345 /* Unmask Level 1 interrupt mask register (enable interrupt) */
346 vrip_intr_setmask1(vc
, ih
, 1);
352 __vrip_intr_disestablish(vrip_chipset_tag_t vc
, vrip_intr_handle_t handle
)
354 struct intrhand
*ih
= handle
;
358 /* Mask level 2 interrupt mask register(if any). (disable interrupt) */
359 vrip_intr_setmask2(vc
, ih
, ~0, 0);
360 /* Mask Level 1 interrupt mask register (disable interrupt) */
361 vrip_intr_setmask1(vc
, ih
, 0);
365 vrip_intr_suspend(void)
367 struct vrip_softc
*sc
= the_vrip_sc
;
368 bus_space_tag_t iot
= sc
->sc_iot
;
369 bus_space_handle_t ioh
= sc
->sc_ioh
;
371 bus_space_write_2 (iot
, ioh
, MSYSINT1_REG_W
, (1<<VRIP_INTR_POWER
));
372 bus_space_write_2 (iot
, ioh
, sc
->sc_msysint2
, 0);
376 vrip_intr_resume(void)
378 struct vrip_softc
*sc
= the_vrip_sc
;
379 u_int32_t reg
= sc
->sc_intrmask
;
380 bus_space_tag_t iot
= sc
->sc_iot
;
381 bus_space_handle_t ioh
= sc
->sc_ioh
;
383 bus_space_write_2 (iot
, ioh
, MSYSINT1_REG_W
, reg
& 0xffff);
384 bus_space_write_2 (iot
, ioh
, sc
->sc_msysint2
, (reg
>> 16) & 0xffff);
387 /* Set level 1 interrupt mask. */
389 __vrip_intr_setmask1(vrip_chipset_tag_t vc
, vrip_intr_handle_t handle
,
392 struct vrip_softc
*sc
= vc
->vc_sc
;
393 struct intrhand
*ih
= handle
;
394 int level1
= ih
- sc
->sc_intrhands
;
395 bus_space_tag_t iot
= sc
->sc_iot
;
396 bus_space_handle_t ioh
= sc
->sc_ioh
;
397 u_int32_t reg
= sc
->sc_intrmask
;
399 DPRINTF(("__vrip_intr_setmask1: SYSINT: %s %d\n",
400 enable
? "enable" : "disable", level1
));
401 reg
= (bus_space_read_2 (iot
, ioh
, MSYSINT1_REG_W
)&0xffff) |
402 ((bus_space_read_2 (iot
, ioh
, sc
->sc_msysint2
) << 16)&0xffff0000);
404 reg
|= (1 << level1
);
406 reg
&= ~(1 << level1
);
408 sc
->sc_intrmask
= reg
;
409 bus_space_write_2 (iot
, ioh
, MSYSINT1_REG_W
, reg
& 0xffff);
410 bus_space_write_2 (iot
, ioh
, sc
->sc_msysint2
, (reg
>> 16) & 0xffff);
417 __vrip_dump_level2mask(vrip_chipset_tag_t vc
, vrip_intr_handle_t handle
)
419 struct vrip_softc
*sc
= vc
->vc_sc
;
420 struct intrhand
*ih
= handle
;
421 const struct vrip_unit
*vu
= ih
->ih_unit
;
425 DPRINTF(("level1[%d] level2 mask:", vu
->vu_intr
[0]));
426 reg
= bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
, vu
->vu_mlreg
);
427 if (vu
->vu_mhreg
) { /* GIU [16:31] case only */
428 reg
|= (bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
,
429 vu
->vu_mhreg
) << 16);
436 /* Get level 2 interrupt status */
438 __vrip_intr_getstatus2(vrip_chipset_tag_t vc
, vrip_intr_handle_t handle
,
439 u_int32_t
*mask
/* Level 2 mask */)
441 struct vrip_softc
*sc
= vc
->vc_sc
;
442 struct intrhand
*ih
= handle
;
443 const struct vrip_unit
*vu
= ih
->ih_unit
;
446 reg
= bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
,
448 reg
|= ((bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
,
449 vu
->vu_hreg
) << 16)&0xffff0000);
450 /* dbg_bit_print(reg);*/
454 /* Set level 2 interrupt mask. */
456 __vrip_intr_setmask2(vrip_chipset_tag_t vc
, vrip_intr_handle_t handle
,
457 u_int32_t mask
/* Level 2 mask */, int onoff
)
459 struct vrip_softc
*sc
= vc
->vc_sc
;
460 struct intrhand
*ih
= handle
;
461 const struct vrip_unit
*vu
= ih
->ih_unit
;
464 DPRINTF(("vrip_intr_setmask2:\n"));
465 DUMP_LEVEL2MASK(vc
, handle
);
466 #ifdef WINCE_DEFAULT_SETTING
467 #warning WINCE_DEFAULT_SETTING
470 reg
= bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
, vu
->vu_mlreg
);
472 reg
|= (mask
&0xffff);
474 reg
&= ~(mask
&0xffff);
475 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
, vu
->vu_mlreg
, reg
);
476 if (vu
->vu_mhreg
!= 0) { /* GIU [16:31] case only */
477 reg
= bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
,
480 reg
|= ((mask
>> 16) & 0xffff);
482 reg
&= ~((mask
>> 16) & 0xffff);
483 bus_space_write_2(sc
->sc_iot
, sc
->sc_ioh
,
487 #endif /* WINCE_DEFAULT_SETTING */
488 DUMP_LEVEL2MASK(vc
, handle
);
494 vrip_intr(void *arg
, u_int32_t pc
, u_int32_t statusReg
)
496 struct vrip_softc
*sc
= (struct vrip_softc
*)arg
;
497 bus_space_tag_t iot
= sc
->sc_iot
;
498 bus_space_handle_t ioh
= sc
->sc_ioh
;
502 * Read level1 interrupt status.
504 reg
= (bus_space_read_2 (iot
, ioh
, SYSINT1_REG_W
)&0xffff) |
505 ((bus_space_read_2 (iot
, ioh
, sc
->sc_sysint2
)<< 16)&0xffff0000);
506 mask
= (bus_space_read_2 (iot
, ioh
, MSYSINT1_REG_W
)&0xffff) |
507 ((bus_space_read_2 (iot
, ioh
, sc
->sc_msysint2
)<< 16)&0xffff0000);
511 * Dispatch each handler.
513 for (i
= 0; i
< 32; i
++) {
514 register struct intrhand
*ih
= &sc
->sc_intrhands
[i
];
515 if (ih
->ih_fun
&& (reg
& (1 << i
))) {
516 ih
->ih_fun(ih
->ih_arg
);
524 __vrip_register_cmu(vrip_chipset_tag_t vc
, vrcmu_chipset_tag_t cmu
)
526 struct vrip_softc
*sc
= vc
->vc_sc
;
528 sc
->sc_chipset
.vc_cc
= cmu
;
532 __vrip_register_gpio(vrip_chipset_tag_t vc
, hpcio_chip_t chip
)
534 struct vrip_softc
*sc
= vc
->vc_sc
;
536 if (chip
->hc_chipid
< 0 || VRIP_NIOCHIPS
<= chip
->hc_chipid
)
537 panic("%s: '%s' has unknown id, %d", __func__
,
538 chip
->hc_name
, chip
->hc_chipid
);
539 sc
->sc_gpio_chips
[chip
->hc_chipid
] = chip
;
543 __vrip_register_dmaau(vrip_chipset_tag_t vc
, vrdmaau_chipset_tag_t dmaau
)
545 struct vrip_softc
*sc
= vc
->vc_sc
;
547 sc
->sc_chipset
.vc_ac
= dmaau
;
551 __vrip_register_dcu(vrip_chipset_tag_t vc
, vrdcu_chipset_tag_t dcu
)
553 struct vrip_softc
*sc
= vc
->vc_sc
;
555 sc
->sc_chipset
.vc_dc
= dcu
;