aic7xxx_93cx6.c revision 95378
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 1795378Sgibbs * GNU General 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 * 3195378Sgibbs * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#14 $ 3265942Sgibbs * 3350477Speter * $FreeBSD: head/sys/dev/aic7xxx/aic7xxx_93cx6.c 95378 2002-04-24 16:58:51Z gibbs $ 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 7095378Sgibbs#ifdef __linux__ 7195378Sgibbs#include "aic7xxx_osm.h" 7295378Sgibbs#include "aic7xxx_inline.h" 7395378Sgibbs#include "aic7xxx_93cx6.h" 7495378Sgibbs#else 7595378Sgibbs#include <dev/aic7xxx/aic7xxx_osm.h> 7665942Sgibbs#include <dev/aic7xxx/aic7xxx_inline.h> 7765942Sgibbs#include <dev/aic7xxx/aic7xxx_93cx6.h> 7895378Sgibbs#endif 7939220Sgibbs 8039220Sgibbs/* 8139220Sgibbs * Right now, we only have to read the SEEPROM. But we make it easier to 8239220Sgibbs * add other 93Cx6 functions. 8339220Sgibbs */ 8439220Sgibbsstatic struct seeprom_cmd { 8565942Sgibbs uint8_t len; 8695378Sgibbs uint8_t bits[9]; 8739220Sgibbs} seeprom_read = {3, {1, 1, 0}}; 8839220Sgibbs 8995378Sgibbsstatic struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; 9095378Sgibbsstatic struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; 9195378Sgibbsstatic struct seeprom_cmd seeprom_write = {3, {1, 0, 1}}; 9295378Sgibbs 9339220Sgibbs/* 9439220Sgibbs * Wait for the SEERDY to go high; about 800 ns. 9539220Sgibbs */ 9639220Sgibbs#define CLOCK_PULSE(sd, rdy) \ 9739220Sgibbs while ((SEEPROM_STATUS_INB(sd) & rdy) == 0) { \ 9839220Sgibbs ; /* Do nothing */ \ 9939220Sgibbs } \ 10039220Sgibbs (void)SEEPROM_INB(sd); /* Clear clock */ 10139220Sgibbs 10239220Sgibbs/* 10395378Sgibbs * Send a START condition and the given command 10495378Sgibbs */ 10595378Sgibbsstatic void 10695378Sgibbssend_seeprom_cmd(struct seeprom_descriptor *sd, struct seeprom_cmd *cmd) 10795378Sgibbs{ 10895378Sgibbs uint8_t temp; 10995378Sgibbs int i = 0; 11095378Sgibbs 11195378Sgibbs /* Send chip select for one clock cycle. */ 11295378Sgibbs temp = sd->sd_MS ^ sd->sd_CS; 11395378Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 11495378Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 11595378Sgibbs 11695378Sgibbs for (i = 0; i < cmd->len; i++) { 11795378Sgibbs if (cmd->bits[i] != 0) 11895378Sgibbs temp ^= sd->sd_DO; 11995378Sgibbs SEEPROM_OUTB(sd, temp); 12095378Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 12195378Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 12295378Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 12395378Sgibbs if (cmd->bits[i] != 0) 12495378Sgibbs temp ^= sd->sd_DO; 12595378Sgibbs } 12695378Sgibbs} 12795378Sgibbs 12895378Sgibbs/* 12995378Sgibbs * Clear CS put the chip in the reset state, where it can wait for new commands. 13095378Sgibbs */ 13195378Sgibbsstatic void 13295378Sgibbsreset_seeprom(struct seeprom_descriptor *sd) 13395378Sgibbs{ 13495378Sgibbs uint8_t temp; 13595378Sgibbs 13695378Sgibbs temp = sd->sd_MS; 13795378Sgibbs SEEPROM_OUTB(sd, temp); 13895378Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 13995378Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 14095378Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 14195378Sgibbs SEEPROM_OUTB(sd, temp); 14295378Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 14395378Sgibbs} 14495378Sgibbs 14595378Sgibbs/* 14639220Sgibbs * Read the serial EEPROM and returns 1 if successful and 0 if 14739220Sgibbs * not successful. 14839220Sgibbs */ 14939220Sgibbsint 15095378Sgibbsahc_read_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, 15195378Sgibbs u_int start_addr, u_int count) 15239220Sgibbs{ 15339220Sgibbs int i = 0; 15439220Sgibbs u_int k = 0; 15563457Sgibbs uint16_t v; 15663457Sgibbs uint8_t temp; 15739220Sgibbs 15839220Sgibbs /* 15939220Sgibbs * Read the requested registers of the seeprom. The loop 16039220Sgibbs * will range from 0 to count-1. 16139220Sgibbs */ 16239220Sgibbs for (k = start_addr; k < count + start_addr; k++) { 16339220Sgibbs /* 16439220Sgibbs * Now we're ready to send the read command followed by the 16539220Sgibbs * address of the 16-bit register we want to read. 16639220Sgibbs */ 16795378Sgibbs send_seeprom_cmd(sd, &seeprom_read); 16895378Sgibbs 16939220Sgibbs /* Send the 6 or 8 bit address (MSB first, LSB last). */ 17095378Sgibbs temp = sd->sd_MS ^ sd->sd_CS; 17139220Sgibbs for (i = (sd->sd_chip - 1); i >= 0; i--) { 17239220Sgibbs if ((k & (1 << i)) != 0) 17339220Sgibbs temp ^= sd->sd_DO; 17439220Sgibbs SEEPROM_OUTB(sd, temp); 17539220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 17639220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 17739220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 17839220Sgibbs if ((k & (1 << i)) != 0) 17939220Sgibbs temp ^= sd->sd_DO; 18039220Sgibbs } 18139220Sgibbs 18239220Sgibbs /* 18339220Sgibbs * Now read the 16 bit register. An initial 0 precedes the 18439220Sgibbs * register contents which begins with bit 15 (MSB) and ends 18539220Sgibbs * with bit 0 (LSB). The initial 0 will be shifted off the 18639220Sgibbs * top of our word as we let the loop run from 0 to 16. 18739220Sgibbs */ 18839220Sgibbs v = 0; 18939220Sgibbs for (i = 16; i >= 0; i--) { 19039220Sgibbs SEEPROM_OUTB(sd, temp); 19139220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 19239220Sgibbs v <<= 1; 19339220Sgibbs if (SEEPROM_DATA_INB(sd) & sd->sd_DI) 19439220Sgibbs v |= 1; 19539220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 19639220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 19739220Sgibbs } 19839220Sgibbs 19939220Sgibbs buf[k - start_addr] = v; 20039220Sgibbs 20139220Sgibbs /* Reset the chip select for the next command cycle. */ 20295378Sgibbs reset_seeprom(sd); 20339220Sgibbs } 20447507Sgibbs#ifdef AHC_DUMP_EEPROM 20555581Sgibbs printf("\nSerial EEPROM:\n\t"); 20639220Sgibbs for (k = 0; k < count; k = k + 1) { 20739220Sgibbs if (((k % 8) == 0) && (k != 0)) { 20855581Sgibbs printf ("\n\t"); 20939220Sgibbs } 21039220Sgibbs printf (" 0x%x", buf[k]); 21139220Sgibbs } 21239220Sgibbs printf ("\n"); 21339220Sgibbs#endif 21439220Sgibbs return (1); 21539220Sgibbs} 21665942Sgibbs 21795378Sgibbs/* 21895378Sgibbs * Write the serial EEPROM and return 1 if successful and 0 if 21995378Sgibbs * not successful. 22095378Sgibbs */ 22165942Sgibbsint 22295378Sgibbsahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, 22395378Sgibbs u_int start_addr, u_int count) 22465942Sgibbs{ 22595378Sgibbs uint16_t v; 22695378Sgibbs uint8_t temp; 22795378Sgibbs int i, k; 22895378Sgibbs 22995378Sgibbs /* Place the chip into write-enable mode */ 23095378Sgibbs send_seeprom_cmd(sd, &seeprom_ewen); 23195378Sgibbs reset_seeprom(sd); 23295378Sgibbs 23395378Sgibbs /* Write all requested data out to the seeprom. */ 23495378Sgibbs temp = sd->sd_MS ^ sd->sd_CS; 23595378Sgibbs for (k = start_addr; k < count + start_addr; k++) { 23695378Sgibbs /* Send the write command */ 23795378Sgibbs send_seeprom_cmd(sd, &seeprom_write); 23895378Sgibbs 23995378Sgibbs /* Send the 6 or 8 bit address (MSB first). */ 24095378Sgibbs for (i = (sd->sd_chip - 1); i >= 0; i--) { 24195378Sgibbs if ((k & (1 << i)) != 0) 24295378Sgibbs temp ^= sd->sd_DO; 24395378Sgibbs SEEPROM_OUTB(sd, temp); 24495378Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 24595378Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 24695378Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 24795378Sgibbs if ((k & (1 << i)) != 0) 24895378Sgibbs temp ^= sd->sd_DO; 24995378Sgibbs } 25095378Sgibbs 25195378Sgibbs /* Write the 16 bit value, MSB first */ 25295378Sgibbs v = buf[k - start_addr]; 25395378Sgibbs for (i = 15; i >= 0; i--) { 25495378Sgibbs if ((v & (1 << i)) != 0) 25595378Sgibbs temp ^= sd->sd_DO; 25695378Sgibbs SEEPROM_OUTB(sd, temp); 25795378Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 25895378Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 25995378Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 26095378Sgibbs if ((v & (1 << i)) != 0) 26195378Sgibbs temp ^= sd->sd_DO; 26295378Sgibbs } 26395378Sgibbs 26495378Sgibbs /* Wait for the chip to complete the write */ 26595378Sgibbs temp = sd->sd_MS; 26695378Sgibbs SEEPROM_OUTB(sd, temp); 26795378Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 26895378Sgibbs temp = sd->sd_MS ^ sd->sd_CS; 26995378Sgibbs do { 27095378Sgibbs SEEPROM_OUTB(sd, temp); 27195378Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 27295378Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 27395378Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 27495378Sgibbs } while ((SEEPROM_DATA_INB(sd) & sd->sd_DI) == 0); 27595378Sgibbs 27695378Sgibbs reset_seeprom(sd); 27795378Sgibbs } 27895378Sgibbs 27995378Sgibbs /* Put the chip back into write-protect mode */ 28095378Sgibbs send_seeprom_cmd(sd, &seeprom_ewds); 28195378Sgibbs reset_seeprom(sd); 28295378Sgibbs 28395378Sgibbs return (1); 28495378Sgibbs} 28595378Sgibbs 28695378Sgibbsint 28795378Sgibbsahc_verify_cksum(struct seeprom_config *sc) 28895378Sgibbs{ 28965942Sgibbs int i; 29065942Sgibbs int maxaddr; 29165942Sgibbs uint32_t checksum; 29265942Sgibbs uint16_t *scarray; 29365942Sgibbs 29465942Sgibbs maxaddr = (sizeof(*sc)/2) - 1; 29565942Sgibbs checksum = 0; 29665942Sgibbs scarray = (uint16_t *)sc; 29765942Sgibbs 29865942Sgibbs for (i = 0; i < maxaddr; i++) 29965942Sgibbs checksum = checksum + scarray[i]; 30065942Sgibbs if (checksum == 0 30165942Sgibbs || (checksum & 0xFFFF) != sc->checksum) { 30265942Sgibbs return (0); 30365942Sgibbs } else { 30465942Sgibbs return(1); 30565942Sgibbs } 30665942Sgibbs} 307