xref: /netbsd-src/sys/arch/evbppc/wii/dev/resetbtn.c (revision 73647a8fde59477a6b38dc9375ebe1c35a0a1cd1)
1*73647a8fSjmcneill /* $NetBSD: resetbtn.c,v 1.2 2024/01/23 21:56:07 jmcneill Exp $ */
28d626ee2Sjmcneill 
38d626ee2Sjmcneill /*-
48d626ee2Sjmcneill  * Copyright (c) 2024 Jared McNeill <jmcneill@invisible.ca>
58d626ee2Sjmcneill  * All rights reserved.
68d626ee2Sjmcneill  *
78d626ee2Sjmcneill  * Redistribution and use in source and binary forms, with or without
88d626ee2Sjmcneill  * modification, are permitted provided that the following conditions
98d626ee2Sjmcneill  * are met:
108d626ee2Sjmcneill  * 1. Redistributions of source code must retain the above copyright
118d626ee2Sjmcneill  *    notice, this list of conditions and the following disclaimer.
128d626ee2Sjmcneill  * 2. Redistributions in binary form must reproduce the above copyright
138d626ee2Sjmcneill  *    notice, this list of conditions and the following disclaimer in the
148d626ee2Sjmcneill  *    documentation and/or other materials provided with the distribution.
158d626ee2Sjmcneill  *
168d626ee2Sjmcneill  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
178d626ee2Sjmcneill  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
188d626ee2Sjmcneill  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
198d626ee2Sjmcneill  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
208d626ee2Sjmcneill  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
218d626ee2Sjmcneill  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
228d626ee2Sjmcneill  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
238d626ee2Sjmcneill  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
248d626ee2Sjmcneill  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
258d626ee2Sjmcneill  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
268d626ee2Sjmcneill  * SUCH DAMAGE.
278d626ee2Sjmcneill  */
288d626ee2Sjmcneill 
298d626ee2Sjmcneill #include <sys/cdefs.h>
30*73647a8fSjmcneill __KERNEL_RCSID(0, "$NetBSD: resetbtn.c,v 1.2 2024/01/23 21:56:07 jmcneill Exp $");
318d626ee2Sjmcneill 
328d626ee2Sjmcneill #include <sys/param.h>
338d626ee2Sjmcneill #include <sys/bus.h>
348d626ee2Sjmcneill #include <sys/device.h>
358d626ee2Sjmcneill #include <sys/systm.h>
368d626ee2Sjmcneill #include <sys/reboot.h>
378d626ee2Sjmcneill #include <powerpc/pio.h>
388d626ee2Sjmcneill #include <dev/sysmon/sysmonvar.h>
398d626ee2Sjmcneill #include <dev/sysmon/sysmon_taskq.h>
408d626ee2Sjmcneill 
418d626ee2Sjmcneill #include "hollywood.h"
428d626ee2Sjmcneill 
438d626ee2Sjmcneill #define	PI_INTERRUPT_CAUSE	0x0c003000
448d626ee2Sjmcneill #define	 RESET_SWITCH_STATE	__BIT(16)
458d626ee2Sjmcneill 
468d626ee2Sjmcneill static int	resetbtn_match(device_t, cfdata_t, void *);
478d626ee2Sjmcneill static void	resetbtn_attach(device_t, device_t, void *);
488d626ee2Sjmcneill 
498d626ee2Sjmcneill static int	resetbtn_intr(void *);
508d626ee2Sjmcneill static void	resetbtn_task(void *);
518d626ee2Sjmcneill 
528d626ee2Sjmcneill CFATTACH_DECL_NEW(resetbtn, sizeof(struct sysmon_pswitch),
538d626ee2Sjmcneill 	resetbtn_match, resetbtn_attach, NULL, NULL);
548d626ee2Sjmcneill 
558d626ee2Sjmcneill static int
resetbtn_match(device_t parent,cfdata_t cf,void * aux)568d626ee2Sjmcneill resetbtn_match(device_t parent, cfdata_t cf, void *aux)
578d626ee2Sjmcneill {
588d626ee2Sjmcneill 	return 1;
598d626ee2Sjmcneill }
608d626ee2Sjmcneill 
618d626ee2Sjmcneill static void
resetbtn_attach(device_t parent,device_t self,void * aux)628d626ee2Sjmcneill resetbtn_attach(device_t parent, device_t self, void *aux)
638d626ee2Sjmcneill {
648d626ee2Sjmcneill 	struct hollywood_attach_args *haa = aux;
658d626ee2Sjmcneill 	struct sysmon_pswitch *smpsw = device_private(self);
668d626ee2Sjmcneill 	int error;
678d626ee2Sjmcneill 
688d626ee2Sjmcneill 	KASSERT(device_unit(self) == 0);
698d626ee2Sjmcneill 
708d626ee2Sjmcneill 	aprint_naive("\n");
718d626ee2Sjmcneill 	aprint_normal(": Reset button\n");
728d626ee2Sjmcneill 
738d626ee2Sjmcneill 	sysmon_task_queue_init();
748d626ee2Sjmcneill 
758d626ee2Sjmcneill 	smpsw->smpsw_name = device_xname(self);
768d626ee2Sjmcneill 	smpsw->smpsw_type = PSWITCH_TYPE_RESET;
778d626ee2Sjmcneill 	error = sysmon_pswitch_register(smpsw);
788d626ee2Sjmcneill 	if (error != 0) {
798d626ee2Sjmcneill 		aprint_error_dev(self,
808d626ee2Sjmcneill 		    "unable to register reset button with sysmon: %d\n", error);
818d626ee2Sjmcneill 		smpsw = NULL;
828d626ee2Sjmcneill 	}
838d626ee2Sjmcneill 
84*73647a8fSjmcneill 	hollywood_intr_establish(haa->haa_irq, IPL_HIGH, resetbtn_intr, smpsw,
85*73647a8fSjmcneill 	    device_xname(self));
868d626ee2Sjmcneill }
878d626ee2Sjmcneill 
888d626ee2Sjmcneill static int
resetbtn_intr(void * arg)898d626ee2Sjmcneill resetbtn_intr(void *arg)
908d626ee2Sjmcneill {
918d626ee2Sjmcneill 	struct sysmon_pswitch *smpsw = arg;
928d626ee2Sjmcneill 
938d626ee2Sjmcneill 	sysmon_task_queue_sched(0, resetbtn_task, smpsw);
948d626ee2Sjmcneill 
958d626ee2Sjmcneill 	return 1;
968d626ee2Sjmcneill }
978d626ee2Sjmcneill 
988d626ee2Sjmcneill static void
resetbtn_task(void * arg)998d626ee2Sjmcneill resetbtn_task(void *arg)
1008d626ee2Sjmcneill {
1018d626ee2Sjmcneill 	struct sysmon_pswitch *smpsw = arg;
1028d626ee2Sjmcneill 	bool pressed;
1038d626ee2Sjmcneill 
1048d626ee2Sjmcneill 	pressed = (in32(PI_INTERRUPT_CAUSE) & RESET_SWITCH_STATE) == 0;
1058d626ee2Sjmcneill 
1068d626ee2Sjmcneill 	if (smpsw != NULL) {
1078d626ee2Sjmcneill 		sysmon_pswitch_event(smpsw,
1088d626ee2Sjmcneill 		    pressed ? PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED);
1098d626ee2Sjmcneill 	} else if (!pressed) {
1108d626ee2Sjmcneill 		kern_reboot(0, NULL);
1118d626ee2Sjmcneill 	}
1128d626ee2Sjmcneill }
113