aic7xxx_93cx6.c revision 95378
120169Snate/* 231606Syokota * Interface for the 93C66/56/46/26/06 serial eeprom parts. 331606Syokota * 431606Syokota * Copyright (c) 1995, 1996 Daniel M. Eischen 531606Syokota * All rights reserved. 631606Syokota * 731606Syokota * Redistribution and use in source and binary forms, with or without 831606Syokota * modification, are permitted provided that the following conditions 931606Syokota * are met: 1031606Syokota * 1. Redistributions of source code must retain the above copyright 1131606Syokota * notice, this list of conditions, and the following disclaimer, 1231606Syokota * without modification. 1331606Syokota * 2. The name of the author may not be used to endorse or promote products 1431606Syokota * derived from this software without specific prior written permission. 1531606Syokota * 1631606Syokota * Alternatively, this software may be distributed under the terms of the 1731606Syokota * GNU General Public License ("GPL"). 1831606Syokota * 1931606Syokota * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2031606Syokota * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2131606Syokota * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2231606Syokota * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2331606Syokota * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2431606Syokota * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2531606Syokota * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2631606Syokota * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2750476Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2831606Syokota * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29248478Sjkim * SUCH DAMAGE. 3053200Sphantom * 3179538Sru * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#14 $ 3220169Snate * 3320169Snate * $FreeBSD: head/sys/dev/aic7xxx/aic7xxx_93cx6.c 95378 2002-04-24 16:58:51Z gibbs $ 3475670Sru */ 3520169Snate 3656190Sasmodai/* 3756190Sasmodai * The instruction set of the 93C66/56/46/26/06 chips are as follows: 3856190Sasmodai * 3956190Sasmodai * Start OP * 4084877Syokota * Function Bit Code Address** Data Description 4184877Syokota * ------------------------------------------------------------------- 4284877Syokota * READ 1 10 A5 - A0 Reads data stored in memory, 4384877Syokota * starting at specified address 4484877Syokota * EWEN 1 00 11XXXX Write enable must precede 4584877Syokota * all programming modes 4620169Snate * ERASE 1 11 A5 - A0 Erase register A5A4A3A2A1A0 4720169Snate * WRITE 1 01 A5 - A0 D15 - D0 Writes register 4820169Snate * ERAL 1 00 10XXXX Erase all registers 4920169Snate * WRAL 1 00 01XXXX D15 - D0 Writes to all registers 5079727Sschweikh * EWDS 1 00 00XXXX Disables all programming 5131606Syokota * instructions 5231606Syokota * *Note: A value of X for address is a don't care condition. 5343725Syokota * **Note: There are 8 address bits for the 93C56/66 chips unlike 5443725Syokota * the 93C46/26/06 chips which have 6 address bits. 5579727Sschweikh * 5643725Syokota * The 93C46 has a four wire interface: clock, chip select, data in, and 5743725Syokota * data out. In order to perform one of the above functions, you need 5879727Sschweikh * to enable the chip select for a clock period (typically a minimum of 5922300Smpp * 1 usec, with the clock high and low a minimum of 750 and 250 nsec 6020169Snate * respectively). While the chip select remains high, you can clock in 6120169Snate * the instructions (above) starting with the start bit, followed by the 6231606Syokota * OP code, Address, and Data (if needed). For the READ instruction, the 6331606Syokota * requested 16-bit register contents is read from the data out line but 6431606Syokota * is preceded by an initial zero (leading 0, followed by 16-bits, MSB 6531606Syokota * first). The clock cycling from low to high initiates the next data 6657676Ssheldonh * bit to be sent from the chip. 6757676Ssheldonh * 6857676Ssheldonh */ 6979727Sschweikh 7057676Ssheldonh#ifdef __linux__ 7157676Ssheldonh#include "aic7xxx_osm.h" 7220169Snate#include "aic7xxx_inline.h" 7331606Syokota#include "aic7xxx_93cx6.h" 7479727Sschweikh#else 7581251Sru#include <dev/aic7xxx/aic7xxx_osm.h> 7681251Sru#include <dev/aic7xxx/aic7xxx_inline.h> 7731606Syokota#include <dev/aic7xxx/aic7xxx_93cx6.h> 7831606Syokota#endif 7931606Syokota 8031606Syokota/* 8181251Sru * Right now, we only have to read the SEEPROM. But we make it easier to 8281251Sru * add other 93Cx6 functions. 8331606Syokota */ 8431606Syokotastatic struct seeprom_cmd { 8531606Syokota uint8_t len; 8631606Syokota uint8_t bits[9]; 8731606Syokota} seeprom_read = {3, {1, 1, 0}}; 8831606Syokota 8931606Syokotastatic struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}}; 90141846Srustatic struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}}; 9131606Syokotastatic struct seeprom_cmd seeprom_write = {3, {1, 0, 1}}; 9231606Syokota 9331606Syokota/* 9431606Syokota * Wait for the SEERDY to go high; about 800 ns. 9579727Sschweikh */ 9631606Syokota#define CLOCK_PULSE(sd, rdy) \ 9720169Snate while ((SEEPROM_STATUS_INB(sd) & rdy) == 0) { \ 9831606Syokota ; /* Do nothing */ \ 9979727Sschweikh } \ 10031606Syokota (void)SEEPROM_INB(sd); /* Clear clock */ 10131606Syokota 10281251Sru/* 10381251Sru * Send a START condition and the given command 10479727Sschweikh */ 10531606Syokotastatic void 10631606Syokotasend_seeprom_cmd(struct seeprom_descriptor *sd, struct seeprom_cmd *cmd) 10779727Sschweikh{ 10831606Syokota uint8_t temp; 10931606Syokota int i = 0; 11031606Syokota 11131606Syokota /* Send chip select for one clock cycle. */ 11231606Syokota temp = sd->sd_MS ^ sd->sd_CS; 113178017Sjkim SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 114178017Sjkim CLOCK_PULSE(sd, sd->sd_RDY); 115178017Sjkim 11631606Syokota for (i = 0; i < cmd->len; i++) { 11731606Syokota if (cmd->bits[i] != 0) 11831606Syokota temp ^= sd->sd_DO; 11931606Syokota SEEPROM_OUTB(sd, temp); 12031606Syokota CLOCK_PULSE(sd, sd->sd_RDY); 12131606Syokota SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 12231606Syokota CLOCK_PULSE(sd, sd->sd_RDY); 12331606Syokota if (cmd->bits[i] != 0) 12431606Syokota temp ^= sd->sd_DO; 12531606Syokota } 12631606Syokota} 12731606Syokota 12831606Syokota/* 12921721Ssos * Clear CS put the chip in the reset state, where it can wait for new commands. 13079727Sschweikh */ 13121721Ssosstatic void 13220169Snatereset_seeprom(struct seeprom_descriptor *sd) 13320169Snate{ 13420169Snate uint8_t temp; 13520169Snate 13620169Snate temp = sd->sd_MS; 13720169Snate SEEPROM_OUTB(sd, temp); 13820169Snate CLOCK_PULSE(sd, sd->sd_RDY); 13920169Snate SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 14020169Snate CLOCK_PULSE(sd, sd->sd_RDY); 14131606Syokota SEEPROM_OUTB(sd, temp); 14279727Sschweikh CLOCK_PULSE(sd, sd->sd_RDY); 14331606Syokota} 14431606Syokota 14520169Snate/* 14657676Ssheldonh * Read the serial EEPROM and returns 1 if successful and 0 if 14757676Ssheldonh * not successful. 14831606Syokota */ 14920169Snateint 15020169Snateahc_read_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, 15120169Snate u_int start_addr, u_int count) 15220169Snate{ 15320169Snate int i = 0; 15420169Snate u_int k = 0; 15579727Sschweikh uint16_t v; 15621721Ssos uint8_t temp; 15721721Ssos 15820169Snate /* 15979727Sschweikh * Read the requested registers of the seeprom. The loop 16021721Ssos * will range from 0 to count-1. 16121721Ssos */ 16220169Snate for (k = start_addr; k < count + start_addr; k++) { 16320169Snate /* 16431606Syokota * Now we're ready to send the read command followed by the 16531606Syokota * address of the 16-bit register we want to read. 16679727Sschweikh */ 16731606Syokota send_seeprom_cmd(sd, &seeprom_read); 16831606Syokota 16931606Syokota /* Send the 6 or 8 bit address (MSB first, LSB last). */ 17079727Sschweikh temp = sd->sd_MS ^ sd->sd_CS; 17131606Syokota for (i = (sd->sd_chip - 1); i >= 0; i--) { 17231606Syokota if ((k & (1 << i)) != 0) 17331606Syokota temp ^= sd->sd_DO; 17431606Syokota SEEPROM_OUTB(sd, temp); 17531606Syokota CLOCK_PULSE(sd, sd->sd_RDY); 17679727Sschweikh SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 17779727Sschweikh CLOCK_PULSE(sd, sd->sd_RDY); 17879727Sschweikh if ((k & (1 << i)) != 0) 17957676Ssheldonh temp ^= sd->sd_DO; 18079727Sschweikh } 18131606Syokota 18231606Syokota /* 18331606Syokota * Now read the 16 bit register. An initial 0 precedes the 18431606Syokota * register contents which begins with bit 15 (MSB) and ends 18520169Snate * with bit 0 (LSB). The initial 0 will be shifted off the 18621721Ssos * top of our word as we let the loop run from 0 to 16. 18779727Sschweikh */ 18881251Sru v = 0; 18981251Sru for (i = 16; i >= 0; i--) { 19020169Snate SEEPROM_OUTB(sd, temp); 19171895Sru CLOCK_PULSE(sd, sd->sd_RDY); 19221721Ssos v <<= 1; 19321721Ssos if (SEEPROM_DATA_INB(sd) & sd->sd_DI) 19420169Snate v |= 1; 19520169Snate SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 19657676Ssheldonh CLOCK_PULSE(sd, sd->sd_RDY); 19757676Ssheldonh } 19857676Ssheldonh 19957676Ssheldonh buf[k - start_addr] = v; 20020169Snate 20120169Snate /* Reset the chip select for the next command cycle. */ 20220169Snate reset_seeprom(sd); 20357676Ssheldonh } 20457676Ssheldonh#ifdef AHC_DUMP_EEPROM 20557676Ssheldonh printf("\nSerial EEPROM:\n\t"); 20657676Ssheldonh for (k = 0; k < count; k = k + 1) { 20779727Sschweikh if (((k % 8) == 0) && (k != 0)) { 20820169Snate printf ("\n\t"); 20920169Snate } 21020169Snate printf (" 0x%x", buf[k]); 21120169Snate } 21271895Sru printf ("\n"); 21379727Sschweikh#endif 21420169Snate return (1); 21557676Ssheldonh} 21657676Ssheldonh 21721721Ssos/* 21820169Snate * Write the serial EEPROM and return 1 if successful and 0 if 21920169Snate * not successful. 22031606Syokota */ 22131606Syokotaint 22221721Ssosahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf, 22357676Ssheldonh u_int start_addr, u_int count) 22484877Syokota{ 22584877Syokota uint16_t v; 22681251Sru uint8_t temp; 22784877Syokota int i, k; 22884877Syokota 22921721Ssos /* Place the chip into write-enable mode */ 23031606Syokota send_seeprom_cmd(sd, &seeprom_ewen); 23179727Sschweikh reset_seeprom(sd); 23257676Ssheldonh 23357676Ssheldonh /* Write all requested data out to the seeprom. */ 23479727Sschweikh temp = sd->sd_MS ^ sd->sd_CS; 23579727Sschweikh for (k = start_addr; k < count + start_addr; k++) { 23657676Ssheldonh /* Send the write command */ 23757676Ssheldonh send_seeprom_cmd(sd, &seeprom_write); 23821721Ssos 23931606Syokota /* Send the 6 or 8 bit address (MSB first). */ 24031606Syokota for (i = (sd->sd_chip - 1); i >= 0; i--) { 24131606Syokota if ((k & (1 << i)) != 0) 24231606Syokota temp ^= sd->sd_DO; 24331606Syokota SEEPROM_OUTB(sd, temp); 24431606Syokota CLOCK_PULSE(sd, sd->sd_RDY); 24531606Syokota SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 24631606Syokota CLOCK_PULSE(sd, sd->sd_RDY); 24731606Syokota if ((k & (1 << i)) != 0) 24831606Syokota temp ^= sd->sd_DO; 24931606Syokota } 25031606Syokota 25179727Sschweikh /* Write the 16 bit value, MSB first */ 25231606Syokota v = buf[k - start_addr]; 25331606Syokota for (i = 15; i >= 0; i--) { 25479727Sschweikh if ((v & (1 << i)) != 0) 25579727Sschweikh temp ^= sd->sd_DO; 25657676Ssheldonh SEEPROM_OUTB(sd, temp); 25757676Ssheldonh CLOCK_PULSE(sd, sd->sd_RDY); 25879727Sschweikh SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 25931606Syokota CLOCK_PULSE(sd, sd->sd_RDY); 26021721Ssos if ((v & (1 << i)) != 0) 26131606Syokota temp ^= sd->sd_DO; 26231606Syokota } 26357676Ssheldonh 26457676Ssheldonh /* Wait for the chip to complete the write */ 26531606Syokota temp = sd->sd_MS; 26631606Syokota SEEPROM_OUTB(sd, temp); 26779727Sschweikh CLOCK_PULSE(sd, sd->sd_RDY); 26832735Syokota temp = sd->sd_MS ^ sd->sd_CS; 26932735Syokota do { 27032735Syokota SEEPROM_OUTB(sd, temp); 27132735Syokota CLOCK_PULSE(sd, sd->sd_RDY); 27232735Syokota SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 27332735Syokota CLOCK_PULSE(sd, sd->sd_RDY); 27443230Syokota } while ((SEEPROM_DATA_INB(sd) & sd->sd_DI) == 0); 27543230Syokota 27643230Syokota reset_seeprom(sd); 27743230Syokota } 27843230Syokota 27943230Syokota /* Put the chip back into write-protect mode */ 28043230Syokota send_seeprom_cmd(sd, &seeprom_ewds); 281141846Sru reset_seeprom(sd); 28243230Syokota 28343230Syokota return (1); 28443230Syokota} 28543230Syokota 28643230Syokotaint 28743230Syokotaahc_verify_cksum(struct seeprom_config *sc) 288141846Sru{ 28968716Sru int i; 29068716Sru int maxaddr; 29168716Sru uint32_t checksum; 29243230Syokota uint16_t *scarray; 29343230Syokota 29443230Syokota maxaddr = (sizeof(*sc)/2) - 1; 29543230Syokota checksum = 0; 29643230Syokota scarray = (uint16_t *)sc; 29743230Syokota 29843230Syokota for (i = 0; i < maxaddr; i++) 29943230Syokota checksum = checksum + scarray[i]; 30043230Syokota if (checksum == 0 30143230Syokota || (checksum & 0xFFFF) != sc->checksum) { 30243230Syokota return (0); 30343230Syokota } else { 30443230Syokota return(1); 30543230Syokota } 30643230Syokota} 30743230Syokota