xref: /netbsd-src/sys/arch/hpcarm/dev/ipaq_pcic.c (revision 7433666e375b3ac4cc764df5a6726be98bc1cdd5)
1*7433666eSthorpej /*      $NetBSD: ipaq_pcic.c,v 1.24 2023/12/20 14:50:02 thorpej Exp $        */
2f4083490Sichiro 
3f4083490Sichiro /*-
4f4083490Sichiro  * Copyright (c) 2001 The NetBSD Foundation, Inc.
5f4083490Sichiro  * All rights reserved.
6f4083490Sichiro  *
7f4083490Sichiro  * This code is derived from software contributed to The NetBSD Foundation
8f4083490Sichiro  * by Ichiro FUKUHARA (ichiro@ichiro.org).
9f4083490Sichiro  *
10f4083490Sichiro  * Redistribution and use in source and binary forms, with or without
11f4083490Sichiro  * modification, are permitted provided that the following conditions
12f4083490Sichiro  * are met:
13f4083490Sichiro  * 1. Redistributions of source code must retain the above copyright
14f4083490Sichiro  *    notice, this list of conditions and the following disclaimer.
15f4083490Sichiro  * 2. Redistributions in binary form must reproduce the above copyright
16f4083490Sichiro  *    notice, this list of conditions and the following disclaimer in the
17f4083490Sichiro  *    documentation and/or other materials provided with the distribution.
18f4083490Sichiro  *
19f4083490Sichiro  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20f4083490Sichiro  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21f4083490Sichiro  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22f4083490Sichiro  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23f4083490Sichiro  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24f4083490Sichiro  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25f4083490Sichiro  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26f4083490Sichiro  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27f4083490Sichiro  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28f4083490Sichiro  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29f4083490Sichiro  * POSSIBILITY OF SUCH DAMAGE.
30f4083490Sichiro  */
31f4083490Sichiro 
3208716eaeSlukem #include <sys/cdefs.h>
33*7433666eSthorpej __KERNEL_RCSID(0, "$NetBSD: ipaq_pcic.c,v 1.24 2023/12/20 14:50:02 thorpej Exp $");
3408716eaeSlukem 
35f4083490Sichiro #include <sys/param.h>
36f4083490Sichiro #include <sys/systm.h>
37f4083490Sichiro #include <sys/types.h>
38f4083490Sichiro #include <sys/conf.h>
39f4083490Sichiro #include <sys/file.h>
40f4083490Sichiro #include <sys/device.h>
41f4083490Sichiro #include <sys/kernel.h>
42f4083490Sichiro #include <sys/kthread.h>
439edf49b0Sdyoung #include <sys/bus.h>
44f4083490Sichiro 
45f4083490Sichiro #include <dev/pcmcia/pcmciachip.h>
46f4083490Sichiro #include <dev/pcmcia/pcmciavar.h>
47f4083490Sichiro 
48f4083490Sichiro #include <hpcarm/dev/ipaq_saipvar.h>
49f4083490Sichiro #include <hpcarm/dev/ipaq_pcicreg.h>
50f4083490Sichiro #include <hpcarm/dev/ipaq_gpioreg.h>
51c0a235d4Sichiro 
52c0a235d4Sichiro #include <arm/sa11x0/sa11x0_gpioreg.h>
53c0a235d4Sichiro #include <arm/sa11x0/sa11x0_var.h>
54c0a235d4Sichiro #include <arm/sa11x0/sa11xx_pcicvar.h>
55f4083490Sichiro 
56f4083490Sichiro #include "ipaqpcic.h"
57f4083490Sichiro 
584c494f76Srjs static	int	ipaqpcic_match(device_t, cfdata_t, void *);
594c494f76Srjs static	void	ipaqpcic_attach(device_t, device_t, void *);
60f4083490Sichiro static	int	ipaqpcic_print(void *, const char *);
61f4083490Sichiro 
62f4083490Sichiro static	int	ipaqpcic_read(struct sapcic_socket *, int);
63f4083490Sichiro static	void	ipaqpcic_write(struct sapcic_socket *, int, int);
64f4083490Sichiro static	void	ipaqpcic_set_power(struct sapcic_socket *, int);
65f4083490Sichiro static	void	ipaqpcic_clear_intr(int);
66f4083490Sichiro static	void	*ipaqpcic_intr_establish(struct sapcic_socket *, int,
67f4083490Sichiro 				       int (*)(void *), void *);
68f4083490Sichiro static	void	ipaqpcic_intr_disestablish(struct sapcic_socket *, void *);
69f4083490Sichiro 
70f4083490Sichiro struct ipaqpcic_softc {
71f4083490Sichiro 	struct sapcic_softc	sc_pc;
72f4083490Sichiro 	bus_space_handle_t	sc_ioh;
7360f2ec7eSichiro 	struct ipaq_softc	*sc_parent;
74f4083490Sichiro 	struct sapcic_socket	sc_socket[2];
75f4083490Sichiro };
76f4083490Sichiro 
7760f2ec7eSichiro static	void	ipaqpcic_init(struct ipaqpcic_softc *);
7860f2ec7eSichiro 
79f4083490Sichiro static struct sapcic_tag ipaqpcic_functions = {
80f4083490Sichiro 	ipaqpcic_read,
81f4083490Sichiro 	ipaqpcic_write,
82f4083490Sichiro 	ipaqpcic_set_power,
83f4083490Sichiro 	ipaqpcic_clear_intr,
84f4083490Sichiro 	ipaqpcic_intr_establish,
85f4083490Sichiro 	ipaqpcic_intr_disestablish
86f4083490Sichiro };
87f4083490Sichiro 
884c494f76Srjs CFATTACH_DECL_NEW(ipaqpcic, sizeof(struct ipaqpcic_softc),
89c5e91d44Sthorpej     ipaqpcic_match, ipaqpcic_attach, NULL, NULL);
90f4083490Sichiro 
91f4083490Sichiro static int
ipaqpcic_match(device_t parent,cfdata_t cf,void * aux)924c494f76Srjs ipaqpcic_match(device_t parent, cfdata_t cf, void *aux)
93f4083490Sichiro {
94f4083490Sichiro 	return (1);
95f4083490Sichiro }
96f4083490Sichiro 
97f4083490Sichiro static void
ipaqpcic_attach(device_t parent,device_t self,void * aux)984c494f76Srjs ipaqpcic_attach(device_t parent, device_t self, void *aux)
99f4083490Sichiro {
100f4083490Sichiro 	int i;
101f4083490Sichiro 	struct pcmciabus_attach_args paa;
1024c494f76Srjs 	struct ipaqpcic_softc *sc = device_private(self);
1034c494f76Srjs 	struct ipaq_softc *psc = device_private(parent);
104f4083490Sichiro 
1054c494f76Srjs 	aprint_normal("\n");
106f4083490Sichiro 
1074c494f76Srjs 	sc->sc_pc.sc_dev = self;
108f4083490Sichiro 	sc->sc_pc.sc_iot = psc->sc_iot;
109f4083490Sichiro 	sc->sc_ioh = psc->sc_ioh;
1104c494f76Srjs 	sc->sc_parent = psc;
111f4083490Sichiro 
11260f2ec7eSichiro 	ipaqpcic_init(sc);
113f4083490Sichiro 
114f4083490Sichiro 	for(i = 0; i < 2; i++) {
115f4083490Sichiro 		sc->sc_socket[i].sc = (struct sapcic_softc *)sc;
116f4083490Sichiro 		sc->sc_socket[i].socket = i;
117124bde73Stoshii 		sc->sc_socket[i].pcictag_cookie = psc;
118f4083490Sichiro 		sc->sc_socket[i].pcictag = &ipaqpcic_functions;
119f4083490Sichiro 		sc->sc_socket[i].event_thread = NULL;
120f4083490Sichiro 		sc->sc_socket[i].event = 0;
121f4083490Sichiro 		sc->sc_socket[i].laststatus = SAPCIC_CARD_INVALID;
122f4083490Sichiro 		sc->sc_socket[i].shutdown = 0;
123f4083490Sichiro 
124f4083490Sichiro 		paa.paa_busname = "pcmcia";
125f4083490Sichiro 		paa.pct = (pcmcia_chipset_tag_t)&sa11x0_pcmcia_functions;
126f4083490Sichiro 		paa.pch = (pcmcia_chipset_handle_t)&sc->sc_socket[i];
127f4083490Sichiro 
128f4083490Sichiro 		sc->sc_socket[i].pcmcia =
1292685996bSthorpej 		    config_found(sc->sc_pc.sc_dev, &paa, ipaqpcic_print,
130c7fb772bSthorpej 				 CFARGS_NONE);
131f4083490Sichiro 
132f4083490Sichiro 		sa11x0_intr_establish((sa11x0_chipset_tag_t)psc,
133f4083490Sichiro 			    i ? IRQ_CD1 : IRQ_CD0,
134f4083490Sichiro 			    1, IPL_BIO, sapcic_intr,
135f4083490Sichiro 			    &sc->sc_socket[i]);
136f4083490Sichiro 
137f4083490Sichiro 		/* schedule kthread creation */
13888ab7da9Sad 		sapcic_kthread_create(&sc->sc_socket[i]);
139f4083490Sichiro 
140f4083490Sichiro #if 0 /* XXX */
141f4083490Sichiro 		/* establish_intr should be after creating the kthread */
142f4083490Sichiro 		config_interrupt(&sc->sc_socket[i], ipaqpcic_config_intr);
143f4083490Sichiro #endif
144f4083490Sichiro 	}
145f4083490Sichiro }
146f4083490Sichiro 
147f4083490Sichiro static int
ipaqpcic_print(void * aux,const char * name)1480107b5e7Srjs ipaqpcic_print(void *aux, const char *name)
149f4083490Sichiro {
150f4083490Sichiro 	return (UNCONF);
151f4083490Sichiro }
152f4083490Sichiro 
15360f2ec7eSichiro static void
ipaqpcic_init(struct ipaqpcic_softc * sc)1540107b5e7Srjs ipaqpcic_init(struct ipaqpcic_softc *sc)
15560f2ec7eSichiro {
156d9f2bbf3Sichiro 	int cr;
157d9f2bbf3Sichiro 
158d9f2bbf3Sichiro 	/* All those are inputs */
159d9f2bbf3Sichiro 	cr = bus_space_read_4(sc->sc_pc.sc_iot, sc->sc_parent->sc_gpioh, SAGPIO_PDR);
160d9f2bbf3Sichiro 	cr &= ~(GPIO_H3600_PCMCIA_CD0 | GPIO_H3600_PCMCIA_CD1 | GPIO_H3600_PCMCIA_IRQ0 |
161d9f2bbf3Sichiro 		GPIO_H3600_PCMCIA_IRQ1);
162d9f2bbf3Sichiro 	bus_space_write_4(sc->sc_pc.sc_iot, sc->sc_parent->sc_gpioh, SAGPIO_PDR, cr);
163d9f2bbf3Sichiro 
16460f2ec7eSichiro 	sc->sc_parent->ipaq_egpio |=
16560f2ec7eSichiro 		EGPIO_H3600_OPT_NVRAM_ON | EGPIO_H3600_OPT_ON ;
16660f2ec7eSichiro 	sc->sc_parent->ipaq_egpio &=
16760f2ec7eSichiro 		~(EGPIO_H3600_CARD_RESET | EGPIO_H3600_OPT_RESET);
16860f2ec7eSichiro 	bus_space_write_2(sc->sc_pc.sc_iot, sc->sc_parent->sc_egpioh,
16960f2ec7eSichiro 			  0, sc->sc_parent->ipaq_egpio);
17060f2ec7eSichiro }
171f4083490Sichiro 
172f4083490Sichiro static int
ipaqpcic_read(struct sapcic_socket * so,int reg)1730107b5e7Srjs ipaqpcic_read(struct sapcic_socket *so, int reg)
174f4083490Sichiro {
175f4083490Sichiro 	int cr, bit;
176f4083490Sichiro 	struct ipaqpcic_softc *sc = (struct ipaqpcic_softc *)so->sc;
177f4083490Sichiro 
17860f2ec7eSichiro 	cr = bus_space_read_4(sc->sc_pc.sc_iot, sc->sc_parent->sc_gpioh, SAGPIO_PLR);
179f4083490Sichiro 
180f4083490Sichiro 	switch (reg) {
181f4083490Sichiro 	case SAPCIC_STATUS_CARD:
182d9f2bbf3Sichiro 		bit = (so->socket ? GPIO_H3600_PCMCIA_CD0 :
183d9f2bbf3Sichiro 				GPIO_H3600_PCMCIA_CD1) & cr;
184d9f2bbf3Sichiro 		if (!bit)
185f4083490Sichiro 			return SAPCIC_CARD_INVALID;
186f4083490Sichiro 		else
187f4083490Sichiro 			return SAPCIC_CARD_VALID;
188f4083490Sichiro 	case SAPCIC_STATUS_VS1:
189f4083490Sichiro         case SAPCIC_STATUS_VS2:
190d9f2bbf3Sichiro 	case SAPCIC_STATUS_READY:
191d9f2bbf3Sichiro 		bit = (so->socket ? GPIO_H3600_PCMCIA_IRQ0:
192d9f2bbf3Sichiro 				GPIO_H3600_PCMCIA_IRQ1);
193d9f2bbf3Sichiro 		return (bit & cr);
194f4083490Sichiro 	default:
1950f09ed48Sprovos 		panic("ipaqpcic_read: bogus register");
196f4083490Sichiro 	}
197f4083490Sichiro }
198f4083490Sichiro 
199f4083490Sichiro static void
ipaqpcic_write(struct sapcic_socket * so,int reg,int arg)2000107b5e7Srjs ipaqpcic_write(struct sapcic_socket *so, int reg, int arg)
201f4083490Sichiro {
20260f2ec7eSichiro 	int s;
203f4083490Sichiro 	struct ipaqpcic_softc *sc = (struct ipaqpcic_softc *)so->sc;
204f4083490Sichiro 
205f4083490Sichiro 	s = splhigh();
206f4083490Sichiro 	switch (reg) {
207f4083490Sichiro 	case SAPCIC_CONTROL_RESET:
20860f2ec7eSichiro 		sc->sc_parent->ipaq_egpio |= EGPIO_H3600_CARD_RESET;
209f4083490Sichiro 		break;
210f4083490Sichiro 	case SAPCIC_CONTROL_LINEENABLE:
211f4083490Sichiro 	case SAPCIC_CONTROL_WAITENABLE:
212f4083490Sichiro 	case SAPCIC_CONTROL_POWERSELECT:
213f4083490Sichiro 		break;
214f4083490Sichiro 
215f4083490Sichiro 	default:
216f4083490Sichiro 		splx(s);
217f4083490Sichiro 		panic("ipaqpcic_write: bogus register");
218f4083490Sichiro 	}
21960f2ec7eSichiro 	bus_space_write_2(sc->sc_pc.sc_iot, sc->sc_parent->sc_egpioh, 0,
22060f2ec7eSichiro 			  sc->sc_parent->ipaq_egpio);
221f4083490Sichiro 	splx(s);
222f4083490Sichiro }
223f4083490Sichiro 
224f4083490Sichiro static void
ipaqpcic_set_power(struct sapcic_socket * so,int arg)2250107b5e7Srjs ipaqpcic_set_power(struct sapcic_socket *so, int arg)
226f4083490Sichiro {
22760f2ec7eSichiro 	int s;
22860f2ec7eSichiro 	struct ipaqpcic_softc *sc = (struct ipaqpcic_softc *)so->sc;
229f4083490Sichiro 
230f4083490Sichiro 	s = splbio();
231f4083490Sichiro 	switch (arg) {
232f4083490Sichiro 	case SAPCIC_POWER_OFF:
23360f2ec7eSichiro 		sc->sc_parent->ipaq_egpio &=
23460f2ec7eSichiro 			~(EGPIO_H3600_OPT_NVRAM_ON | EGPIO_H3600_OPT_ON);
235f4083490Sichiro 		break;
236f4083490Sichiro 	case SAPCIC_POWER_3V:
237f4083490Sichiro 	case SAPCIC_POWER_5V:
23860f2ec7eSichiro 		sc->sc_parent->ipaq_egpio |=
23960f2ec7eSichiro 			EGPIO_H3600_OPT_NVRAM_ON | EGPIO_H3600_OPT_ON;
240f4083490Sichiro 		break;
241f4083490Sichiro 	default:
2420f09ed48Sprovos 		panic("ipaqpcic_set_power: bogus arg");
243f4083490Sichiro 	}
24460f2ec7eSichiro 	bus_space_write_2(sc->sc_pc.sc_iot, sc->sc_parent->sc_egpioh,
24560f2ec7eSichiro 			  0, sc->sc_parent->ipaq_egpio);
246f4083490Sichiro 	splx(s);
247f4083490Sichiro }
248f4083490Sichiro 
249f4083490Sichiro static void
ipaqpcic_clear_intr(int arg)2500107b5e7Srjs ipaqpcic_clear_intr(int arg)
251f4083490Sichiro {
252f4083490Sichiro }
253f4083490Sichiro 
254f4083490Sichiro static void *
ipaqpcic_intr_establish(struct sapcic_socket * so,int level,int (* ih_fun)(void *),void * ih_arg)2550107b5e7Srjs ipaqpcic_intr_establish(struct sapcic_socket *so, int level,
2560107b5e7Srjs 			int (*ih_fun)(void *), void *ih_arg)
257f4083490Sichiro {
258f4083490Sichiro 	int irq;
259f4083490Sichiro 
260f4083490Sichiro 	irq = so->socket ? IRQ_IRQ0 : IRQ_IRQ1;
261124bde73Stoshii 	return (sa11x0_intr_establish((sa11x0_chipset_tag_t)so->pcictag_cookie,
262f4083490Sichiro 				    irq-16, 1, level, ih_fun, ih_arg));
263f4083490Sichiro }
264f4083490Sichiro 
265f4083490Sichiro static void
ipaqpcic_intr_disestablish(struct sapcic_socket * so,void * ih)2660107b5e7Srjs ipaqpcic_intr_disestablish(struct sapcic_socket *so, void *ih)
267f4083490Sichiro {
268124bde73Stoshii 	sa11x0_intr_disestablish((sa11x0_chipset_tag_t)so->pcictag_cookie, ih);
269f4083490Sichiro }
270