aic7xxx_93cx6.c revision 72640
139220Sgibbs/* 239220Sgibbs * Interface for the 93C66/56/46/26/06 serial eeprom parts. 339220Sgibbs * 439220Sgibbs * Copyright (c) 1995, 1996 Daniel M. Eischen 539220Sgibbs * All rights reserved. 639220Sgibbs * 739220Sgibbs * Redistribution and use in source and binary forms, with or without 839220Sgibbs * modification, are permitted provided that the following conditions 939220Sgibbs * are met: 1039220Sgibbs * 1. Redistributions of source code must retain the above copyright 1165942Sgibbs * notice, this list of conditions, and the following disclaimer, 1265942Sgibbs * without modification. 1365942Sgibbs * 2. The name of the author may not be used to endorse or promote products 1465942Sgibbs * derived from this software without specific prior written permission. 1539220Sgibbs * 1665942Sgibbs * Alternatively, this software may be distributed under the terms of the 1765942Sgibbs * GNU Public License ("GPL"). 1865942Sgibbs * 1965942Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2065942Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2165942Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2265942Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2365942Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2465942Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2565942Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2665942Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2765942Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2865942Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2965942Sgibbs * SUCH DAMAGE. 3065942Sgibbs * 3170204Sgibbs * $Id: //depot/src/aic7xxx/aic7xxx_93cx6.c#5 $ 3265942Sgibbs * 3350477Speter * $FreeBSD: head/sys/dev/aic7xxx/aic7xxx_93cx6.c 72640 2001-02-18 10:25:42Z asmodai $ 3439220Sgibbs */ 3539220Sgibbs 3639220Sgibbs/* 3739220Sgibbs * The instruction set of the 93C66/56/46/26/06 chips are as follows: 3839220Sgibbs * 3939220Sgibbs * Start OP * 4039220Sgibbs * Function Bit Code Address** Data Description 4139220Sgibbs * ------------------------------------------------------------------- 4239220Sgibbs * READ 1 10 A5 - A0 Reads data stored in memory, 4339220Sgibbs * starting at specified address 4472640Sasmodai * EWEN 1 00 11XXXX Write enable must precede 4539220Sgibbs * all programming modes 4639220Sgibbs * ERASE 1 11 A5 - A0 Erase register A5A4A3A2A1A0 4739220Sgibbs * WRITE 1 01 A5 - A0 D15 - D0 Writes register 4839220Sgibbs * ERAL 1 00 10XXXX Erase all registers 4939220Sgibbs * WRAL 1 00 01XXXX D15 - D0 Writes to all registers 5039220Sgibbs * EWDS 1 00 00XXXX Disables all programming 5139220Sgibbs * instructions 5239220Sgibbs * *Note: A value of X for address is a don't care condition. 5339220Sgibbs * **Note: There are 8 address bits for the 93C56/66 chips unlike 5439220Sgibbs * the 93C46/26/06 chips which have 6 address bits. 5539220Sgibbs * 5639220Sgibbs * The 93C46 has a four wire interface: clock, chip select, data in, and 5739220Sgibbs * data out. In order to perform one of the above functions, you need 5839220Sgibbs * to enable the chip select for a clock period (typically a minimum of 5939220Sgibbs * 1 usec, with the clock high and low a minimum of 750 and 250 nsec 6039220Sgibbs * respectively). While the chip select remains high, you can clock in 6139220Sgibbs * the instructions (above) starting with the start bit, followed by the 6239220Sgibbs * OP code, Address, and Data (if needed). For the READ instruction, the 6339220Sgibbs * requested 16-bit register contents is read from the data out line but 6439220Sgibbs * is preceded by an initial zero (leading 0, followed by 16-bits, MSB 6539220Sgibbs * first). The clock cycling from low to high initiates the next data 6639220Sgibbs * bit to be sent from the chip. 6739220Sgibbs * 6839220Sgibbs */ 6939220Sgibbs 7065942Sgibbs#ifdef __linux__ 7165942Sgibbs#include "aic7xxx_linux.h" 7265942Sgibbs#include "aic7xxx_inline.h" 7365942Sgibbs#include "aic7xxx_93cx6.h" 7465942Sgibbs#endif 7547507Sgibbs 7665942Sgibbs#ifdef __FreeBSD__ 7765942Sgibbs#include <dev/aic7xxx/aic7xxx_freebsd.h> 7865942Sgibbs#include <dev/aic7xxx/aic7xxx_inline.h> 7965942Sgibbs#include <dev/aic7xxx/aic7xxx_93cx6.h> 8065942Sgibbs#endif 8139220Sgibbs 8239220Sgibbs/* 8339220Sgibbs * Right now, we only have to read the SEEPROM. But we make it easier to 8439220Sgibbs * add other 93Cx6 functions. 8539220Sgibbs */ 8639220Sgibbsstatic struct seeprom_cmd { 8765942Sgibbs uint8_t len; 8865942Sgibbs uint8_t bits[3]; 8939220Sgibbs} seeprom_read = {3, {1, 1, 0}}; 9039220Sgibbs 9139220Sgibbs/* 9239220Sgibbs * Wait for the SEERDY to go high; about 800 ns. 9339220Sgibbs */ 9439220Sgibbs#define CLOCK_PULSE(sd, rdy) \ 9539220Sgibbs while ((SEEPROM_STATUS_INB(sd) & rdy) == 0) { \ 9639220Sgibbs ; /* Do nothing */ \ 9739220Sgibbs } \ 9839220Sgibbs (void)SEEPROM_INB(sd); /* Clear clock */ 9939220Sgibbs 10039220Sgibbs/* 10139220Sgibbs * Read the serial EEPROM and returns 1 if successful and 0 if 10239220Sgibbs * not successful. 10339220Sgibbs */ 10439220Sgibbsint 10539220Sgibbsread_seeprom(sd, buf, start_addr, count) 10639220Sgibbs struct seeprom_descriptor *sd; 10763457Sgibbs uint16_t *buf; 10865942Sgibbs u_int start_addr; 10965942Sgibbs u_int count; 11039220Sgibbs{ 11139220Sgibbs int i = 0; 11239220Sgibbs u_int k = 0; 11363457Sgibbs uint16_t v; 11463457Sgibbs uint8_t temp; 11539220Sgibbs 11639220Sgibbs /* 11739220Sgibbs * Read the requested registers of the seeprom. The loop 11839220Sgibbs * will range from 0 to count-1. 11939220Sgibbs */ 12039220Sgibbs for (k = start_addr; k < count + start_addr; k++) { 12139220Sgibbs /* Send chip select for one clock cycle. */ 12239220Sgibbs temp = sd->sd_MS ^ sd->sd_CS; 12339220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 12439220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 12539220Sgibbs 12639220Sgibbs /* 12739220Sgibbs * Now we're ready to send the read command followed by the 12839220Sgibbs * address of the 16-bit register we want to read. 12939220Sgibbs */ 13039220Sgibbs for (i = 0; i < seeprom_read.len; i++) { 13139220Sgibbs if (seeprom_read.bits[i] != 0) 13239220Sgibbs temp ^= sd->sd_DO; 13339220Sgibbs SEEPROM_OUTB(sd, temp); 13439220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 13539220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 13639220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 13739220Sgibbs if (seeprom_read.bits[i] != 0) 13839220Sgibbs temp ^= sd->sd_DO; 13939220Sgibbs } 14039220Sgibbs /* Send the 6 or 8 bit address (MSB first, LSB last). */ 14139220Sgibbs for (i = (sd->sd_chip - 1); i >= 0; i--) { 14239220Sgibbs if ((k & (1 << i)) != 0) 14339220Sgibbs temp ^= sd->sd_DO; 14439220Sgibbs SEEPROM_OUTB(sd, temp); 14539220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 14639220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 14739220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 14839220Sgibbs if ((k & (1 << i)) != 0) 14939220Sgibbs temp ^= sd->sd_DO; 15039220Sgibbs } 15139220Sgibbs 15239220Sgibbs /* 15339220Sgibbs * Now read the 16 bit register. An initial 0 precedes the 15439220Sgibbs * register contents which begins with bit 15 (MSB) and ends 15539220Sgibbs * with bit 0 (LSB). The initial 0 will be shifted off the 15639220Sgibbs * top of our word as we let the loop run from 0 to 16. 15739220Sgibbs */ 15839220Sgibbs v = 0; 15939220Sgibbs for (i = 16; i >= 0; i--) { 16039220Sgibbs SEEPROM_OUTB(sd, temp); 16139220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 16239220Sgibbs v <<= 1; 16339220Sgibbs if (SEEPROM_DATA_INB(sd) & sd->sd_DI) 16439220Sgibbs v |= 1; 16539220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 16639220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 16739220Sgibbs } 16839220Sgibbs 16939220Sgibbs buf[k - start_addr] = v; 17039220Sgibbs 17139220Sgibbs /* Reset the chip select for the next command cycle. */ 17239220Sgibbs temp = sd->sd_MS; 17339220Sgibbs SEEPROM_OUTB(sd, temp); 17439220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 17539220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 17639220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 17739220Sgibbs SEEPROM_OUTB(sd, temp); 17839220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 17939220Sgibbs } 18047507Sgibbs#ifdef AHC_DUMP_EEPROM 18155581Sgibbs printf("\nSerial EEPROM:\n\t"); 18239220Sgibbs for (k = 0; k < count; k = k + 1) { 18339220Sgibbs if (((k % 8) == 0) && (k != 0)) { 18455581Sgibbs printf ("\n\t"); 18539220Sgibbs } 18639220Sgibbs printf (" 0x%x", buf[k]); 18739220Sgibbs } 18839220Sgibbs printf ("\n"); 18939220Sgibbs#endif 19039220Sgibbs return (1); 19139220Sgibbs} 19265942Sgibbs 19365942Sgibbsint 19465942Sgibbsverify_cksum(struct seeprom_config *sc) 19565942Sgibbs{ 19665942Sgibbs int i; 19765942Sgibbs int maxaddr; 19865942Sgibbs uint32_t checksum; 19965942Sgibbs uint16_t *scarray; 20065942Sgibbs 20165942Sgibbs maxaddr = (sizeof(*sc)/2) - 1; 20265942Sgibbs checksum = 0; 20365942Sgibbs scarray = (uint16_t *)sc; 20465942Sgibbs 20565942Sgibbs for (i = 0; i < maxaddr; i++) 20665942Sgibbs checksum = checksum + scarray[i]; 20765942Sgibbs if (checksum == 0 20865942Sgibbs || (checksum & 0xFFFF) != sc->checksum) { 20965942Sgibbs return (0); 21065942Sgibbs } else { 21165942Sgibbs return(1); 21265942Sgibbs } 21365942Sgibbs} 214