[ARM] 2918/1: [update] Base port of Comdial MP1000 platfrom
[safe/jmp/linux-2.6] / arch / arm / mach-clps711x / mp1000-seprom.c
1 /*`
2  * mp1000-seprom.c
3  *
4  *  This file contains the Serial EEPROM code for the MP1000 board
5  *
6  *  Copyright (C) 2005 Comdial Corporation
7  *
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.
12  *
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.
17  *
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
21  *
22  */
23
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>
29
30 /* If SepromInit() can initialize and checksum the seprom successfully, */
31 /* then it will point seprom_data_ptr at the shadow copy.  */
32
33 static eeprom_struct seprom_data;                       /* shadow copy of seprom content */
34
35 eeprom_struct *seprom_data_ptr = 0;             /* 0 => not initialized */
36
37 /*
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
42  */
43
44 static char *port_d_ptr = (char *)(CLPS7111_VIRT_BASE + PDDR);
45 static char *port_e_ptr = (char *)(CLPS7111_VIRT_BASE + PEDR);
46
47 #define NO_OF_SHORTS    64      // Device is 64 x 16 bits
48 #define ENABLE_RW       0
49 #define DISABLE_RW      1
50
51 static inline void toggle_seprom_clock(void)
52 {
53         *port_e_ptr |= HwPortESepromCLK;
54         *port_e_ptr &= ~(HwPortESepromCLK);
55 }
56
57 static inline void select_eeprom(void)
58 {
59         *port_d_ptr |= HwPortDEECS;
60         *port_e_ptr &= ~(HwPortESepromCLK);
61 }
62
63 static inline void deselect_eeprom(void)
64 {
65         *port_d_ptr &= ~(HwPortDEECS);
66         *port_e_ptr &= ~(HwPortESepromDIn);
67 }
68
69 /*
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.
73  */
74
75 eeprom_struct* get_seprom_ptr(void)
76 {
77         return seprom_data_ptr;
78 }
79
80 unsigned char* get_eeprom_mac_address(void)
81 {
82         return seprom_data_ptr->variant.eprom_struct.mac_Address;
83 }
84
85 /*
86  * ReadSProm, Physically reads data from the Serial PROM
87  */
88 static void read_sprom(short address, int length, eeprom_struct *buffer)
89 {
90         short data = COMMAND_READ | (address & 0x3F);
91         short bit;
92         int i;
93
94         select_eeprom();
95
96         // Clock in 9 bits of the command
97         for (i = 0, bit = 0x100; i < 9; i++, bit >>= 1) {
98                 if (data & bit)
99                         *port_e_ptr |= HwPortESepromDIn;
100                 else
101                         *port_e_ptr &= ~(HwPortESepromDIn);
102
103                 toggle_seprom_clock();
104         }
105
106         //
107         // Now read one or more shorts of data from the Seprom
108         //
109         while (length-- > 0) {
110                 data = 0;
111
112                 // Read 16 bits at a time
113                 for (i = 0; i < 16; i++) {
114                         data <<= 1;
115                         toggle_seprom_clock();
116                         data |= *port_e_ptr & HwPortESepromDOut;
117
118                 }
119
120                 buffer->variant.eprom_short_data[address++] = data;
121         }
122
123         deselect_eeprom();
124
125         return;
126 }
127
128
129
130 /*
131  * ReadSerialPROM
132  *
133  * Input: Pointer to array of 64 x 16 Bits
134  *
135  * Output: if no problem reading data is filled in
136  */
137 static void read_serial_prom(eeprom_struct *data)
138 {
139         read_sprom(0, 64, data);
140 }
141
142
143 //
144 // Compute Serial EEPROM checksum
145 //
146 // Input: Pointer to struct with Eprom data
147 //
148 // Output: The computed Eprom checksum
149 //
150 static short compute_seprom_checksum(eeprom_struct *data)
151 {
152         short checksum = 0;
153         int i;
154
155         for (i = 0; i < 126; i++) {
156                 checksum += (short)data->variant.eprom_byte_data[i];
157         }
158
159         return((short)(0x5555 - (checksum & 0xFFFF)));
160 }
161
162 //
163 // Make sure the data port bits for the SEPROM are correctly initialised
164 //
165
166 void __init seprom_init(void)
167 {
168         short checksum;
169
170         // Init Port D
171         *(char *)(CLPS7111_VIRT_BASE + PDDDR) = 0x0;
172         *(char *)(CLPS7111_VIRT_BASE + PDDR) = 0x15;
173
174         // Init Port E
175         *(int *)(CLPS7111_VIRT_BASE + PEDDR) = 0x06;
176         *(int *)(CLPS7111_VIRT_BASE + PEDR) = 0x04;
177
178         //
179         // Make sure that EEPROM struct size never exceeds 128 bytes
180         //
181         if (sizeof(eeprom_struct) > 128) {
182                 panic("Serial PROM struct size > 128, aborting read\n");
183         }
184
185         read_serial_prom(&seprom_data);
186
187         checksum = compute_seprom_checksum(&seprom_data);
188
189         if (checksum != seprom_data.variant.eprom_short_data[63]) {
190                 panic("Serial EEPROM checksum failed\n");
191         }
192
193         seprom_data_ptr = &seprom_data;
194 }
195