1/* $NetBSD: g42xxeb_mci.c,v 1.2 2010/06/26 07:51:45 bsh Exp $ */ 2 3/*- 4 * Copyright (c) 2009 Genetec Corporation. All rights reserved. 5 * Written by Hiroyuki Bessho for Genetec Corporation. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following 14 * disclaimer in the documentation and/or other materials provided 15 * with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' 18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 27 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31/* derived from zaurus/dev/zmci.c */ 32 33/*- 34 * Copyright (C) 2006-2008 NONAKA Kimihiro <nonaka@netbsd.org> 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 51 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 52 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 */ 57 58#include <sys/cdefs.h> 59__KERNEL_RCSID(0, "$NetBSD: g42xxeb_mci.c,v 1.2 2010/06/26 07:51:45 bsh Exp $"); 60 61#include <sys/param.h> 62#include <sys/device.h> 63#include <sys/systm.h> 64#include <sys/bus.h> 65#include <sys/pmf.h> 66 67#include <machine/intr.h> 68 69#include <arm/xscale/pxa2x0cpu.h> 70#include <arm/xscale/pxa2x0reg.h> 71#include <arm/xscale/pxa2x0var.h> 72#include <arm/xscale/pxa2x0_gpio.h> 73#include <arm/xscale/pxa2x0_mci.h> 74 75#include <dev/sdmmc/sdmmcreg.h> 76 77#include <arm/xscale/pxa2x0var.h> 78#include <evbarm/g42xxeb/g42xxeb_var.h> 79 80struct g42xxeb_mci_softc { 81 struct pxamci_softc sc_mci; 82 83 bus_space_tag_t sc_obio_iot; 84 bus_space_handle_t sc_obio_ioh; 85 86 void *sc_detect_ih; 87}; 88 89static int pxamci_match(device_t, cfdata_t, void *); 90static void pxamci_attach(device_t, device_t, void *); 91 92CFATTACH_DECL_NEW(pxamci_obio, sizeof(struct g42xxeb_mci_softc), 93 pxamci_match, pxamci_attach, NULL, NULL); 94 95static int g42xxeb_mci_intr(void *arg); 96 97static uint32_t g42xxeb_mci_get_ocr(void *); 98static int g42xxeb_mci_set_power(void *, uint32_t); 99static int g42xxeb_mci_card_detect(void *); 100static int g42xxeb_mci_write_protect(void *); 101 102static int 103pxamci_match(device_t parent, cfdata_t cf, void *aux) 104{ 105 106 if (strcmp(cf->cf_name, "pxamci") == 0) 107 return 1; 108 return 0; 109} 110 111struct pxa2x0_gpioconf g42xxeb_pxamci_gpioconf[] = { 112 { 6, GPIO_CLR | GPIO_ALT_FN_1_OUT }, /* MMCCLK */ 113 { 8, GPIO_CLR | GPIO_ALT_FN_1_OUT }, /* MMCCS0 */ 114 { 9, GPIO_CLR | GPIO_ALT_FN_1_OUT }, /* MMCCS1 */ 115 { -1 } 116}; 117 118 119static void 120pxamci_attach(device_t parent, device_t self, void *aux) 121{ 122 struct g42xxeb_mci_softc *sc = device_private(self); 123 struct obio_attach_args *oba = aux; 124 struct obio_softc *osc = device_private(parent); 125 struct pxaip_attach_args pxa; 126 struct pxa2x0_gpioconf *gpioconf[] = { 127 g42xxeb_pxamci_gpioconf, 128 NULL 129 }; 130 131 bus_space_tag_t iot = oba->oba_iot; 132 133 sc->sc_mci.sc_dev = self; 134 135 pxa2x0_gpio_config(gpioconf); 136 137 /* Establish card detect interrupt */ 138 sc->sc_detect_ih = obio_intr_establish(osc, G42XXEB_INT_MMCSD, 139 IPL_BIO, IST_EDGE_BOTH, g42xxeb_mci_intr, sc); 140 if (sc->sc_detect_ih == NULL) { 141 aprint_error_dev(self, 142 "unable to establish SD detect interrupt\n"); 143 return; 144 } 145 146 sc->sc_mci.sc_tag.cookie = sc; 147 sc->sc_mci.sc_tag.get_ocr = g42xxeb_mci_get_ocr; 148 sc->sc_mci.sc_tag.set_power = g42xxeb_mci_set_power; 149 sc->sc_mci.sc_tag.card_detect = g42xxeb_mci_card_detect; 150 sc->sc_mci.sc_tag.write_protect = g42xxeb_mci_write_protect; 151 sc->sc_mci.sc_caps = 0; 152 153 pxa.pxa_iot = iot; /* actually, here we want I/O tag for 154 pxaip, not for obio. */ 155 156#if 0 157 /* pxamci_attach_sub() ignores following values and uses 158 * constants. */ 159 pxa.pxa_addr = PXA2X0_MMC_BASE; 160 pxa.pxa_size = PXA2X0_MMC_SIZE; 161 pxa.pxa_intr = PXA2X0_INT_MMC; 162#endif 163 164 /* disable DMA for sdmmc for now. */ 165 SET(sc->sc_mci.sc_caps, PMC_CAPS_NO_DMA); 166 167 if (pxamci_attach_sub(self, &pxa)) { 168 aprint_error_dev(self, 169 "unable to attach MMC controller\n"); 170 goto free_intr; 171 } 172 173 if (!pmf_device_register(self, NULL, NULL)) { 174 aprint_error_dev(self, 175 "couldn't establish power handler\n"); 176 } 177 178 sc->sc_obio_iot = iot; 179 sc->sc_obio_ioh = osc->sc_obioreg_ioh; 180 181 return; 182 183free_intr: 184 obio_intr_disestablish(osc, G42XXEB_INT_MMCSD, sc->sc_detect_ih); 185 sc->sc_detect_ih = NULL; 186} 187 188static int 189g42xxeb_mci_intr(void *arg) 190{ 191 struct g42xxeb_mci_softc *sc = (struct g42xxeb_mci_softc *)arg; 192 193 pxamci_card_detect_event(&sc->sc_mci); 194 195 return 1; 196} 197 198static uint32_t 199g42xxeb_mci_get_ocr(void *arg) 200{ 201 202 return MMC_OCR_3_2V_3_3V; 203} 204 205static int 206g42xxeb_mci_set_power(void *arg, uint32_t ocr) 207{ 208 /* nothing to do */ 209 return 0; 210} 211 212/* 213 * Return non-zero if the card is currently inserted. 214 */ 215static int 216g42xxeb_mci_card_detect(void *arg) 217{ 218 struct g42xxeb_mci_softc *sc = (struct g42xxeb_mci_softc *)arg; 219 uint16_t reg; 220 221 reg = bus_space_read_2(sc->sc_obio_iot, sc->sc_obio_ioh, 222 G42XXEB_INTSTS2); 223 224 return !(reg & (1<<G42XXEB_INT_MMCSD)); 225} 226 227/* 228 * Return non-zero if the card is currently write-protected. 229 */ 230static int 231g42xxeb_mci_write_protect(void *arg) 232{ 233 struct g42xxeb_mci_softc *sc = (struct g42xxeb_mci_softc *)arg; 234 uint16_t reg; 235 236 reg = bus_space_read_2(sc->sc_obio_iot, sc->sc_obio_ioh, 237 G42XXEB_WP); 238 239 return reg & 1; 240} 241