xref: /netbsd-src/sys/dev/hpc/hpcioman.c (revision c7fb772b85b2b5d4cfb282f868f454b4701534fd)
1*c7fb772bSthorpej /*	$NetBSD: hpcioman.c,v 1.21 2021/08/07 16:19:11 thorpej Exp $ */
226b0905dStakemura 
326b0905dStakemura /*-
426b0905dStakemura  * Copyright (c) 1999-2001 The NetBSD Foundation, Inc.
526b0905dStakemura  * All rights reserved.
626b0905dStakemura  *
726b0905dStakemura  * This code is derived from software contributed to The NetBSD Foundation
826b0905dStakemura  * by UCHIYAMA Yasushi.
926b0905dStakemura  *
1026b0905dStakemura  * Redistribution and use in source and binary forms, with or without
1126b0905dStakemura  * modification, are permitted provided that the following conditions
1226b0905dStakemura  * are met:
1326b0905dStakemura  * 1. Redistributions of source code must retain the above copyright
1426b0905dStakemura  *    notice, this list of conditions and the following disclaimer.
1526b0905dStakemura  * 2. Redistributions in binary form must reproduce the above copyright
1626b0905dStakemura  *    notice, this list of conditions and the following disclaimer in the
1726b0905dStakemura  *    documentation and/or other materials provided with the distribution.
1826b0905dStakemura  *
1926b0905dStakemura  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2026b0905dStakemura  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2126b0905dStakemura  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2226b0905dStakemura  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2326b0905dStakemura  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2426b0905dStakemura  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2526b0905dStakemura  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2626b0905dStakemura  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2726b0905dStakemura  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2826b0905dStakemura  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2926b0905dStakemura  * POSSIBILITY OF SUCH DAMAGE.
3026b0905dStakemura  */
3126b0905dStakemura 
32b84f53efSlukem #include <sys/cdefs.h>
33*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: hpcioman.c,v 1.21 2021/08/07 16:19:11 thorpej Exp $");
34b84f53efSlukem 
3526b0905dStakemura #include <sys/param.h>
3626b0905dStakemura #include <sys/systm.h>
3726b0905dStakemura #include <sys/device.h>
3826b0905dStakemura 
3926b0905dStakemura #include <machine/config_hook.h>
4026b0905dStakemura #include <machine/platid.h>
4126b0905dStakemura #include <machine/platid_mask.h>
4226b0905dStakemura 
43a2a38285Sad #include <sys/bus.h>
4426b0905dStakemura #include <dev/hpc/hpciovar.h>
4526b0905dStakemura #include <dev/hpc/hpciomanvar.h>
4626b0905dStakemura 
4726b0905dStakemura #include "locators.h"
4826b0905dStakemura 
49529e91fcScegger int	hpcioman_match(device_t, cfdata_t, void *);
50529e91fcScegger void	hpcioman_attach(device_t, device_t, void *);
5126b0905dStakemura int	hpcioman_print(void *, const char *);
52cbab9cadSchs int	hpcioman_search(device_t, cfdata_t, const int *, void *);
5326b0905dStakemura 
54cbab9cadSchs CFATTACH_DECL_NEW(hpcioman, 0,
55c9b3657cSthorpej     hpcioman_match, hpcioman_attach, NULL, NULL);
5626b0905dStakemura 
5726b0905dStakemura int
hpcioman_match(device_t parent,cfdata_t cf,void * aux)58529e91fcScegger hpcioman_match(device_t parent, cfdata_t cf, void *aux)
5926b0905dStakemura {
60a8304325Stakemura 	struct hpcio_attach_args *haa = aux;
6126b0905dStakemura 	platid_mask_t mask;
6226b0905dStakemura 
63a8304325Stakemura 	if (strcmp(haa->haa_busname, HPCIO_BUSNAME))
64859a6a49Such 		return (0);
6526b0905dStakemura 	/* select platform */
6626b0905dStakemura 	mask = PLATID_DEREF(cf->cf_loc[HPCIOIFCF_PLATFORM]);
6726b0905dStakemura 
68859a6a49Such 	return (platid_match(&platid, &mask));
6926b0905dStakemura }
7026b0905dStakemura 
7126b0905dStakemura void
hpcioman_attach(device_t parent,device_t self,void * aux)72529e91fcScegger hpcioman_attach(device_t parent, device_t self, void *aux)
7326b0905dStakemura {
7426b0905dStakemura 	printf("\n");
7526b0905dStakemura 
762685996bSthorpej 	config_search(self, aux,
77*c7fb772bSthorpej 	    CFARGS(.search = hpcioman_search));
7826b0905dStakemura }
7926b0905dStakemura 
8026b0905dStakemura int
hpcioman_search(device_t parent,cfdata_t cf,const int * ldesc,void * aux)81cbab9cadSchs hpcioman_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
8226b0905dStakemura {
8326b0905dStakemura 	struct hpcio_attach_args *haa = aux;
8426b0905dStakemura 	struct hpcioman_attach_args hma;
8526b0905dStakemura 
8626b0905dStakemura 	/* get io chip */
8726b0905dStakemura 	hma.hma_hc = (*haa->haa_getchip)(haa->haa_sc, cf->cf_iochip);
8826b0905dStakemura 
8926b0905dStakemura 	/* interrupt mode */
9026b0905dStakemura 	if (cf->cf_level != HPCIOMANCF_LEVEL_DEFAULT) {
913d94c421Stakemura 		switch (cf->cf_hold) {
923d94c421Stakemura 		case 1:
933d94c421Stakemura 			hma.hma_intr_mode = HPCIO_INTR_HOLD;
943d94c421Stakemura 			break;
953d94c421Stakemura 		case 0:
963d94c421Stakemura 		case HPCIOMANCF_HOLD_DEFAULT:
973d94c421Stakemura 		default:
983d94c421Stakemura 			hma.hma_intr_mode = HPCIO_INTR_THROUGH;
993d94c421Stakemura 			break;
1003d94c421Stakemura 		}
10126b0905dStakemura 		hma.hma_intr_mode |= HPCIO_INTR_LEVEL;
10226b0905dStakemura 		if (cf->cf_level == 0)
10326b0905dStakemura 			hma.hma_intr_mode |= HPCIO_INTR_LOW;
10426b0905dStakemura 		else
10526b0905dStakemura 			hma.hma_intr_mode |= HPCIO_INTR_HIGH;
10626b0905dStakemura 	} else {
1073d94c421Stakemura 		switch (cf->cf_hold) {
1083d94c421Stakemura 		case 0:
1093d94c421Stakemura 			hma.hma_intr_mode = HPCIO_INTR_THROUGH;
1103d94c421Stakemura 			break;
1113d94c421Stakemura 		case 1:
1123d94c421Stakemura 		case HPCIOMANCF_HOLD_DEFAULT:
1133d94c421Stakemura 		default:
1143d94c421Stakemura 			hma.hma_intr_mode = HPCIO_INTR_HOLD;
1153d94c421Stakemura 			break;
1163d94c421Stakemura 		}
11726b0905dStakemura 		hma.hma_intr_mode |= HPCIO_INTR_EDGE;
11826b0905dStakemura 		switch (cf->cf_edge) {
11926b0905dStakemura 		case 1:
12026b0905dStakemura 			hma.hma_intr_mode |= HPCIO_INTR_POSEDGE;
12126b0905dStakemura 			break;
12226b0905dStakemura 		case 2:
12326b0905dStakemura 			hma.hma_intr_mode |= HPCIO_INTR_NEGEDGE;
12426b0905dStakemura 			break;
12526b0905dStakemura 		case 0:
12626b0905dStakemura 		case 3:
12726b0905dStakemura 		case HPCIOMANCF_EDGE_DEFAULT:
12826b0905dStakemura 			hma.hma_intr_mode |= HPCIO_INTR_POSEDGE;
12926b0905dStakemura 			hma.hma_intr_mode |= HPCIO_INTR_NEGEDGE;
13026b0905dStakemura 			break;
13126b0905dStakemura 		default:
13226b0905dStakemura 			printf("%s(%d): invalid configuration, edge=%d",
13326b0905dStakemura 			    __FILE__, __LINE__, cf->cf_edge);
13426b0905dStakemura 			break;
13526b0905dStakemura 		}
13626b0905dStakemura 	}
13726b0905dStakemura 
13826b0905dStakemura 	hma.hma_type = cf->cf_type;
13926b0905dStakemura 	hma.hma_id = cf->cf_id;
14026b0905dStakemura 	hma.hma_port = cf->cf_port;
14126b0905dStakemura 	if (cf->cf_active == 0) {
14226b0905dStakemura 		hma.hma_on = 0;
14326b0905dStakemura 		hma.hma_off = 1;
14426b0905dStakemura 	} else {
14526b0905dStakemura 		hma.hma_on = 1;
14626b0905dStakemura 		hma.hma_off = 0;
14726b0905dStakemura 	}
14826b0905dStakemura 	hma.hma_initvalue = -1; /* none */
14926b0905dStakemura 	if (cf->cf_initvalue != HPCIOMANCF_INITVALUE_DEFAULT) {
15026b0905dStakemura 		if (cf->cf_initvalue == 0)
15126b0905dStakemura 			hma.hma_initvalue = hma.hma_off;
15226b0905dStakemura 		else
15326b0905dStakemura 			hma.hma_initvalue = hma.hma_on;
15426b0905dStakemura 	}
1553d94c421Stakemura 	hma.hma_connect = cf->cf_connect;
15626b0905dStakemura 
157*c7fb772bSthorpej 	config_attach(parent, cf, &hma, hpcioman_print, CFARGS_NONE);
15826b0905dStakemura 
15926b0905dStakemura 	return (0);
16026b0905dStakemura }
16126b0905dStakemura 
16226b0905dStakemura int
hpcioman_print(void * aux,const char * pnp)16326b0905dStakemura hpcioman_print(void *aux, const char *pnp)
16426b0905dStakemura {
16526b0905dStakemura 	struct hpcioman_attach_args *hma = aux;
16626b0905dStakemura 	int type = hma->hma_type;
16726b0905dStakemura 
16826b0905dStakemura 	if (!pnp)  {
169703e7687Sthorpej 		aprint_normal(" iochip %s, port %d, type %d, id %d",
17026b0905dStakemura 		    hma->hma_hc ? hma->hma_hc->hc_name : "not found",
17126b0905dStakemura 		    hma->hma_port, type, hma->hma_id);
17226b0905dStakemura 		if (type == CONFIG_HOOK_BUTTONEVENT ||
17326b0905dStakemura 		    type == CONFIG_HOOK_PMEVENT ||
1743d94c421Stakemura 		    type == CONFIG_HOOK_EVENT ||
1753d94c421Stakemura 		    type == CONFIG_HOOK_PCIINTR) {
17626b0905dStakemura 			if (hma->hma_intr_mode & HPCIO_INTR_EDGE)
177703e7687Sthorpej 				aprint_normal (", interrupt edge [%s%s]",
178859a6a49Such 				    (hma->hma_intr_mode&HPCIO_INTR_POSEDGE)
179859a6a49Such 				    ? "p" : "",
180859a6a49Such 				    (hma->hma_intr_mode&HPCIO_INTR_NEGEDGE)
181859a6a49Such 				    ? "n" : "");
18226b0905dStakemura 			else
183703e7687Sthorpej 				aprint_normal (", interrupt level %s",
184859a6a49Such 				    (hma->hma_intr_mode&HPCIO_INTR_HIGH) ?
185859a6a49Such 				    "high" : "low");
18626b0905dStakemura 		}
18726b0905dStakemura 		if (hma->hma_initvalue != -1)
188703e7687Sthorpej 			aprint_normal(", initial value %d", hma->hma_initvalue);
18926b0905dStakemura 		if (hma->hma_on == 0)
190703e7687Sthorpej 			aprint_normal(", active low");
19126b0905dStakemura 	}
19226b0905dStakemura 
193859a6a49Such 	return (QUIET);
19426b0905dStakemura }
195