123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- /*`
- * 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 <linux/kernel.h>
- #include <linux/init.h>
- #include <asm/hardware.h>
- #include <asm/hardware/clps7111.h>
- #include <asm/arch/mp1000-seprom.h>
- /* 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;
- }
|