aic7xxx_93cx6.c revision 55581
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 * 2150477Speter * $FreeBSD: head/sys/dev/aic7xxx/aic7xxx_93cx6.c 55581 2000-01-07 23:08:20Z gibbs $ 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 5847507Sgibbs#include "opt_aic7xxx.h" 5947507Sgibbs 6039220Sgibbs#include <sys/param.h> 6139220Sgibbs#include <sys/systm.h> 6239220Sgibbs#include <machine/bus_memio.h> 6339220Sgibbs#include <machine/bus_pio.h> 6439220Sgibbs#include <machine/bus.h> 6539220Sgibbs#include <dev/aic7xxx/93cx6.h> 6639220Sgibbs 6739220Sgibbs/* 6839220Sgibbs * Right now, we only have to read the SEEPROM. But we make it easier to 6939220Sgibbs * add other 93Cx6 functions. 7039220Sgibbs */ 7139220Sgibbsstatic struct seeprom_cmd { 7239220Sgibbs unsigned char len; 7339220Sgibbs unsigned char bits[3]; 7439220Sgibbs} seeprom_read = {3, {1, 1, 0}}; 7539220Sgibbs 7639220Sgibbs/* 7739220Sgibbs * Wait for the SEERDY to go high; about 800 ns. 7839220Sgibbs */ 7939220Sgibbs#define CLOCK_PULSE(sd, rdy) \ 8039220Sgibbs while ((SEEPROM_STATUS_INB(sd) & rdy) == 0) { \ 8139220Sgibbs ; /* Do nothing */ \ 8239220Sgibbs } \ 8339220Sgibbs (void)SEEPROM_INB(sd); /* Clear clock */ 8439220Sgibbs 8539220Sgibbs/* 8639220Sgibbs * Read the serial EEPROM and returns 1 if successful and 0 if 8739220Sgibbs * not successful. 8839220Sgibbs */ 8939220Sgibbsint 9039220Sgibbsread_seeprom(sd, buf, start_addr, count) 9139220Sgibbs struct seeprom_descriptor *sd; 9239220Sgibbs u_int16_t *buf; 9339220Sgibbs bus_size_t start_addr; 9439220Sgibbs bus_size_t count; 9539220Sgibbs{ 9639220Sgibbs int i = 0; 9739220Sgibbs u_int k = 0; 9839220Sgibbs u_int16_t v; 9939220Sgibbs u_int8_t temp; 10039220Sgibbs 10139220Sgibbs /* 10239220Sgibbs * Read the requested registers of the seeprom. The loop 10339220Sgibbs * will range from 0 to count-1. 10439220Sgibbs */ 10539220Sgibbs for (k = start_addr; k < count + start_addr; k++) { 10639220Sgibbs /* Send chip select for one clock cycle. */ 10739220Sgibbs temp = sd->sd_MS ^ sd->sd_CS; 10839220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 10939220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 11039220Sgibbs 11139220Sgibbs /* 11239220Sgibbs * Now we're ready to send the read command followed by the 11339220Sgibbs * address of the 16-bit register we want to read. 11439220Sgibbs */ 11539220Sgibbs for (i = 0; i < seeprom_read.len; i++) { 11639220Sgibbs if (seeprom_read.bits[i] != 0) 11739220Sgibbs temp ^= sd->sd_DO; 11839220Sgibbs SEEPROM_OUTB(sd, temp); 11939220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 12039220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 12139220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 12239220Sgibbs if (seeprom_read.bits[i] != 0) 12339220Sgibbs temp ^= sd->sd_DO; 12439220Sgibbs } 12539220Sgibbs /* Send the 6 or 8 bit address (MSB first, LSB last). */ 12639220Sgibbs for (i = (sd->sd_chip - 1); i >= 0; i--) { 12739220Sgibbs if ((k & (1 << i)) != 0) 12839220Sgibbs temp ^= sd->sd_DO; 12939220Sgibbs SEEPROM_OUTB(sd, temp); 13039220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 13139220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 13239220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 13339220Sgibbs if ((k & (1 << i)) != 0) 13439220Sgibbs temp ^= sd->sd_DO; 13539220Sgibbs } 13639220Sgibbs 13739220Sgibbs /* 13839220Sgibbs * Now read the 16 bit register. An initial 0 precedes the 13939220Sgibbs * register contents which begins with bit 15 (MSB) and ends 14039220Sgibbs * with bit 0 (LSB). The initial 0 will be shifted off the 14139220Sgibbs * top of our word as we let the loop run from 0 to 16. 14239220Sgibbs */ 14339220Sgibbs v = 0; 14439220Sgibbs for (i = 16; i >= 0; i--) { 14539220Sgibbs SEEPROM_OUTB(sd, temp); 14639220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 14739220Sgibbs v <<= 1; 14839220Sgibbs if (SEEPROM_DATA_INB(sd) & sd->sd_DI) 14939220Sgibbs v |= 1; 15039220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 15139220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 15239220Sgibbs } 15339220Sgibbs 15439220Sgibbs buf[k - start_addr] = v; 15539220Sgibbs 15639220Sgibbs /* Reset the chip select for the next command cycle. */ 15739220Sgibbs temp = sd->sd_MS; 15839220Sgibbs SEEPROM_OUTB(sd, temp); 15939220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 16039220Sgibbs SEEPROM_OUTB(sd, temp ^ sd->sd_CK); 16139220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 16239220Sgibbs SEEPROM_OUTB(sd, temp); 16339220Sgibbs CLOCK_PULSE(sd, sd->sd_RDY); 16439220Sgibbs } 16547507Sgibbs#ifdef AHC_DUMP_EEPROM 16655581Sgibbs printf("\nSerial EEPROM:\n\t"); 16739220Sgibbs for (k = 0; k < count; k = k + 1) { 16839220Sgibbs if (((k % 8) == 0) && (k != 0)) { 16955581Sgibbs printf ("\n\t"); 17039220Sgibbs } 17139220Sgibbs printf (" 0x%x", buf[k]); 17239220Sgibbs } 17339220Sgibbs printf ("\n"); 17439220Sgibbs#endif 17539220Sgibbs return (1); 17639220Sgibbs} 177