4 * This file contains the Serial EEPROM code for the MP1000 board
6 * Copyright (C) 2005 Comdial Corporation
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <linux/kernel.h>
25 #include <linux/init.h>
26 #include <asm/hardware.h>
27 #include <asm/hardware/clps7111.h>
28 #include <asm/arch/mp1000-seprom.h>
30 /* If SepromInit() can initialize and checksum the seprom successfully, */
31 /* then it will point seprom_data_ptr at the shadow copy. */
33 static eeprom_struct seprom_data
; /* shadow copy of seprom content */
35 eeprom_struct
*seprom_data_ptr
= 0; /* 0 => not initialized */
38 * Port D Bit 5 is Chip Select for EEPROM
39 * Port E Bit 0 is Input, Data out from EEPROM
40 * Port E Bit 1 is Output, Data in to EEPROM
41 * Port E Bit 2 is Output, CLK to EEPROM
44 static char *port_d_ptr
= (char *)(CLPS7111_VIRT_BASE
+ PDDR
);
45 static char *port_e_ptr
= (char *)(CLPS7111_VIRT_BASE
+ PEDR
);
47 #define NO_OF_SHORTS 64 // Device is 64 x 16 bits
51 static inline void toggle_seprom_clock(void)
53 *port_e_ptr
|= HwPortESepromCLK
;
54 *port_e_ptr
&= ~(HwPortESepromCLK
);
57 static inline void select_eeprom(void)
59 *port_d_ptr
|= HwPortDEECS
;
60 *port_e_ptr
&= ~(HwPortESepromCLK
);
63 static inline void deselect_eeprom(void)
65 *port_d_ptr
&= ~(HwPortDEECS
);
66 *port_e_ptr
&= ~(HwPortESepromDIn
);
70 * GetSepromDataPtr - returns pointer to shadow (RAM) copy of seprom
71 * and returns 0 if seprom is not initialized or
72 * has a checksum error.
75 eeprom_struct
* get_seprom_ptr(void)
77 return seprom_data_ptr
;
80 unsigned char* get_eeprom_mac_address(void)
82 return seprom_data_ptr
->variant
.eprom_struct
.mac_Address
;
86 * ReadSProm, Physically reads data from the Serial PROM
88 static void read_sprom(short address
, int length
, eeprom_struct
*buffer
)
90 short data
= COMMAND_READ
| (address
& 0x3F);
96 // Clock in 9 bits of the command
97 for (i
= 0, bit
= 0x100; i
< 9; i
++, bit
>>= 1) {
99 *port_e_ptr
|= HwPortESepromDIn
;
101 *port_e_ptr
&= ~(HwPortESepromDIn
);
103 toggle_seprom_clock();
107 // Now read one or more shorts of data from the Seprom
109 while (length
-- > 0) {
112 // Read 16 bits at a time
113 for (i
= 0; i
< 16; i
++) {
115 toggle_seprom_clock();
116 data
|= *port_e_ptr
& HwPortESepromDOut
;
120 buffer
->variant
.eprom_short_data
[address
++] = data
;
133 * Input: Pointer to array of 64 x 16 Bits
135 * Output: if no problem reading data is filled in
137 static void read_serial_prom(eeprom_struct
*data
)
139 read_sprom(0, 64, data
);
144 // Compute Serial EEPROM checksum
146 // Input: Pointer to struct with Eprom data
148 // Output: The computed Eprom checksum
150 static short compute_seprom_checksum(eeprom_struct
*data
)
155 for (i
= 0; i
< 126; i
++) {
156 checksum
+= (short)data
->variant
.eprom_byte_data
[i
];
159 return((short)(0x5555 - (checksum
& 0xFFFF)));
163 // Make sure the data port bits for the SEPROM are correctly initialised
166 void __init
seprom_init(void)
171 *(char *)(CLPS7111_VIRT_BASE
+ PDDDR
) = 0x0;
172 *(char *)(CLPS7111_VIRT_BASE
+ PDDR
) = 0x15;
175 *(int *)(CLPS7111_VIRT_BASE
+ PEDDR
) = 0x06;
176 *(int *)(CLPS7111_VIRT_BASE
+ PEDR
) = 0x04;
179 // Make sure that EEPROM struct size never exceeds 128 bytes
181 if (sizeof(eeprom_struct
) > 128) {
182 panic("Serial PROM struct size > 128, aborting read\n");
185 read_serial_prom(&seprom_data
);
187 checksum
= compute_seprom_checksum(&seprom_data
);
189 if (checksum
!= seprom_data
.variant
.eprom_short_data
[63]) {
190 panic("Serial EEPROM checksum failed\n");
193 seprom_data_ptr
= &seprom_data
;