xref: /openbsd/sys/arch/sparc64/dev/pmc.c (revision 898184e3)
1 /*	$OpenBSD: pmc.c,v 1.3 2012/10/17 22:32:01 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 2007 Mark Kettenis
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Driver for watchdog device on Blade 1000, Fire 280R, Fire V480 etc.
21  */
22 
23 #include <sys/param.h>
24 #include <sys/kernel.h>
25 #include <sys/device.h>
26 #include <sys/malloc.h>
27 #include <sys/systm.h>
28 
29 #include <machine/bus.h>
30 #include <machine/autoconf.h>
31 
32 #include <sparc64/dev/ebusreg.h>
33 #include <sparc64/dev/ebusvar.h>
34 
35 /*
36  * Register access is indirect, through an address and data port.
37  */
38 
39 #define	PMC_ADDR	0
40 #define	PMC_DATA	1
41 
42 /* Watchdog time-out register. */
43 #define PMC_WDTO	0x05
44 
45 struct pmc_softc {
46 	struct device		sc_dv;
47 	bus_space_tag_t		sc_iot;
48 	bus_space_handle_t	sc_ioh;
49 };
50 
51 int	pmc_match(struct device *, void *, void *);
52 void	pmc_attach(struct device *, struct device *, void *);
53 int	pmc_wdog_cb(void *, int);
54 
55 struct cfattach pmc_ca = {
56 	sizeof(struct pmc_softc), pmc_match, pmc_attach
57 };
58 
59 struct cfdriver pmc_cd = {
60 	NULL, "pmc", DV_DULL
61 };
62 
63 int
64 pmc_match(struct device *parent, void *cf, void *aux)
65 {
66 	struct ebus_attach_args *ea = aux;
67 
68 	if (strcmp("pmc", ea->ea_name) == 0)
69 		return (1);
70 	return (0);
71 }
72 
73 void
74 pmc_attach(struct device *parent, struct device *self, void *aux)
75 {
76 	struct pmc_softc *sc = (void *)self;
77 	struct ebus_attach_args *ea = aux;
78 
79 	/* Use prom address if available, otherwise map it. */
80 	if (ea->ea_nvaddrs) {
81 		if (bus_space_map(ea->ea_memtag, ea->ea_vaddrs[0], 0,
82 		    BUS_SPACE_MAP_PROMADDRESS, &sc->sc_ioh)) {
83 			printf(": can't map PROM register space\n");
84 			return;
85 		}
86 		sc->sc_iot = ea->ea_memtag;
87 	} else if (ebus_bus_map(ea->ea_iotag, 0,
88 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
89 	    ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
90 		sc->sc_iot = ea->ea_iotag;
91 	} else if (ebus_bus_map(ea->ea_memtag, 0,
92 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
93 	    ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
94 		sc->sc_iot = ea->ea_memtag;
95 	} else {
96 		printf(": can't map register space\n");
97 		return;
98 	}
99 
100 	printf("\n");
101 
102 	wdog_register(pmc_wdog_cb, sc);
103 }
104 
105 int
106 pmc_wdog_cb(void *arg, int period)
107 {
108 	struct pmc_softc *sc = arg;
109 	int mins;
110 
111 	mins = (period + 59) / 60;
112 	if (mins > 255)
113 		mins = 255;
114 
115 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, PMC_ADDR, PMC_WDTO);
116 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, PMC_DATA, mins);
117 
118 	return (mins * 60);
119 }
120