xref: /netbsd-src/sys/dev/hpc/button.c (revision cbab9cadce21ae72fac13910001079fff214cc29)
1*cbab9cadSchs /*	$NetBSD: button.c,v 1.16 2012/10/27 17:18:17 chs Exp $	*/
24ca3c858Stakemura 
34ca3c858Stakemura /*-
426b0905dStakemura  * Copyright (c) 1999-2001
526b0905dStakemura  *         TAKEMURA Shin1 and PocketBSD Project. All rights reserved.
64ca3c858Stakemura  *
74ca3c858Stakemura  * Redistribution and use in source and binary forms, with or without
84ca3c858Stakemura  * modification, are permitted provided that the following conditions
94ca3c858Stakemura  * are met:
104ca3c858Stakemura  * 1. Redistributions of source code must retain the above copyright
114ca3c858Stakemura  *    notice, this list of conditions and the following disclaimer.
124ca3c858Stakemura  * 2. Redistributions in binary form must reproduce the above copyright
134ca3c858Stakemura  *    notice, this list of conditions and the following disclaimer in the
144ca3c858Stakemura  *    documentation and/or other materials provided with the distribution.
154ca3c858Stakemura  * 3. All advertising materials mentioning features or use of this software
164ca3c858Stakemura  *    must display the following acknowledgement:
174ca3c858Stakemura  *	This product includes software developed by the PocketBSD project
184ca3c858Stakemura  *	and its contributors.
194ca3c858Stakemura  * 4. Neither the name of the project nor the names of its contributors
204ca3c858Stakemura  *    may be used to endorse or promote products derived from this software
214ca3c858Stakemura  *    without specific prior written permission.
224ca3c858Stakemura  *
234ca3c858Stakemura  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
244ca3c858Stakemura  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
254ca3c858Stakemura  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
264ca3c858Stakemura  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
274ca3c858Stakemura  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
284ca3c858Stakemura  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
294ca3c858Stakemura  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
304ca3c858Stakemura  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
314ca3c858Stakemura  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
324ca3c858Stakemura  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
334ca3c858Stakemura  * SUCH DAMAGE.
344ca3c858Stakemura  *
354ca3c858Stakemura  */
364ca3c858Stakemura 
37b84f53efSlukem #include <sys/cdefs.h>
38*cbab9cadSchs __KERNEL_RCSID(0, "$NetBSD: button.c,v 1.16 2012/10/27 17:18:17 chs Exp $");
39b84f53efSlukem 
404ca3c858Stakemura #include <sys/param.h>
414ca3c858Stakemura #include <sys/systm.h>
424ca3c858Stakemura #include <sys/device.h>
434ca3c858Stakemura 
44a2a38285Sad #include <sys/bus.h>
454ca3c858Stakemura 
464ca3c858Stakemura #include <machine/config_hook.h>
474ca3c858Stakemura #include <machine/platid.h>
484ca3c858Stakemura #include <machine/platid_mask.h>
494ca3c858Stakemura 
504ca3c858Stakemura #include <dev/hpc/hpciovar.h>
514ca3c858Stakemura 
524ca3c858Stakemura #include "locators.h"
534ca3c858Stakemura 
5426b0905dStakemura struct button_softc {
554ca3c858Stakemura 	hpcio_chip_t sc_hc;
564ca3c858Stakemura 	hpcio_intr_handle_t sc_intr_handle;
574ca3c858Stakemura 	int sc_port;
584ca3c858Stakemura 	long sc_id;
594ca3c858Stakemura 	int sc_active;
604ca3c858Stakemura 	config_hook_tag sc_hook_tag;
614ca3c858Stakemura 	config_hook_tag sc_ghook_tag;
624ca3c858Stakemura };
634ca3c858Stakemura 
64529e91fcScegger static int	button_match(device_t, cfdata_t, void *);
65529e91fcScegger static void	button_attach(device_t, device_t, void *);
66859a6a49Such static int	button_intr(void *);
67859a6a49Such static int	button_state(void *, int, long, void *);
684ca3c858Stakemura 
69*cbab9cadSchs CFATTACH_DECL_NEW(button, sizeof(struct button_softc),
70c9b3657cSthorpej     button_match, button_attach, NULL, NULL);
714ca3c858Stakemura 
724ca3c858Stakemura int
button_match(device_t parent,cfdata_t match,void * aux)73529e91fcScegger button_match(device_t parent, cfdata_t match, void *aux)
744ca3c858Stakemura {
75a8304325Stakemura 	struct hpcio_attach_args *haa = aux;
764ca3c858Stakemura 	platid_mask_t mask;
774ca3c858Stakemura 
78a8304325Stakemura 	if (strcmp(haa->haa_busname, HPCIO_BUSNAME))
79859a6a49Such 		return (0);
804ca3c858Stakemura 	if (match->cf_loc[HPCIOIFCF_PLATFORM] == 0)
81859a6a49Such 		return (0);
824ca3c858Stakemura 	mask = PLATID_DEREF(match->cf_loc[HPCIOIFCF_PLATFORM]);
83859a6a49Such 	return (platid_match(&platid, &mask));
844ca3c858Stakemura }
854ca3c858Stakemura 
864ca3c858Stakemura void
button_attach(device_t parent,device_t self,void * aux)87529e91fcScegger button_attach(device_t parent, device_t self, void *aux)
884ca3c858Stakemura {
894ca3c858Stakemura 	struct hpcio_attach_args *haa = aux;
904ca3c858Stakemura 	int *loc;
91*cbab9cadSchs 	struct button_softc *sc = device_private(self);
924ca3c858Stakemura 	int mode;
934ca3c858Stakemura 
94*cbab9cadSchs 	loc = device_cfdata(self)->cf_loc;
9526b0905dStakemura 	sc->sc_hc = (*haa->haa_getchip)(haa->haa_sc, loc[HPCIOIFCF_IOCHIP]);
964ca3c858Stakemura 	sc->sc_port = loc[HPCIOIFCF_PORT];
974ca3c858Stakemura 	sc->sc_id = loc[HPCIOIFCF_ID];
984ca3c858Stakemura 	sc->sc_active = loc[HPCIOIFCF_ACTIVE];
994ca3c858Stakemura 	printf(" port=%d id=%ld active=%s",
1004ca3c858Stakemura 	    sc->sc_port, sc->sc_id, sc->sc_active ? "high" : "low");
1014ca3c858Stakemura 
1024ca3c858Stakemura 	mode = HPCIO_INTR_HOLD;
1034ca3c858Stakemura 	if (loc[HPCIOIFCF_LEVEL] != HPCIOIFCF_LEVEL_DEFAULT) {
1044ca3c858Stakemura 		mode |= HPCIO_INTR_LEVEL;
1054ca3c858Stakemura 		if (loc[HPCIOIFCF_LEVEL] == 0)
1064ca3c858Stakemura 			mode |= HPCIO_INTR_LOW;
1074ca3c858Stakemura 		else
1084ca3c858Stakemura 			mode |= HPCIO_INTR_HIGH;
1094ca3c858Stakemura 		printf(" sense=level");
1104ca3c858Stakemura 	} else {
1114ca3c858Stakemura 		mode |= HPCIO_INTR_EDGE;
11226b0905dStakemura 		switch (loc[HPCIOIFCF_EDGE]) {
11326b0905dStakemura 		case 1:
11426b0905dStakemura 			mode |= HPCIO_INTR_POSEDGE;
11526b0905dStakemura 			break;
11626b0905dStakemura 		case 2:
11726b0905dStakemura 			mode |= HPCIO_INTR_NEGEDGE;
11826b0905dStakemura 			break;
11926b0905dStakemura 		case 0:
12026b0905dStakemura 		case 3:
12126b0905dStakemura 		case HPCIOMANCF_EDGE_DEFAULT:
12226b0905dStakemura 			mode |= HPCIO_INTR_POSEDGE;
12326b0905dStakemura 			mode |= HPCIO_INTR_NEGEDGE;
12426b0905dStakemura 			break;
12526b0905dStakemura 		default:
12626b0905dStakemura 			printf("%s(%d): invalid configuration, edge=%d",
12726b0905dStakemura 			    __FILE__, __LINE__, loc[HPCIOIFCF_EDGE]);
12826b0905dStakemura 			break;
12926b0905dStakemura 		}
1304ca3c858Stakemura 		printf(" sense=edge");
1314ca3c858Stakemura 	}
1324ca3c858Stakemura 
1334ca3c858Stakemura 	if (sc->sc_port == HPCIOIFCF_PORT_DEFAULT ||
1344ca3c858Stakemura 	    sc->sc_id == HPCIOIFCF_ID_DEFAULT)
1354ca3c858Stakemura 		printf(" (ignored)");
1364ca3c858Stakemura 	else
1374ca3c858Stakemura 		sc->sc_intr_handle =
1384ca3c858Stakemura 		    hpcio_intr_establish(sc->sc_hc, sc->sc_port,
13926b0905dStakemura 			mode, button_intr, sc);
140859a6a49Such 	sc->sc_ghook_tag = config_hook(CONFIG_HOOK_GET, sc->sc_id,
141859a6a49Such 	    CONFIG_HOOK_SHARE, button_state, sc);
1424ca3c858Stakemura 	printf("\n");
1434ca3c858Stakemura }
1444ca3c858Stakemura 
1454ca3c858Stakemura int
button_state(void * ctx,int type,long id,void * msg)146859a6a49Such button_state(void *ctx, int type, long id, void *msg)
1474ca3c858Stakemura {
14826b0905dStakemura 	struct button_softc *sc = ctx;
1494ca3c858Stakemura 
1504ca3c858Stakemura 	if (type != CONFIG_HOOK_GET || id != sc->sc_id)
151859a6a49Such 		return (1);
1524ca3c858Stakemura 
1534ca3c858Stakemura 	if (CONFIG_HOOK_VALUEP(msg))
154859a6a49Such 		return (1);
1554ca3c858Stakemura 
1564ca3c858Stakemura 	*(int*)msg = (hpcio_portread(sc->sc_hc, sc->sc_port) == sc->sc_active);
157859a6a49Such 	return (0);
1584ca3c858Stakemura }
1594ca3c858Stakemura 
1604ca3c858Stakemura int
button_intr(void * ctx)161859a6a49Such button_intr(void *ctx)
1624ca3c858Stakemura {
16326b0905dStakemura 	struct button_softc *sc = ctx;
1644ca3c858Stakemura 	int on;
1654ca3c858Stakemura 
1664ca3c858Stakemura 	on = (hpcio_portread(sc->sc_hc, sc->sc_port) == sc->sc_active);
1674ca3c858Stakemura 
1684ca3c858Stakemura 	/* Clear interrupt */
1694ca3c858Stakemura 	hpcio_intr_clear(sc->sc_hc, sc->sc_intr_handle);
1704ca3c858Stakemura 
1714ca3c858Stakemura 	config_hook_call(CONFIG_HOOK_BUTTONEVENT, sc->sc_id, (void*)on);
1724ca3c858Stakemura 
173859a6a49Such 	return (0);
1744ca3c858Stakemura }
175