aic7xxx_93cx6.c revision 39220
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 1139220Sgibbs * notice immediately at the beginning of the file, without modification, 1239220Sgibbs * this list of conditions, and the following disclaimer. 1339220Sgibbs * 2. Redistributions in binary form must reproduce the above copyright 1439220Sgibbs * notice, this list of conditions and the following disclaimer in the 1539220Sgibbs * documentation and/or other materials provided with the distribution. 1639220Sgibbs * 3. Absolutely no warranty of function or purpose is made by the author 1739220Sgibbs * Daniel M. Eischen. 1839220Sgibbs * 4. Modifications may be freely made to this file if the above conditions 1939220Sgibbs * are met. 2039220Sgibbs * 2139220Sgibbs * $Id: 93cx6.c,v 1.10 1997/02/22 09:38:36 peter Exp $ 2239220Sgibbs */ 2339220Sgibbs 2439220Sgibbs/* 2539220Sgibbs * The instruction set of the 93C66/56/46/26/06 chips are as follows: 2639220Sgibbs * 2739220Sgibbs * Start OP * 2839220Sgibbs * Function Bit Code Address** Data Description 2939220Sgibbs * ------------------------------------------------------------------- 3039220Sgibbs * READ 1 10 A5 - A0 Reads data stored in memory, 3139220Sgibbs * starting at specified address 3239220Sgibbs * EWEN 1 00 11XXXX Write enable must preceed 3339220Sgibbs * all programming modes 3439220Sgibbs * ERASE 1 11 A5 - A0 Erase register A5A4A3A2A1A0 3539220Sgibbs * WRITE 1 01 A5 - A0 D15 - D0 Writes register 3639220Sgibbs * ERAL 1 00 10XXXX Erase all registers 3739220Sgibbs * WRAL 1 00 01XXXX D15 - D0 Writes to all registers 3839220Sgibbs * EWDS 1 00 00XXXX Disables all programming 3939220Sgibbs * instructions 4039220Sgibbs * *Note: A value of X for address is a don't care condition. 4139220Sgibbs * **Note: There are 8 address bits for the 93C56/66 chips unlike 4239220Sgibbs * the 93C46/26/06 chips which have 6 address bits. 4339220Sgibbs * 4439220Sgibbs * The 93C46 has a four wire interface: clock, chip select, data in, and 4539220Sgibbs * data out. In order to perform one of the above functions, you need 4639220Sgibbs * to enable the chip select for a clock period (typically a minimum of 4739220Sgibbs * 1 usec, with the clock high and low a minimum of 750 and 250 nsec 4839220Sgibbs * respectively). While the chip select remains high, you can clock in 4939220Sgibbs * the instructions (above) starting with the start bit, followed by the 5039220Sgibbs * OP code, Address, and Data (if needed). For the READ instruction, the 5139220Sgibbs * requested 16-bit register contents is read from the data out line but 5239220Sgibbs * is preceded by an initial zero (leading 0, followed by 16-bits, MSB 5339220Sgibbs * first). The clock cycling from low to high initiates the next data 5439220Sgibbs * bit to be sent from the chip. 5539220Sgibbs * 5639220Sgibbs */ 5739220Sgibbs 5839220Sgibbs#include <sys/param.h> 5939220Sgibbs#include <sys/systm.h> 6039220Sgibbs#include <machine/bus_memio.h> 6139220Sgibbs#include <machine/bus_pio.h> 6239220Sgibbs#include <machine/bus.h> 6339220Sgibbs#include <dev/aic7xxx/93cx6.h> 6439220Sgibbs 6539220Sgibbs/* 6639220Sgibbs * Right now, we only have to read the SEEPROM. But we make it easier to 6739220Sgibbs * add other 93Cx6 functions. 6839220Sgibbs */ 6939220Sgibbsstatic struct seeprom_cmd { 7039220Sgibbs unsigned char len; 7139220Sgibbs unsigned char bits[3]; 7239220Sgibbs} seeprom_read = {3, {1, 1, 0}}; 7339220Sgibbs 7439220Sgibbs/* 7539220Sgibbs * Wait for the SEERDY to go high; about 800 ns. 7639220Sgibbs */ 7739220Sgibbs#define CLOCK_PULSE(sd, rdy) \ 7839220Sgibbs while ((SEEPROM_STATUS_INB(sd) & rdy) == 0) { \ 7939220Sgibbs ; /* Do nothing */ \ 8039220Sgibbs } \ 8139220Sgibbs (void)SEEPROM_INB(sd); /* Clear clock */ 8239220Sgibbs 8339220Sgibbs/* 8439220Sgibbs * Read the serial EEPROM and returns 1 if successful and 0 if 8539220Sgibbs * not successful. 8639220Sgibbs */ 8739220Sgibbsint 8839220Sgibbsread_seeprom(sd, buf, start_addr, count) 8939220Sgibbs struct seeprom_descriptor *sd; 9039220Sgibbs u_int16_t *buf; 9139220Sgibbs bus_size_t start_addr; 9239220Sgibbs bus_size_t count; 9339220Sgibbs{ 9439220Sgibbs int i = 0; 9539220Sgibbs u_int k = 0; 9639220Sgibbs u_int16_t v; 9739220Sgibbs u_int8_t temp; 9839220Sgibbs 9939220Sgibbs /* 10039220Sgibbs * Read the requested registers of the seeprom. The loop 10139220Sgibbs * will range from 0 to count-1. 10239220Sgibbs */ 10339220Sgibbs for (k = start_addr; k < count + start_addr; k++) { 10439220Sgibbs /* Send chip select for one clock cycle. */ 10539220Sgibbs temp = sd->sd_MS ^ sd->sd_CS; 10639220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 10739220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 10839220Sgibbs 10939220Sgibbs /* 11039220Sgibbs * Now we're ready to send the read command followed by the 11139220Sgibbs * address of the 16-bit register we want to read. 11239220Sgibbs */ 11339220Sgibbs for (i = 0; i < seeprom_read.len; i++) { 11439220Sgibbs if (seeprom_read.bits[i] != 0) 11539220Sgibbs temp ^= sd->sd_DO; 11639220Sgibbs SEEPROM_OUTB(sd, temp); 11739220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 11839220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 11939220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 12039220Sgibbs if (seeprom_read.bits[i] != 0) 12139220Sgibbs temp ^= sd->sd_DO; 12239220Sgibbs } 12339220Sgibbs /* Send the 6 or 8 bit address (MSB first, LSB last). */ 12439220Sgibbs for (i = (sd->sd_chip - 1); i >= 0; i--) { 12539220Sgibbs if ((k & (1 << i)) != 0) 12639220Sgibbs temp ^= sd->sd_DO; 12739220Sgibbs SEEPROM_OUTB(sd, temp); 12839220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 12939220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 13039220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 13139220Sgibbs if ((k & (1 << i)) != 0) 13239220Sgibbs temp ^= sd->sd_DO; 13339220Sgibbs } 13439220Sgibbs 13539220Sgibbs /* 13639220Sgibbs * Now read the 16 bit register. An initial 0 precedes the 13739220Sgibbs * register contents which begins with bit 15 (MSB) and ends 13839220Sgibbs * with bit 0 (LSB). The initial 0 will be shifted off the 13939220Sgibbs * top of our word as we let the loop run from 0 to 16. 14039220Sgibbs */ 14139220Sgibbs v = 0; 14239220Sgibbs for (i = 16; i >= 0; i--) { 14339220Sgibbs SEEPROM_OUTB(sd, temp); 14439220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 14539220Sgibbs v <<= 1; 14639220Sgibbs if (SEEPROM_DATA_INB(sd) & sd->sd_DI) 14739220Sgibbs v |= 1; 14839220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 14939220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 15039220Sgibbs } 15139220Sgibbs 15239220Sgibbs buf[k - start_addr] = v; 15339220Sgibbs 15439220Sgibbs /* Reset the chip select for the next command cycle. */ 15539220Sgibbs temp = sd->sd_MS; 15639220Sgibbs SEEPROM_OUTB(sd, temp); 15739220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 15839220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 15939220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 16039220Sgibbs SEEPROM_OUTB(sd, temp); 16139220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 16239220Sgibbs } 16339220Sgibbs#ifdef 93CX6_DUMP_EEPROM 16439220Sgibbs printf("\nSerial EEPROM:"); 16539220Sgibbs for (k = 0; k < count; k = k + 1) { 16639220Sgibbs if (((k % 8) == 0) && (k != 0)) { 16739220Sgibbs printf ("\n "); 16839220Sgibbs } 16939220Sgibbs printf (" 0x%x", buf[k]); 17039220Sgibbs } 17139220Sgibbs printf ("\n"); 17239220Sgibbs#endif 17339220Sgibbs return (1); 17439220Sgibbs} 175