1 /* $NetBSD: eeprom.c,v 1.5 1995/03/10 02:06:54 gwr Exp $ */ 2 3 /* 4 * Copyright (c) 1994 Gordon W. Ross 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 copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 /* 31 * Access functions for the EEPROM (Electrically Eraseable PROM) 32 * The main reason for the existence of this module is to 33 * handle the painful task of updating the EEPROM contents. 34 * After a write, it must not be touched for 10 milliseconds. 35 * (See the Sun-3 Architecture Manual sec. 5.9) 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/device.h> 41 #include <sys/conf.h> 42 #include <sys/buf.h> 43 #include <sys/malloc.h> 44 45 #include <machine/autoconf.h> 46 #include <machine/obio.h> 47 #include <machine/eeprom.h> 48 49 #define HZ 100 /* XXX */ 50 51 int ee_console; /* for convenience of drivers */ 52 53 static int ee_update(caddr_t buf, int off, int cnt); 54 55 static char *eeprom_va; 56 static int ee_busy, ee_want; 57 58 int eeprom_match __P((struct device *, void *vcf, void *args)); 59 void eeprom_attach __P((struct device *, struct device *, void *)); 60 61 struct cfdriver eepromcd = { 62 NULL, "eeprom", eeprom_match, eeprom_attach, 63 DV_DULL, sizeof(struct device), 0 }; 64 65 /* Called very early by internal_configure. */ 66 void eeprom_init() 67 { 68 eeprom_va = obio_find_mapping(OBIO_EEPROM, OBIO_EEPROM_SIZE); 69 ee_console = ((struct eeprom *)eeprom_va)->eeConsole; 70 } 71 72 int eeprom_match(parent, vcf, args) 73 struct device *parent; 74 void *vcf, *args; 75 { 76 struct cfdata *cf = vcf; 77 struct confargs *ca = args; 78 79 /* This driver only supports one unit. */ 80 if (cf->cf_unit != 0) 81 return (0); 82 if (eeprom_va == NULL) 83 return (0); 84 if (ca->ca_paddr == -1) 85 ca->ca_paddr = OBIO_EEPROM; 86 return (1); 87 } 88 89 void eeprom_attach(parent, self, args) 90 struct device *parent; 91 struct device *self; 92 void *args; 93 { 94 struct confargs *ca = args; 95 96 printf("\n"); 97 } 98 99 100 static int ee_take() /* Take the lock. */ 101 { 102 int error = 0; 103 while (ee_busy) { 104 ee_want = 1; 105 error = tsleep(&ee_busy, PZERO | PCATCH, "eeprom", 0); 106 ee_want = 0; 107 if (error) /* interrupted */ 108 goto out; 109 } 110 ee_busy = 1; 111 out: 112 return error; 113 } 114 115 static void ee_give() /* Give the lock. */ 116 { 117 ee_busy = 0; 118 if (ee_want) { 119 ee_want = 0; 120 wakeup(&ee_busy); 121 } 122 } 123 124 int eeprom_uio(struct uio *uio) 125 { 126 int error; 127 int off; /* NOT off_t */ 128 u_int cnt; 129 caddr_t va; 130 caddr_t buf = (caddr_t)0; 131 132 off = uio->uio_offset; 133 if (off >= OBIO_EEPROM_SIZE) 134 return (EFAULT); 135 136 cnt = uio->uio_resid; 137 if (cnt > (OBIO_EEPROM_SIZE - off)) 138 cnt = (OBIO_EEPROM_SIZE - off); 139 140 if ((error = ee_take()) != 0) 141 return (error); 142 143 if (eeprom_va == NULL) { 144 error = ENXIO; 145 goto out; 146 } 147 148 va = eeprom_va; 149 if (uio->uio_rw != UIO_READ) { 150 /* Write requires a temporary buffer. */ 151 buf = malloc(OBIO_EEPROM_SIZE, M_DEVBUF, M_WAITOK); 152 if (!buf) { 153 error = EAGAIN; 154 goto out; 155 } 156 va = buf; 157 } 158 159 if ((error = uiomove(va + off, (int)cnt, uio)) != 0) 160 goto out; 161 162 if (uio->uio_rw != UIO_READ) 163 error = ee_update(buf, off, cnt); 164 165 out: 166 if (buf) 167 free(buf, M_DEVBUF); 168 ee_give(); 169 return (error); 170 } 171 172 /* 173 * Update the EEPROM from the passed buf. 174 */ 175 static int ee_update(char *buf, int off, int cnt) 176 { 177 volatile char *ep; 178 char *bp; 179 180 if (eeprom_va == NULL) 181 return (ENXIO); 182 183 ep = eeprom_va + off; 184 bp = buf + off; 185 186 while (cnt > 0) { 187 /* 188 * DO NOT WRITE IT UNLESS WE HAVE TO because the 189 * EEPROM has a limited number of write cycles. 190 * After some number of writes it just fails! 191 */ 192 if (*ep != *bp) { 193 *ep = *bp; 194 /* 195 * We have written the EEPROM, so now we must 196 * sleep for at least 10 milliseconds while 197 * holding the lock to prevent all access to 198 * the EEPROM while it recovers. 199 */ 200 (void)tsleep(eeprom_va, PZERO-1, "eeprom", HZ/50); 201 } 202 /* Make sure the write worked. */ 203 if (*ep != *bp) 204 return (EIO); 205 ep++; 206 bp++; 207 cnt--; 208 } 209 } 210 211 /* 212 * Read a byte out of the EEPROM. This is called from 213 * things like the zs driver very early to find out 214 * which device should be used as the console. 215 */ 216 int ee_get_byte(int off, int canwait) 217 { 218 int c = -1; 219 if ((off < 0) || (off >= OBIO_EEPROM_SIZE)) 220 goto out; 221 if (eeprom_va == NULL) 222 goto out; 223 224 if (canwait) { 225 if (ee_take()) 226 goto out; 227 } else { 228 if (ee_busy) 229 goto out; 230 } 231 232 c = eeprom_va[off] & 0xFF; 233 234 if (canwait) 235 ee_give(); 236 out: 237 return c; 238 } 239