1 /* $NetBSD: sa11x1_pcic.c,v 1.25 2022/09/27 06:36:43 skrll Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by IWAMOTO Toshihiro. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: sa11x1_pcic.c,v 1.25 2022/09/27 06:36:43 skrll Exp $"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/types.h> 38 #include <sys/conf.h> 39 #include <sys/file.h> 40 #include <sys/device.h> 41 #include <sys/kernel.h> 42 #include <sys/kthread.h> 43 44 #include <sys/bus.h> 45 46 #include <dev/pcmcia/pcmciachip.h> 47 #include <dev/pcmcia/pcmciavar.h> 48 #include <arm/sa11x0/sa11x0_reg.h> 49 #include <arm/sa11x0/sa11x0_var.h> 50 #include <arm/sa11x0/sa1111_reg.h> 51 #include <arm/sa11x0/sa1111_var.h> 52 #include <arm/sa11x0/sa11x1_pcicreg.h> 53 #include <arm/sa11x0/sa11xx_pcicvar.h> 54 #include <arm/sa11x0/sa11x1_pcicvar.h> 55 56 #include "sacpcic.h" 57 58 static int sacpcic_print(void *, const char *); 59 60 static void 61 sacpcic_config_deferred(device_t dev) 62 { 63 struct sacpcic_softc *sc = device_private(dev); 64 struct sapcic_socket *so; 65 int i; 66 67 for (i = 0; i < 2; i++) { 68 so = &sc->sc_socket[i]; 69 sapcic_kthread_create(so); 70 71 sacc_intr_establish((sacc_chipset_tag_t)so->pcictag_cookie, 72 i ? IRQ_S1_CDVALID : IRQ_S0_CDVALID, 73 IST_EDGE_RAISE, IPL_BIO, sapcic_intr, so); 74 } 75 } 76 77 void 78 sacpcic_attach_common(struct sacc_softc *psc, struct sacpcic_softc *sc, 79 void *aux, void (* socket_setup_hook)(struct sapcic_socket *)) 80 { 81 int i; 82 struct pcmciabus_attach_args paa; 83 84 aprint_normal("\n"); 85 86 sc->sc_pc.sc_iot = psc->sc_iot; 87 sc->sc_ioh = psc->sc_ioh; 88 89 mutex_init(&sc->sc_pc.sc_lock, MUTEX_DEFAULT, IPL_NONE); 90 91 for (i = 0; i < 2; i++) { 92 sc->sc_socket[i].sc = (struct sapcic_softc *)sc; 93 sc->sc_socket[i].socket = i; 94 sc->sc_socket[i].pcictag_cookie = psc; 95 sc->sc_socket[i].pcictag = NULL; 96 sc->sc_socket[i].event_thread = NULL; 97 sc->sc_socket[i].event = 0; 98 sc->sc_socket[i].laststatus = SAPCIC_CARD_INVALID; 99 sc->sc_socket[i].shutdown = 0; 100 101 socket_setup_hook(&sc->sc_socket[i]); 102 103 paa.paa_busname = "pcmcia"; 104 paa.pct = (pcmcia_chipset_tag_t)&sa11x0_pcmcia_functions; 105 paa.pch = (pcmcia_chipset_handle_t)&sc->sc_socket[i]; 106 107 sc->sc_socket[i].pcmcia = 108 config_found(sc->sc_pc.sc_dev, &paa, sacpcic_print, 109 CFARGS_NONE); 110 } 111 112 config_interrupts(sc->sc_pc.sc_dev, sacpcic_config_deferred); 113 } 114 115 int 116 sacpcic_print(void *aux, const char *name) 117 { 118 119 return UNCONF; 120 } 121 122 int 123 sacpcic_read(struct sapcic_socket *so, int reg) 124 { 125 int cr, bit; 126 struct sacpcic_softc *sc = (struct sacpcic_softc *)so->sc; 127 128 cr = bus_space_read_4(sc->sc_pc.sc_iot, sc->sc_ioh, SACPCIC_SR); 129 130 switch (reg) { 131 case SAPCIC_STATUS_CARD: 132 bit = (so->socket ? SR_S1_CARDDETECT : SR_S0_CARDDETECT) & cr; 133 if (bit) 134 return SAPCIC_CARD_INVALID; 135 else 136 return SAPCIC_CARD_VALID; 137 138 case SAPCIC_STATUS_VS1: 139 bit = (so->socket ? SR_S1_VS1 : SR_S0_VS1); 140 return (bit & cr); 141 142 case SAPCIC_STATUS_VS2: 143 bit = (so->socket ? SR_S1_VS2 : SR_S0_VS2); 144 return (bit & cr); 145 146 case SAPCIC_STATUS_READY: 147 bit = (so->socket ? SR_S1_READY : SR_S0_READY); 148 return (bit & cr); 149 150 default: 151 panic("sacpcic_read: bogus register"); 152 } 153 } 154 155 void 156 sacpcic_write(struct sapcic_socket *so, int reg, int arg) 157 { 158 int s, oldvalue, newvalue, mask; 159 struct sacpcic_softc *sc = (struct sacpcic_softc *)so->sc; 160 161 s = splhigh(); 162 oldvalue = bus_space_read_4(sc->sc_pc.sc_iot, sc->sc_ioh, SACPCIC_CR); 163 164 switch (reg) { 165 case SAPCIC_CONTROL_RESET: 166 mask = so->socket ? CR_S1_RST : CR_S0_RST; 167 168 newvalue = (oldvalue & ~mask) | (arg ? mask : 0); 169 break; 170 171 case SAPCIC_CONTROL_LINEENABLE: 172 mask = so->socket ? CR_S1_FLT : CR_S0_FLT; 173 174 newvalue = (oldvalue & ~mask) | (arg ? mask : 0); 175 break; 176 177 case SAPCIC_CONTROL_WAITENABLE: 178 mask = so->socket ? CR_S1_PWAITEN : CR_S0_PWAITEN; 179 180 newvalue = (oldvalue & ~mask) | (arg ? mask : 0); 181 break; 182 183 case SAPCIC_CONTROL_POWERSELECT: 184 mask = so->socket ? CR_S1_PSE : CR_S0_PSE; 185 newvalue = oldvalue & ~mask; 186 187 switch (arg) { 188 case SAPCIC_POWER_3V: 189 break; 190 case SAPCIC_POWER_5V: 191 newvalue |= mask; 192 break; 193 default: 194 splx(s); 195 panic("sacpcic_write: bogus arg"); 196 } 197 break; 198 199 default: 200 splx(s); 201 panic("sacpcic_write: bogus register"); 202 } 203 bus_space_write_4(sc->sc_pc.sc_iot, sc->sc_ioh, SACPCIC_CR, newvalue); 204 splx(s); 205 } 206 207 void 208 sacpcic_clear_intr(int arg) 209 { 210 /* sacc_intr_dispatch takes care of intr status */ 211 } 212 213 void * 214 sacpcic_intr_establish(struct sapcic_socket *so, int level, 215 int (*ih_fun)(void *), void *ih_arg) 216 { 217 int irq; 218 219 irq = so->socket ? IRQ_S1_READY : IRQ_S0_READY; 220 return sacc_intr_establish((sacc_chipset_tag_t)so->pcictag_cookie, irq, 221 IST_EDGE_FALL, level, ih_fun, ih_arg); 222 } 223 224 void 225 sacpcic_intr_disestablish(struct sapcic_socket *so, void *ih) 226 { 227 sacc_intr_disestablish((sacc_chipset_tag_t)so->pcictag_cookie, ih); 228 } 229