aic7xxx_93cx6.c revision 50477
138465Smsmith/* 238465Smsmith * Interface for the 93C66/56/46/26/06 serial eeprom parts. 3139738Simp * 438465Smsmith * Copyright (c) 1995, 1996 Daniel M. Eischen 538465Smsmith * All rights reserved. 638465Smsmith * 738465Smsmith * Redistribution and use in source and binary forms, with or without 838465Smsmith * modification, are permitted provided that the following conditions 938465Smsmith * are met: 1038465Smsmith * 1. Redistributions of source code must retain the above copyright 1138465Smsmith * notice immediately at the beginning of the file, without modification, 1238465Smsmith * this list of conditions, and the following disclaimer. 1338465Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1438465Smsmith * notice, this list of conditions and the following disclaimer in the 1538465Smsmith * documentation and/or other materials provided with the distribution. 1638465Smsmith * 3. Absolutely no warranty of function or purpose is made by the author 1738465Smsmith * Daniel M. Eischen. 1838465Smsmith * 4. Modifications may be freely made to this file if the above conditions 1938465Smsmith * are met. 2038465Smsmith * 2138465Smsmith * $FreeBSD: head/sys/dev/aic7xxx/aic7xxx_93cx6.c 50477 1999-08-28 01:08:13Z peter $ 2238465Smsmith */ 2338465Smsmith 2438465Smsmith/* 2538465Smsmith * The instruction set of the 93C66/56/46/26/06 chips are as follows: 2638465Smsmith * 2738465Smsmith * Start OP * 2838465Smsmith * Function Bit Code Address** Data Description 29124140Sobrien * ------------------------------------------------------------------- 30124140Sobrien * READ 1 10 A5 - A0 Reads data stored in memory, 31124140Sobrien * starting at specified address 3238465Smsmith * EWEN 1 00 11XXXX Write enable must preceed 3338465Smsmith * all programming modes 3438465Smsmith * ERASE 1 11 A5 - A0 Erase register A5A4A3A2A1A0 3567227Sobrien * WRITE 1 01 A5 - A0 D15 - D0 Writes register 3638465Smsmith * ERAL 1 00 10XXXX Erase all registers 3767227Sobrien * WRAL 1 00 01XXXX D15 - D0 Writes to all registers 3867227Sobrien * EWDS 1 00 00XXXX Disables all programming 3967227Sobrien * instructions 4067227Sobrien * *Note: A value of X for address is a don't care condition. 4167227Sobrien * **Note: There are 8 address bits for the 93C56/66 chips unlike 4238465Smsmith * the 93C46/26/06 chips which have 6 address bits. 4367227Sobrien * 4467227Sobrien * The 93C46 has a four wire interface: clock, chip select, data in, and 4567227Sobrien * data out. In order to perform one of the above functions, you need 4667227Sobrien * to enable the chip select for a clock period (typically a minimum of 4767227Sobrien * 1 usec, with the clock high and low a minimum of 750 and 250 nsec 48133862Smarius * respectively). While the chip select remains high, you can clock in 4967227Sobrien * the instructions (above) starting with the start bit, followed by the 5067227Sobrien * OP code, Address, and Data (if needed). For the READ instruction, the 5167227Sobrien * requested 16-bit register contents is read from the data out line but 5267227Sobrien * is preceded by an initial zero (leading 0, followed by 16-bits, MSB 5367227Sobrien * first). The clock cycling from low to high initiates the next data 5467227Sobrien * bit to be sent from the chip. 5538465Smsmith * 5638465Smsmith */ 5767227Sobrien 5867227Sobrien#include "opt_aic7xxx.h" 5938465Smsmith 6038465Smsmith#include <sys/param.h> 6167227Sobrien#include <sys/systm.h> 6267227Sobrien#include <machine/bus_memio.h> 6367227Sobrien#include <machine/bus_pio.h> 6438465Smsmith#include <machine/bus.h> 6538465Smsmith#include <dev/aic7xxx/93cx6.h> 6638465Smsmith 6767227Sobrien/* 6838465Smsmith * Right now, we only have to read the SEEPROM. But we make it easier to 6967227Sobrien * add other 93Cx6 functions. 7038465Smsmith */ 7138465Smsmithstatic struct seeprom_cmd { 7238465Smsmith unsigned char len; 7367227Sobrien unsigned char bits[3]; 7438465Smsmith} seeprom_read = {3, {1, 1, 0}}; 7567227Sobrien 7638465Smsmith/* 7767227Sobrien * Wait for the SEERDY to go high; about 800 ns. 7867227Sobrien */ 7967227Sobrien#define CLOCK_PULSE(sd, rdy) \ 8067227Sobrien while ((SEEPROM_STATUS_INB(sd) & rdy) == 0) { \ 8167227Sobrien ; /* Do nothing */ \ 8267227Sobrien } \ 8367227Sobrien (void)SEEPROM_INB(sd); /* Clear clock */ 8438465Smsmith 8538465Smsmith/* 8638465Smsmith * Read the serial EEPROM and returns 1 if successful and 0 if 8738465Smsmith * not successful. 8838465Smsmith */ 8967227Sobrienint 9038465Smsmithread_seeprom(sd, buf, start_addr, count) 9167227Sobrien struct seeprom_descriptor *sd; 9267227Sobrien u_int16_t *buf; 9338465Smsmith bus_size_t start_addr; 9467227Sobrien bus_size_t count; 9567227Sobrien{ 9667227Sobrien int i = 0; 9767227Sobrien u_int k = 0; 9867227Sobrien u_int16_t v; 9938465Smsmith u_int8_t temp; 100176068Sgrehan 101176068Sgrehan /* 102176068Sgrehan * Read the requested registers of the seeprom. The loop 103176068Sgrehan * will range from 0 to count-1. 10438465Smsmith */ 10538465Smsmith for (k = start_addr; k < count + start_addr; k++) { 10638465Smsmith /* Send chip select for one clock cycle. */ 10767227Sobrien temp = sd->sd_MS ^ sd->sd_CS; 10838465Smsmith SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 10967227Sobrien CLOCK_PULSE(sd, sd->sd_RDY); 11038465Smsmith 11167227Sobrien /* 11267227Sobrien * Now we're ready to send the read command followed by the 11338465Smsmith * address of the 16-bit register we want to read. 11491113Sjake */ 11567227Sobrien for (i = 0; i < seeprom_read.len; i++) { 11667227Sobrien if (seeprom_read.bits[i] != 0) 11767227Sobrien temp ^= sd->sd_DO; 11838465Smsmith SEEPROM_OUTB(sd, temp); 11967227Sobrien CLOCK_PULSE(sd, sd->sd_RDY); 12038465Smsmith SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 121 CLOCK_PULSE(sd, sd->sd_RDY); 122 if (seeprom_read.bits[i] != 0) 123 temp ^= sd->sd_DO; 124 } 125 /* Send the 6 or 8 bit address (MSB first, LSB last). */ 126 for (i = (sd->sd_chip - 1); i >= 0; i--) { 127 if ((k & (1 << i)) != 0) 128 temp ^= sd->sd_DO; 129 SEEPROM_OUTB(sd, temp); 130 CLOCK_PULSE(sd, sd->sd_RDY); 131 SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 132 CLOCK_PULSE(sd, sd->sd_RDY); 133 if ((k & (1 << i)) != 0) 134 temp ^= sd->sd_DO; 135 } 136 137 /* 138 * Now read the 16 bit register. An initial 0 precedes the 139 * register contents which begins with bit 15 (MSB) and ends 140 * with bit 0 (LSB). The initial 0 will be shifted off the 141 * top of our word as we let the loop run from 0 to 16. 142 */ 143 v = 0; 144 for (i = 16; i >= 0; i--) { 145 SEEPROM_OUTB(sd, temp); 146 CLOCK_PULSE(sd, sd->sd_RDY); 147 v <<= 1; 148 if (SEEPROM_DATA_INB(sd) & sd->sd_DI) 149 v |= 1; 150 SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 151 CLOCK_PULSE(sd, sd->sd_RDY); 152 } 153 154 buf[k - start_addr] = v; 155 156 /* Reset the chip select for the next command cycle. */ 157 temp = sd->sd_MS; 158 SEEPROM_OUTB(sd, temp); 159 CLOCK_PULSE(sd, sd->sd_RDY); 160 SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 161 CLOCK_PULSE(sd, sd->sd_RDY); 162 SEEPROM_OUTB(sd, temp); 163 CLOCK_PULSE(sd, sd->sd_RDY); 164 } 165#ifdef AHC_DUMP_EEPROM 166 printf("\nSerial EEPROM:"); 167 for (k = 0; k < count; k = k + 1) { 168 if (((k % 8) == 0) && (k != 0)) { 169 printf ("\n "); 170 } 171 printf (" 0x%x", buf[k]); 172 } 173 printf ("\n"); 174#endif 175 return (1); 176} 177