1*78d5ff0eSmpi /* $OpenBSD: power.c,v 1.11 2022/03/13 08:04:38 mpi Exp $ */
2185647a5Smickey
3185647a5Smickey /*
4185647a5Smickey * Copyright (c) 2003 Michael Shalayeff
5185647a5Smickey * All rights reserved.
6185647a5Smickey *
7185647a5Smickey * Redistribution and use in source and binary forms, with or without
8185647a5Smickey * modification, are permitted provided that the following conditions
9185647a5Smickey * are met:
10185647a5Smickey * 1. Redistributions of source code must retain the above copyright
11185647a5Smickey * notice, this list of conditions and the following disclaimer.
12185647a5Smickey * 2. Redistributions in binary form must reproduce the above copyright
13185647a5Smickey * notice, this list of conditions and the following disclaimer in the
14185647a5Smickey * documentation and/or other materials provided with the distribution.
15185647a5Smickey *
16185647a5Smickey * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17185647a5Smickey * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18185647a5Smickey * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19185647a5Smickey * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20185647a5Smickey * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21185647a5Smickey * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22185647a5Smickey * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23185647a5Smickey * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24185647a5Smickey * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25185647a5Smickey * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26185647a5Smickey * THE POSSIBILITY OF SUCH DAMAGE.
27185647a5Smickey */
28185647a5Smickey
29185647a5Smickey #include <sys/param.h>
3002d8e5b1Suebayasi #include <sys/proc.h>
3102d8e5b1Suebayasi #include <sys/signalvar.h>
32185647a5Smickey #include <sys/kernel.h>
33185647a5Smickey #include <sys/systm.h>
34185647a5Smickey #include <sys/device.h>
35185647a5Smickey #include <sys/kthread.h>
36185647a5Smickey
37185647a5Smickey #include <machine/reg.h>
380c7cde72Smickey #include <machine/pdc.h>
39185647a5Smickey #include <machine/autoconf.h>
40185647a5Smickey
41185647a5Smickey #include <hppa/dev/cpudevs.h>
42185647a5Smickey
43185647a5Smickey struct power_softc {
44185647a5Smickey struct device sc_dev;
45a5549269Smickey void *sc_ih;
46185647a5Smickey
47185647a5Smickey struct proc *sc_thread;
48185647a5Smickey void (*sc_kicker)(void *);
49185647a5Smickey
50185647a5Smickey int sc_dr_cnt;
510c7cde72Smickey paddr_t sc_pwr_reg;
52a5549269Smickey volatile int sc_interrupted;
53185647a5Smickey };
54185647a5Smickey
55185647a5Smickey int powermatch(struct device *, void *, void *);
56185647a5Smickey void powerattach(struct device *, struct device *, void *);
57185647a5Smickey
58*78d5ff0eSmpi const struct cfattach power_ca = {
59185647a5Smickey sizeof(struct power_softc), powermatch, powerattach
60185647a5Smickey };
61185647a5Smickey
62185647a5Smickey struct cfdriver power_cd = {
63185647a5Smickey NULL, "power", DV_DULL
64185647a5Smickey };
65185647a5Smickey
66185647a5Smickey void power_thread_create(void *v);
67185647a5Smickey void power_thread_dr(void *v);
680c7cde72Smickey void power_thread_reg(void *v);
690c7cde72Smickey void power_cold_hook_reg(int);
70a5549269Smickey int power_intr(void *);
71185647a5Smickey
72185647a5Smickey int
powermatch(struct device * parent,void * cfdata,void * aux)73185647a5Smickey powermatch(struct device *parent, void *cfdata, void *aux)
74185647a5Smickey {
75185647a5Smickey struct cfdata *cf = cfdata;
76185647a5Smickey struct confargs *ca = aux;
77185647a5Smickey
78185647a5Smickey if (cf->cf_unit > 0 && !strcmp(ca->ca_name, "power"))
79185647a5Smickey return (0);
80185647a5Smickey
81185647a5Smickey return (1);
82185647a5Smickey }
83185647a5Smickey
84185647a5Smickey void
powerattach(struct device * parent,struct device * self,void * aux)85185647a5Smickey powerattach(struct device *parent, struct device *self, void *aux)
86185647a5Smickey {
87185647a5Smickey struct power_softc *sc = (struct power_softc *)self;
88a5549269Smickey struct confargs *ca = aux;
89185647a5Smickey
90185647a5Smickey switch (cpu_hvers) {
91185647a5Smickey case HPPA_BOARD_HP712_60:
92185647a5Smickey case HPPA_BOARD_HP712_80:
93185647a5Smickey case HPPA_BOARD_HP712_100:
94185647a5Smickey case HPPA_BOARD_HP712_120:
95185647a5Smickey sc->sc_kicker = power_thread_dr;
960c7cde72Smickey printf(": DR25\n");
97185647a5Smickey break;
980c7cde72Smickey
99185647a5Smickey default:
100a5549269Smickey if (ca->ca_hpa) {
1010c7cde72Smickey extern void (*cold_hook)(int);
1020c7cde72Smickey
103a5549269Smickey sc->sc_pwr_reg = ca->ca_hpa;
1040c7cde72Smickey cold_hook = power_cold_hook_reg;
1050c7cde72Smickey sc->sc_kicker = power_thread_reg;
106a5549269Smickey printf("\n");
107a5549269Smickey } else
108a5549269Smickey printf(": not available\n");
109185647a5Smickey break;
110185647a5Smickey }
111185647a5Smickey
112a5549269Smickey if (ca->ca_irq >= 0)
113a5549269Smickey sc->sc_ih = cpu_intr_establish(IPL_CLOCK, ca->ca_irq,
114a5549269Smickey power_intr, sc, sc->sc_dev.dv_xname);
115a5549269Smickey
116185647a5Smickey if (sc->sc_kicker)
117185647a5Smickey kthread_create_deferred(power_thread_create, sc);
118185647a5Smickey }
119185647a5Smickey
120a5549269Smickey int
power_intr(void * v)121a5549269Smickey power_intr(void *v)
122a5549269Smickey {
123a5549269Smickey struct power_softc *sc = v;
124a5549269Smickey
125a5549269Smickey sc->sc_interrupted = 1;
126a5549269Smickey
127a5549269Smickey return (1);
128a5549269Smickey }
129a5549269Smickey
130185647a5Smickey void
power_thread_create(void * v)131185647a5Smickey power_thread_create(void *v)
132185647a5Smickey {
133185647a5Smickey struct power_softc *sc = v;
134185647a5Smickey
135185647a5Smickey if (kthread_create(sc->sc_kicker, sc, &sc->sc_thread,
136308f2339Smickey sc->sc_dev.dv_xname))
137185647a5Smickey printf("WARNING: failed to create kernel power thread\n");
138185647a5Smickey }
139185647a5Smickey
140185647a5Smickey void
power_thread_dr(void * v)141185647a5Smickey power_thread_dr(void *v)
142185647a5Smickey {
143185647a5Smickey struct power_softc *sc = v;
144185647a5Smickey u_int32_t r;
145185647a5Smickey
146185647a5Smickey for (;;) {
147185647a5Smickey mfcpu(DR0_PCXL_SHINT_EN, r); /* XXX don't ask */
148185647a5Smickey if (r & 0x80000000)
149185647a5Smickey sc->sc_dr_cnt = 0;
150185647a5Smickey else
151185647a5Smickey sc->sc_dr_cnt++;
152185647a5Smickey
153185647a5Smickey /*
154185647a5Smickey * the bit is undampened straight wire from the power
155185647a5Smickey * switch and thus we have do dampen it ourselves.
156185647a5Smickey */
157185647a5Smickey if (sc->sc_dr_cnt == hz / 10)
15802d8e5b1Suebayasi prsignal(initprocess, SIGUSR2);
159185647a5Smickey
160448a8ce5Scheloha tsleep_nsec(v, PWAIT, "drpower", MSEC_TO_NSEC(100));
161185647a5Smickey }
162185647a5Smickey }
1630c7cde72Smickey
1640c7cde72Smickey void
power_thread_reg(void * v)1650c7cde72Smickey power_thread_reg(void *v)
1660c7cde72Smickey {
1670c7cde72Smickey struct power_softc *sc = v;
1680c7cde72Smickey u_int32_t r;
1690c7cde72Smickey
1700c7cde72Smickey for (;;) {
1712df76cc2Sguenther __asm volatile("ldwas 0(%1), %0"
1720c7cde72Smickey : "=&r" (r) : "r" (sc->sc_pwr_reg));
1730c7cde72Smickey
1740c7cde72Smickey if (!(r & 1))
175cc18e21dSmiod prsignal(initprocess, SIGUSR2);
1760c7cde72Smickey
177448a8ce5Scheloha tsleep_nsec(v, PWAIT, "regpower", MSEC_TO_NSEC(100));
1780c7cde72Smickey }
1790c7cde72Smickey }
1800c7cde72Smickey
1810c7cde72Smickey void
power_cold_hook_reg(int on)1820c7cde72Smickey power_cold_hook_reg(int on)
1830c7cde72Smickey {
184a5549269Smickey extern struct pdc_power_info pdc_power_info; /* machdep.c */
1850c7cde72Smickey int error;
1860c7cde72Smickey
1870c7cde72Smickey if ((error = pdc_call((iodcio_t)pdc, 0, PDC_SOFT_POWER,
1880c7cde72Smickey PDC_SOFT_POWER_ENABLE, &pdc_power_info,
1890c7cde72Smickey on == HPPA_COLD_HOT)))
1900c7cde72Smickey printf("power_cold_hook_reg: failed (%d)\n", error);
1910c7cde72Smickey }
192