1 /* $NetBSD: gpio_opb.c,v 1.2 2005/08/26 13:19:37 drochner Exp $ */ 2 3 /* 4 * Copyright (c) 2004 Shigeyuki Fukushima. 5 * All rights reserved. 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 * 3. The name of the author may not be used to endorse or promote 17 * products derived from this software without specific prior 18 * written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 21 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 26 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "locators.h" 34 35 #include <sys/param.h> 36 #include <sys/device.h> 37 #include <sys/systm.h> 38 39 #include <machine/pio.h> 40 41 #include <powerpc/ibm4xx/dcr405gp.h> 42 #include <powerpc/ibm4xx/dev/opbvar.h> 43 #include <powerpc/ibm4xx/dev/gpioreg.h> 44 #include <powerpc/ibm4xx/dev/gpiovar.h> 45 46 struct gpio_softc { 47 struct device sc_dev; /* device generic */ 48 struct gpio_controller sc_gpio; /* GPIO controller */ 49 u_long sc_addr; /* GPIO controller address */ 50 }; 51 52 static int gpio_print(void *, const char *); 53 static int gpio_search(struct device *, struct cfdata *, 54 const int *ldesc, void *aux); 55 static int gpio_match(struct device *, struct cfdata *, void *); 56 static void gpio_attach(struct device *, struct device *, void *); 57 58 static int gpio_or_read(void *, int); 59 static int gpio_tcr_read(void *, int); 60 static int gpio_odr_read(void *, int); 61 static int gpio_ir_read(void *, int); 62 static void gpio_or_write(void *arg, int addr, int bit); 63 static void gpio_tcr_write(void *arg, int addr, int bit); 64 static void gpio_odr_write(void *arg, int addr, int bit); 65 66 static int gpio_read_bit(void *, int, int); 67 static void gpio_write_bit(void *, int, int, int); 68 static uint32_t gpio_read(void *, int); 69 static void gpio_write(void *, int, uint32_t); 70 71 CFATTACH_DECL(gpio, sizeof(struct gpio_softc), 72 gpio_match, gpio_attach, NULL, NULL); 73 74 static int 75 gpio_print(void *aux, const char *pnp) 76 { 77 struct gpio_attach_args *gaa = aux; 78 79 aprint_normal(" addr GPIO#%d", gaa->ga_addr); 80 81 return (UNCONF); 82 } 83 84 static int 85 gpio_search(struct device *parent, struct cfdata *cf, 86 const int *ldesc, void *aux) 87 { 88 struct gpio_softc *sc = (void *)parent; 89 struct gpio_attach_args gaa; 90 91 gaa.ga_tag = &sc->sc_gpio; 92 gaa.ga_addr = cf->cf_loc[GPIOCF_ADDR]; 93 94 if (config_match(parent, cf, &gaa) > 0) 95 config_attach(parent, cf, &gaa, gpio_print); 96 97 return (0); 98 } 99 100 static int 101 gpio_match(struct device *parent, struct cfdata *cf, void *args) 102 { 103 struct opb_attach_args *oaa = args; 104 105 if (strcmp(oaa->opb_name, cf->cf_name) != 0) 106 return (0); 107 108 return (1); 109 } 110 111 static void 112 gpio_attach(struct device *parent, struct device *self, void *aux) 113 { 114 struct gpio_softc *sc = (struct gpio_softc *)self; 115 struct opb_attach_args *oaa = aux; 116 117 aprint_naive(": GPIO controller\n"); 118 aprint_normal(": On-Chip GPIO controller\n"); 119 120 sc->sc_addr = oaa->opb_addr; 121 sc->sc_gpio.cookie = sc; 122 sc->sc_gpio.io_or_read = gpio_or_read; 123 sc->sc_gpio.io_tcr_read = gpio_tcr_read; 124 sc->sc_gpio.io_odr_read = gpio_odr_read; 125 sc->sc_gpio.io_ir_read = gpio_ir_read; 126 sc->sc_gpio.io_or_write = gpio_or_write; 127 sc->sc_gpio.io_tcr_write = gpio_tcr_write; 128 sc->sc_gpio.io_odr_write = gpio_odr_write; 129 130 (void) config_search_ia(gpio_search, self, "gpio", NULL); 131 } 132 133 static int 134 gpio_or_read(void *arg, int addr) 135 { 136 return (gpio_read_bit(arg, GPIO_OR, addr)); 137 } 138 139 static int 140 gpio_tcr_read(void *arg, int addr) 141 { 142 return (gpio_read_bit(arg, GPIO_TCR, addr)); 143 } 144 145 static int 146 gpio_odr_read(void *arg, int addr) 147 { 148 return (gpio_read_bit(arg, GPIO_ODR, addr)); 149 } 150 151 static int 152 gpio_ir_read(void *arg, int addr) 153 { 154 gpio_write_bit(arg, GPIO_ODR, addr, 0); 155 gpio_write_bit(arg, GPIO_TCR, addr, 0); 156 return (gpio_read_bit(arg, GPIO_ODR, addr)); 157 } 158 159 static void 160 gpio_or_write(void *arg, int addr, int bit) 161 { 162 gpio_write_bit(arg, GPIO_ODR, addr, 0); 163 gpio_write_bit(arg, GPIO_TCR, addr, 1); 164 gpio_write_bit(arg, GPIO_OR, addr, bit); 165 } 166 167 static void 168 gpio_tcr_write(void *arg, int addr, int bit) 169 { 170 gpio_write_bit(arg, GPIO_TCR, addr, bit); 171 } 172 173 static void 174 gpio_odr_write(void *arg, int addr, int bit) 175 { 176 gpio_write_bit(arg, GPIO_ODR, addr, bit); 177 } 178 179 static int 180 gpio_read_bit(void *arg, int offset, int addr) 181 { 182 uint32_t rv = gpio_read(arg, offset); 183 uint32_t mask = GPIO_SBIT(addr); 184 185 return ((rv & mask) >> GPIO_SHIFT(addr)); 186 } 187 188 void 189 gpio_write_bit(void *arg, int offset, int addr, int bit) 190 { 191 uint32_t rv = gpio_read(arg, offset); 192 uint32_t mask = GPIO_SBIT(addr); 193 194 rv = rv & ~mask; 195 rv = rv | ((bit << GPIO_SHIFT(addr)) & mask); 196 gpio_write(arg, offset, rv); 197 } 198 199 static uint32_t 200 gpio_read(void *arg, int offset) 201 { 202 struct gpio_softc *sc = arg; 203 uint32_t rv; 204 205 rv = inl(sc->sc_addr + offset); 206 207 return rv; 208 } 209 210 static void 211 gpio_write(void *arg, int offset, uint32_t out) 212 { 213 struct gpio_softc *sc = arg; 214 215 outl((sc->sc_addr + offset), out); 216 } 217