Merge tag 'iwlwifi-next-for-kalle-2014-12-30' of https://git.kernel.org/pub/scm/linux...
[cascardo/linux.git] / arch / mips / cavium-octeon / executive / octeon-model.c
1 /***********************license start***************
2  * Author: Cavium Networks
3  *
4  * Contact: support@caviumnetworks.com
5  * This file is part of the OCTEON SDK
6  *
7  * Copyright (c) 2003-2010 Cavium Networks
8  *
9  * This file is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License, Version 2, as
11  * published by the Free Software Foundation.
12  *
13  * This file is distributed in the hope that it will be useful, but
14  * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16  * NONINFRINGEMENT.  See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this file; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22  * or visit http://www.gnu.org/licenses/.
23  *
24  * This file may also be available under a different license from Cavium.
25  * Contact Cavium Networks for more information
26  ***********************license end**************************************/
27
28 #include <asm/octeon/octeon.h>
29
30 /**
31  * Read a byte of fuse data
32  * @byte_addr:   address to read
33  *
34  * Returns fuse value: 0 or 1
35  */
36 static uint8_t __init cvmx_fuse_read_byte(int byte_addr)
37 {
38         union cvmx_mio_fus_rcmd read_cmd;
39
40         read_cmd.u64 = 0;
41         read_cmd.s.addr = byte_addr;
42         read_cmd.s.pend = 1;
43         cvmx_write_csr(CVMX_MIO_FUS_RCMD, read_cmd.u64);
44         while ((read_cmd.u64 = cvmx_read_csr(CVMX_MIO_FUS_RCMD))
45                && read_cmd.s.pend)
46                 ;
47         return read_cmd.s.dat;
48 }
49
50 /*
51  * Version of octeon_model_get_string() that takes buffer as argument,
52  * as running early in u-boot static/global variables don't work when
53  * running from flash.
54  */
55 static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
56                                                          char *buffer)
57 {
58         const char *family;
59         const char *core_model;
60         char pass[4];
61         int clock_mhz;
62         const char *suffix;
63         union cvmx_l2d_fus3 fus3;
64         int num_cores;
65         union cvmx_mio_fus_dat2 fus_dat2;
66         union cvmx_mio_fus_dat3 fus_dat3;
67         char fuse_model[10];
68         uint32_t fuse_data = 0;
69
70         fus3.u64 = 0;
71         if (!OCTEON_IS_MODEL(OCTEON_CN6XXX))
72                 fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3);
73         fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
74         fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3);
75         num_cores = cvmx_pop(cvmx_read_csr(CVMX_CIU_FUSE));
76
77         /* Make sure the non existent devices look disabled */
78         switch ((chip_id >> 8) & 0xff) {
79         case 6:         /* CN50XX */
80         case 2:         /* CN30XX */
81                 fus_dat3.s.nodfa_dte = 1;
82                 fus_dat3.s.nozip = 1;
83                 break;
84         case 4:         /* CN57XX or CN56XX */
85                 fus_dat3.s.nodfa_dte = 1;
86                 break;
87         default:
88                 break;
89         }
90
91         /* Make a guess at the suffix */
92         /* NSP = everything */
93         /* EXP = No crypto */
94         /* SCP = No DFA, No zip */
95         /* CP = No DFA, No crypto, No zip */
96         if (fus_dat3.s.nodfa_dte) {
97                 if (fus_dat2.s.nocrypto)
98                         suffix = "CP";
99                 else
100                         suffix = "SCP";
101         } else if (fus_dat2.s.nocrypto)
102                 suffix = "EXP";
103         else
104                 suffix = "NSP";
105
106         /*
107          * Assume pass number is encoded using <5:3><2:0>. Exceptions
108          * will be fixed later.
109          */
110         sprintf(pass, "%d.%d", (int)((chip_id >> 3) & 7) + 1, (int)chip_id & 7);
111
112         /*
113          * Use the number of cores to determine the last 2 digits of
114          * the model number. There are some exceptions that are fixed
115          * later.
116          */
117         switch (num_cores) {
118         case 32:
119                 core_model = "80";
120                 break;
121         case 24:
122                 core_model = "70";
123                 break;
124         case 16:
125                 core_model = "60";
126                 break;
127         case 15:
128                 core_model = "58";
129                 break;
130         case 14:
131                 core_model = "55";
132                 break;
133         case 13:
134                 core_model = "52";
135                 break;
136         case 12:
137                 core_model = "50";
138                 break;
139         case 11:
140                 core_model = "48";
141                 break;
142         case 10:
143                 core_model = "45";
144                 break;
145         case 9:
146                 core_model = "42";
147                 break;
148         case 8:
149                 core_model = "40";
150                 break;
151         case 7:
152                 core_model = "38";
153                 break;
154         case 6:
155                 core_model = "34";
156                 break;
157         case 5:
158                 core_model = "32";
159                 break;
160         case 4:
161                 core_model = "30";
162                 break;
163         case 3:
164                 core_model = "25";
165                 break;
166         case 2:
167                 core_model = "20";
168                 break;
169         case 1:
170                 core_model = "10";
171                 break;
172         default:
173                 core_model = "XX";
174                 break;
175         }
176
177         /* Now figure out the family, the first two digits */
178         switch ((chip_id >> 8) & 0xff) {
179         case 0:         /* CN38XX, CN37XX or CN36XX */
180                 if (fus3.cn38xx.crip_512k) {
181                         /*
182                          * For some unknown reason, the 16 core one is
183                          * called 37 instead of 36.
184                          */
185                         if (num_cores >= 16)
186                                 family = "37";
187                         else
188                                 family = "36";
189                 } else
190                         family = "38";
191                 /*
192                  * This series of chips didn't follow the standard
193                  * pass numbering.
194                  */
195                 switch (chip_id & 0xf) {
196                 case 0:
197                         strcpy(pass, "1.X");
198                         break;
199                 case 1:
200                         strcpy(pass, "2.X");
201                         break;
202                 case 3:
203                         strcpy(pass, "3.X");
204                         break;
205                 default:
206                         strcpy(pass, "X.X");
207                         break;
208                 }
209                 break;
210         case 1:         /* CN31XX or CN3020 */
211                 if ((chip_id & 0x10) || fus3.cn31xx.crip_128k)
212                         family = "30";
213                 else
214                         family = "31";
215                 /*
216                  * This series of chips didn't follow the standard
217                  * pass numbering.
218                  */
219                 switch (chip_id & 0xf) {
220                 case 0:
221                         strcpy(pass, "1.0");
222                         break;
223                 case 2:
224                         strcpy(pass, "1.1");
225                         break;
226                 default:
227                         strcpy(pass, "X.X");
228                         break;
229                 }
230                 break;
231         case 2:         /* CN3010 or CN3005 */
232                 family = "30";
233                 /* A chip with half cache is an 05 */
234                 if (fus3.cn30xx.crip_64k)
235                         core_model = "05";
236                 /*
237                  * This series of chips didn't follow the standard
238                  * pass numbering.
239                  */
240                 switch (chip_id & 0xf) {
241                 case 0:
242                         strcpy(pass, "1.0");
243                         break;
244                 case 2:
245                         strcpy(pass, "1.1");
246                         break;
247                 default:
248                         strcpy(pass, "X.X");
249                         break;
250                 }
251                 break;
252         case 3:         /* CN58XX */
253                 family = "58";
254                 /* Special case. 4 core, half cache (CP with half cache) */
255                 if ((num_cores == 4) && fus3.cn58xx.crip_1024k && !strncmp(suffix, "CP", 2))
256                         core_model = "29";
257
258                 /* Pass 1 uses different encodings for pass numbers */
259                 if ((chip_id & 0xFF) < 0x8) {
260                         switch (chip_id & 0x3) {
261                         case 0:
262                                 strcpy(pass, "1.0");
263                                 break;
264                         case 1:
265                                 strcpy(pass, "1.1");
266                                 break;
267                         case 3:
268                                 strcpy(pass, "1.2");
269                                 break;
270                         default:
271                                 strcpy(pass, "1.X");
272                                 break;
273                         }
274                 }
275                 break;
276         case 4:         /* CN57XX, CN56XX, CN55XX, CN54XX */
277                 if (fus_dat2.cn56xx.raid_en) {
278                         if (fus3.cn56xx.crip_1024k)
279                                 family = "55";
280                         else
281                                 family = "57";
282                         if (fus_dat2.cn56xx.nocrypto)
283                                 suffix = "SP";
284                         else
285                                 suffix = "SSP";
286                 } else {
287                         if (fus_dat2.cn56xx.nocrypto)
288                                 suffix = "CP";
289                         else {
290                                 suffix = "NSP";
291                                 if (fus_dat3.s.nozip)
292                                         suffix = "SCP";
293
294                                 if (fus_dat3.s.bar2_en)
295                                         suffix = "NSPB2";
296                         }
297                         if (fus3.cn56xx.crip_1024k)
298                                 family = "54";
299                         else
300                                 family = "56";
301                 }
302                 break;
303         case 6:         /* CN50XX */
304                 family = "50";
305                 break;
306         case 7:         /* CN52XX */
307                 if (fus3.cn52xx.crip_256k)
308                         family = "51";
309                 else
310                         family = "52";
311                 break;
312         case 0x93:              /* CN61XX */
313                 family = "61";
314                 if (fus_dat2.cn61xx.nocrypto && fus_dat2.cn61xx.dorm_crypto)
315                         suffix = "AP";
316                 if (fus_dat2.cn61xx.nocrypto)
317                         suffix = "CP";
318                 else if (fus_dat2.cn61xx.dorm_crypto)
319                         suffix = "DAP";
320                 else if (fus_dat3.cn61xx.nozip)
321                         suffix = "SCP";
322                 break;
323         case 0x90:              /* CN63XX */
324                 family = "63";
325                 if (fus_dat3.s.l2c_crip == 2)
326                         family = "62";
327                 if (num_cores == 6)     /* Other core counts match generic */
328                         core_model = "35";
329                 if (fus_dat2.cn63xx.nocrypto)
330                         suffix = "CP";
331                 else if (fus_dat2.cn63xx.dorm_crypto)
332                         suffix = "DAP";
333                 else if (fus_dat3.cn63xx.nozip)
334                         suffix = "SCP";
335                 else
336                         suffix = "AAP";
337                 break;
338         case 0x92:              /* CN66XX */
339                 family = "66";
340                 if (num_cores == 6)     /* Other core counts match generic */
341                         core_model = "35";
342                 if (fus_dat2.cn66xx.nocrypto && fus_dat2.cn66xx.dorm_crypto)
343                         suffix = "AP";
344                 if (fus_dat2.cn66xx.nocrypto)
345                         suffix = "CP";
346                 else if (fus_dat2.cn66xx.dorm_crypto)
347                         suffix = "DAP";
348                 else if (fus_dat3.cn66xx.nozip)
349                         suffix = "SCP";
350                 else
351                         suffix = "AAP";
352                 break;
353         case 0x91:              /* CN68XX */
354                 family = "68";
355                 if (fus_dat2.cn68xx.nocrypto && fus_dat3.cn68xx.nozip)
356                         suffix = "CP";
357                 else if (fus_dat2.cn68xx.dorm_crypto)
358                         suffix = "DAP";
359                 else if (fus_dat3.cn68xx.nozip)
360                         suffix = "SCP";
361                 else if (fus_dat2.cn68xx.nocrypto)
362                         suffix = "SP";
363                 else
364                         suffix = "AAP";
365                 break;
366         default:
367                 family = "XX";
368                 core_model = "XX";
369                 strcpy(pass, "X.X");
370                 suffix = "XXX";
371                 break;
372         }
373
374         clock_mhz = octeon_get_clock_rate() / 1000000;
375         if (family[0] != '3') {
376                 int fuse_base = 384 / 8;
377                 if (family[0] == '6')
378                         fuse_base = 832 / 8;
379
380                 /* Check for model in fuses, overrides normal decode */
381                 /* This is _not_ valid for Octeon CN3XXX models */
382                 fuse_data |= cvmx_fuse_read_byte(fuse_base + 3);
383                 fuse_data = fuse_data << 8;
384                 fuse_data |= cvmx_fuse_read_byte(fuse_base + 2);
385                 fuse_data = fuse_data << 8;
386                 fuse_data |= cvmx_fuse_read_byte(fuse_base + 1);
387                 fuse_data = fuse_data << 8;
388                 fuse_data |= cvmx_fuse_read_byte(fuse_base);
389                 if (fuse_data & 0x7ffff) {
390                         int model = fuse_data & 0x3fff;
391                         int suffix = (fuse_data >> 14) & 0x1f;
392                         if (suffix && model) {
393                                 /* Have both number and suffix in fuses, so both */
394                                 sprintf(fuse_model, "%d%c", model, 'A' + suffix - 1);
395                                 core_model = "";
396                                 family = fuse_model;
397                         } else if (suffix && !model) {
398                                 /* Only have suffix, so add suffix to 'normal' model number */
399                                 sprintf(fuse_model, "%s%c", core_model, 'A' + suffix - 1);
400                                 core_model = fuse_model;
401                         } else {
402                                 /* Don't have suffix, so just use model from fuses */
403                                 sprintf(fuse_model, "%d", model);
404                                 core_model = "";
405                                 family = fuse_model;
406                         }
407                 }
408         }
409         sprintf(buffer, "CN%s%sp%s-%d-%s", family, core_model, pass, clock_mhz, suffix);
410         return buffer;
411 }
412
413 /**
414  * Given the chip processor ID from COP0, this function returns a
415  * string representing the chip model number. The string is of the
416  * form CNXXXXpX.X-FREQ-SUFFIX.
417  * - XXXX = The chip model number
418  * - X.X = Chip pass number
419  * - FREQ = Current frequency in Mhz
420  * - SUFFIX = NSP, EXP, SCP, SSP, or CP
421  *
422  * @chip_id: Chip ID
423  *
424  * Returns Model string
425  */
426 const char *__init octeon_model_get_string(uint32_t chip_id)
427 {
428         static char buffer[32];
429         return octeon_model_get_string_buffer(chip_id, buffer);
430 }