1/* $NetBSD$ */ 2/* 3 * Copyright (c) 2011 KIYOHARA Takashi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include <sys/param.h> 29#include <sys/bus.h> 30#include <sys/device.h> 31#include <sys/errno.h> 32 33#include <machine/platid.h> 34#include <machine/platid_mask.h> 35 36#include <arm/xscale/pxa2x0var.h> 37#include <arm/xscale/pxa2x0_gpio.h> 38#include <arm/xscale/pxa2x0_pcic.h> 39 40#include <dev/pcmcia/pcmciareg.h> 41#include <dev/pcmcia/pcmciavar.h> 42#include <dev/pcmcia/pcmciachip.h> 43 44 45#define HAVE_CARD(r) (!((r) & GPIO_SET)) 46 47 48static int nbppcic_match(device_t, cfdata_t, void *); 49static void nbppcic_attach(device_t, device_t, void *); 50 51static u_int nbppcic_read(struct pxapcic_socket *, int); 52static void nbppcic_write(struct pxapcic_socket *, int, u_int); 53static void nbppcic_set_power(struct pxapcic_socket *, int); 54static void nbppcic_clear_intr(struct pxapcic_socket *); 55static void *nbppcic_intr_establish(struct pxapcic_socket *, int, 56 int (*)(void *), void *); 57static void nbppcic_intr_disestablish(struct pxapcic_socket *, void *); 58 59static void nbppcic_socket_setup(struct pxapcic_socket *); 60 61CFATTACH_DECL_NEW(nbppcic, sizeof(struct pxapcic_softc), 62 nbppcic_match, nbppcic_attach, NULL, NULL); 63 64static struct pxapcic_tag nbppcic_functions = { 65 nbppcic_read, 66 nbppcic_write, 67 nbppcic_set_power, 68 nbppcic_clear_intr, 69 nbppcic_intr_establish, 70 nbppcic_intr_disestablish, 71}; 72 73 74static int 75nbppcic_match(device_t parent, cfdata_t match, void *aux) 76{ 77 struct pxaip_attach_args *pxa = aux; 78 79 if (strcmp(pxa->pxa_name, match->cf_name) != 0 || 80 !platid_match(&platid, &platid_mask_MACH_PSIONTEKLOGIX_NETBOOK_PRO)) 81 return 0; 82 83 return 1; 84} 85 86static void 87nbppcic_attach(device_t parent, device_t self, void *aux) 88{ 89 struct pxapcic_softc *sc = device_private(self); 90 struct pxaip_attach_args *pxa = aux; 91 92 sc->sc_dev = self; 93 sc->sc_iot = pxa->pxa_iot; 94 95 sc->sc_nslots = 2; 96 sc->sc_irqpin[0] = 71; /* GPIO 71: PRDY1/~IRQ1 */ 97 sc->sc_irqcfpin[0] = 73; /* GPIO 73: PCD1 */ 98 sc->sc_irqpin[1] = 77; /* GPIO 77: PRDY2/~IRQ2 */ 99 sc->sc_irqcfpin[1] = 75; /* GPIO 75: PCD2 */ 100 101 pxapcic_attach_common(sc, &nbppcic_socket_setup); 102} 103 104static u_int 105nbppcic_read(struct pxapcic_socket *so, int which) 106{ 107 struct pxapcic_softc *sc = so->sc; 108 int reg; 109 110 switch (which) { 111 case PXAPCIC_CARD_STATUS: 112 reg = pxa2x0_gpio_get_function(sc->sc_irqcfpin[so->socket]); 113 return (HAVE_CARD(reg) ? 114 PXAPCIC_CARD_VALID : PXAPCIC_CARD_INVALID); 115 116 case PXAPCIC_CARD_READY: 117 reg = pxa2x0_gpio_get_function(sc->sc_irqpin[so->socket]); 118 return (reg & GPIO_SET) ? 1 : 0; 119 120 default: 121 panic("%s: bogus register", __func__); 122 } 123 /* NOTREACHED */ 124} 125 126static void 127nbppcic_write(struct pxapcic_socket *so, int which, u_int arg) 128{ 129 130 switch (which) { 131 case PXAPCIC_CARD_POWER: 132 /* To Be Done: ;-) */ 133 break; 134 135 case PXAPCIC_CARD_RESET: 136 { 137 int reset_pin[2] = { 70, 74 }; /* GPIO 70, GPIO 74 */ 138 139 pxa2x0_gpio_set_function(reset_pin[so->socket], 140 GPIO_OUT | (arg ? GPIO_CLR : GPIO_SET)); 141 break; 142 } 143 144 default: 145 panic("%s: bogus register", __func__); 146 } 147 /* NOTREACHED */ 148} 149 150/* ARGSUSED */ 151static void 152nbppcic_set_power(struct pxapcic_socket *so, int arg) 153{ 154 155 if(arg != PXAPCIC_POWER_OFF && arg != PXAPCIC_POWER_3V) 156 panic("%s: bogus arg\n", __func__); 157} 158 159/* ARGSUSED */ 160static void 161nbppcic_clear_intr(struct pxapcic_socket *so) 162{ 163 164 /* nothing to do */ 165} 166 167static void * 168nbppcic_intr_establish(struct pxapcic_socket *so, int level, 169 int (* ih_fun)(void *), void *ih_arg) 170{ 171 172 return pxa2x0_gpio_intr_establish(so->irqpin, IST_EDGE_FALLING, 173 level, ih_fun, ih_arg); 174} 175 176/* ARGSUSED */ 177static void 178nbppcic_intr_disestablish(struct pxapcic_socket *so, void *ih) 179{ 180 181 pxa2x0_gpio_intr_disestablish(ih); 182} 183 184 185static void 186nbppcic_socket_setup(struct pxapcic_socket *so) 187{ 188 189 so->power_capability = PXAPCIC_POWER_3V; 190 so->pcictag_cookie = NULL; 191 so->pcictag = &nbppcic_functions; 192} 193