/*` * mp1000-seprom.c * * This file contains the Serial EEPROM code for the MP1000 board * * Copyright (C) 2005 Comdial Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include /* If SepromInit() can initialize and checksum the seprom successfully, */ /* then it will point seprom_data_ptr at the shadow copy. */ static eeprom_struct seprom_data; /* shadow copy of seprom content */ eeprom_struct *seprom_data_ptr = 0; /* 0 => not initialized */ /* * Port D Bit 5 is Chip Select for EEPROM * Port E Bit 0 is Input, Data out from EEPROM * Port E Bit 1 is Output, Data in to EEPROM * Port E Bit 2 is Output, CLK to EEPROM */ static char *port_d_ptr = (char *)(CLPS7111_VIRT_BASE + PDDR); static char *port_e_ptr = (char *)(CLPS7111_VIRT_BASE + PEDR); #define NO_OF_SHORTS 64 // Device is 64 x 16 bits #define ENABLE_RW 0 #define DISABLE_RW 1 static inline void toggle_seprom_clock(void) { *port_e_ptr |= HwPortESepromCLK; *port_e_ptr &= ~(HwPortESepromCLK); } static inline void select_eeprom(void) { *port_d_ptr |= HwPortDEECS; *port_e_ptr &= ~(HwPortESepromCLK); } static inline void deselect_eeprom(void) { *port_d_ptr &= ~(HwPortDEECS); *port_e_ptr &= ~(HwPortESepromDIn); } /* * GetSepromDataPtr - returns pointer to shadow (RAM) copy of seprom * and returns 0 if seprom is not initialized or * has a checksum error. */ eeprom_struct* get_seprom_ptr(void) { return seprom_data_ptr; } unsigned char* get_eeprom_mac_address(void) { return seprom_data_ptr->variant.eprom_struct.mac_Address; } /* * ReadSProm, Physically reads data from the Serial PROM */ static void read_sprom(short address, int length, eeprom_struct *buffer) { short data = COMMAND_READ | (address & 0x3F); short bit; int i; select_eeprom(); // Clock in 9 bits of the command for (i = 0, bit = 0x100; i < 9; i++, bit >>= 1) { if (data & bit) *port_e_ptr |= HwPortESepromDIn; else *port_e_ptr &= ~(HwPortESepromDIn); toggle_seprom_clock(); } // // Now read one or more shorts of data from the Seprom // while (length-- > 0) { data = 0; // Read 16 bits at a time for (i = 0; i < 16; i++) { data <<= 1; toggle_seprom_clock(); data |= *port_e_ptr & HwPortESepromDOut; } buffer->variant.eprom_short_data[address++] = data; } deselect_eeprom(); return; } /* * ReadSerialPROM * * Input: Pointer to array of 64 x 16 Bits * * Output: if no problem reading data is filled in */ static void read_serial_prom(eeprom_struct *data) { read_sprom(0, 64, data); } // // Compute Serial EEPROM checksum // // Input: Pointer to struct with Eprom data // // Output: The computed Eprom checksum // static short compute_seprom_checksum(eeprom_struct *data) { short checksum = 0; int i; for (i = 0; i < 126; i++) { checksum += (short)data->variant.eprom_byte_data[i]; } return((short)(0x5555 - (checksum & 0xFFFF))); } // // Make sure the data port bits for the SEPROM are correctly initialised // void __init seprom_init(void) { short checksum; // Init Port D *(char *)(CLPS7111_VIRT_BASE + PDDDR) = 0x0; *(char *)(CLPS7111_VIRT_BASE + PDDR) = 0x15; // Init Port E *(int *)(CLPS7111_VIRT_BASE + PEDDR) = 0x06; *(int *)(CLPS7111_VIRT_BASE + PEDR) = 0x04; // // Make sure that EEPROM struct size never exceeds 128 bytes // if (sizeof(eeprom_struct) > 128) { panic("Serial PROM struct size > 128, aborting read\n"); } read_serial_prom(&seprom_data); checksum = compute_seprom_checksum(&seprom_data); if (checksum != seprom_data.variant.eprom_short_data[63]) { panic("Serial EEPROM checksum failed\n"); } seprom_data_ptr = &seprom_data; }