]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/cxt1e1/hwprobe.c
Merge branch 'uprobes/core' of git://git.kernel.org/pub/scm/linux/kernel/git/oleg...
[karo-tx-linux.git] / drivers / staging / cxt1e1 / hwprobe.c
1 /* Copyright (C) 2007  One Stop Systems
2  * Copyright (C) 2003-2005  SBE, Inc.
3  *
4  *   This program is free software; you can redistribute it and/or modify
5  *   it under the terms of the GNU General Public License as published by
6  *   the Free Software Foundation; either version 2 of the License, or
7  *   (at your option) any later version.
8  *
9  *   This program is distributed in the hope that it will be useful,
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *   GNU General Public License for more details.
13  */
14
15 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
16
17 #include <linux/netdevice.h>
18 #include <linux/hdlc.h>
19 #include <linux/if_arp.h>
20 #include <asm/uaccess.h>
21 #include <linux/rtnetlink.h>
22 #include <linux/pci.h>
23 #include "pmcc4_sysdep.h"
24 #include "sbecom_inline_linux.h"
25 #include "libsbew.h"
26 #include "pmcc4_private.h"
27 #include "pmcc4.h"
28 #include "pmcc4_ioctls.h"
29 #include "pmc93x6_eeprom.h"
30 #ifdef CONFIG_PROC_FS
31 #include "sbeproc.h"
32 #endif
33
34 extern int  error_flag;
35 extern int  drvr_state;
36
37 /* forward references */
38 void        c4_stopwd(ci_t *);
39 struct net_device * __init c4_add_dev(hdw_info_t *, int, unsigned long,
40                                       unsigned long, int, int);
41
42
43 struct s_hdw_info hdw_info[MAX_BOARDS];
44
45
46 void __init
47 show_two(hdw_info_t *hi, int brdno)
48 {
49         ci_t       *ci;
50         struct pci_dev *pdev;
51         char       *bid;
52         char       banner[80];
53         char    sn[6] = {0,};
54
55         ci = (ci_t *)(netdev_priv(hi->ndev));
56         bid = sbeid_get_bdname(ci);
57         switch (hi->promfmt) {
58         case PROM_FORMAT_TYPE1:
59                 memcpy(sn, hi->mfg_info.pft1.Serial, 6);
60                 break;
61         case PROM_FORMAT_TYPE2:
62                 memcpy(sn, hi->mfg_info.pft2.Serial, 6);
63                 break;
64         }
65
66         sprintf(banner, "%s: %s  S/N %06X, MUSYCC Rev %02X",
67                 hi->devname, bid,
68                 ((sn[3] << 16) & 0xff0000) |
69                 ((sn[4] << 8) & 0x00ff00) |
70                 (sn[5] & 0x0000ff),
71                 (u_int8_t) hi->revid[0]);
72
73         pr_info("%s\n", banner);
74
75         pdev = hi->pdev[0];
76         pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
77                 hi->devname, "MUSYCC",
78                 (unsigned long) hi->addr_mapped[0], hi->addr[0],
79                 hi->pci_busno, (u_int8_t) PCI_SLOT(pdev->devfn),
80                 (u_int8_t) PCI_FUNC(pdev->devfn), pdev->irq);
81
82         pdev = hi->pdev[1];
83         pr_info("%s: %s at v/p=%lx/%lx (%02x:%02x.%x) irq %d\n",
84                 hi->devname, "EBUS  ",
85                 (unsigned long) hi->addr_mapped[1], hi->addr[1],
86                 hi->pci_busno, (u_int8_t) PCI_SLOT(pdev->devfn),
87                 (u_int8_t) PCI_FUNC(pdev->devfn), pdev->irq);
88 }
89
90
91 void __init
92 hdw_sn_get(hdw_info_t *hi, int brdno)
93 {
94         /* obtain hardware EEPROM information */
95         long        addr;
96
97         addr = (long) hi->addr_mapped[1] + EEPROM_OFFSET;
98
99         /* read EEPROM with largest known format size... */
100         pmc_eeprom_read_buffer(addr, 0, (char *)hi->mfg_info.data,
101                                sizeof(FLD_TYPE2));
102
103 #if 0
104         {
105                 unsigned char *ucp = (unsigned char *) &hi->mfg_info.data;
106
107                 pr_info("eeprom[00]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
108                         *(ucp + 0), *(ucp + 1), *(ucp + 2), *(ucp + 3),
109                         *(ucp + 4), *(ucp + 5), *(ucp + 6), *(ucp + 7));
110                 pr_info("eeprom[08]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
111                         *(ucp + 8), *(ucp + 9), *(ucp + 10), *(ucp + 11),
112                         *(ucp + 12), *(ucp + 13), *(ucp + 14), *(ucp + 15));
113                 pr_info("eeprom[16]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
114                         *(ucp + 16), *(ucp + 17), *(ucp + 18), *(ucp + 19),
115                         *(ucp + 20), *(ucp + 21), *(ucp + 22), *(ucp + 23));
116                 pr_info("eeprom[24]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
117                         *(ucp + 24), *(ucp + 25), *(ucp + 26), *(ucp + 27),
118                         *(ucp + 28), *(ucp + 29), *(ucp + 30), *(ucp + 31));
119                 pr_info("eeprom[32]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
120                         *(ucp + 32), *(ucp + 33), *(ucp + 34), *(ucp + 35),
121                         *(ucp + 36), *(ucp + 37), *(ucp + 38), *(ucp + 39));
122                 pr_info("eeprom[40]:  %02x %02x %02x %02x  %02x %02x %02x %02x\n",
123                         *(ucp + 40), *(ucp + 41), *(ucp + 42), *(ucp + 43),
124                         *(ucp + 44), *(ucp + 45), *(ucp + 46), *(ucp + 47));
125         }
126 #endif
127 #if 0
128         pr_info("sn: %x %x %x %x %x %x\n",
129                         hi->mfg_info.Serial[0],
130                         hi->mfg_info.Serial[1],
131                         hi->mfg_info.Serial[2],
132                         hi->mfg_info.Serial[3],
133                         hi->mfg_info.Serial[4],
134                         hi->mfg_info.Serial[5]);
135 #endif
136
137         hi->promfmt = pmc_verify_cksum(&hi->mfg_info.data);
138         if (hi->promfmt == PROM_FORMAT_Unk) {
139                 /* bad crc, data is suspect */
140                 if (cxt1e1_log_level >= LOG_WARN)
141                         pr_info("%s: EEPROM cksum error\n", hi->devname);
142                 hi->mfg_info_sts = EEPROM_CRCERR;
143         } else
144                 hi->mfg_info_sts = EEPROM_OK;
145 }
146
147
148         void __init
149 prep_hdw_info(void)
150 {
151         hdw_info_t *hi;
152         int         i;
153
154         for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
155                 hi->pci_busno = 0xff;
156                 hi->pci_slot = 0xff;
157                 hi->pci_pin[0] = 0;
158                 hi->pci_pin[1] = 0;
159                 hi->ndev = NULL;
160                 hi->addr[0] = 0L;
161                 hi->addr[1] = 0L;
162                 hi->addr_mapped[0] = 0L;
163                 hi->addr_mapped[1] = 0L;
164         }
165 }
166
167 void
168 cleanup_ioremap(void)
169 {
170         hdw_info_t *hi;
171         int         i;
172
173         for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
174                 if (hi->pci_slot == 0xff)
175                         break;
176                 if (hi->addr_mapped[0]) {
177                         iounmap((void *)(hi->addr_mapped[0]));
178                         release_mem_region((long) hi->addr[0], hi->len[0]);
179                         hi->addr_mapped[0] = 0;
180                 }
181                 if (hi->addr_mapped[1]) {
182                         iounmap((void *)(hi->addr_mapped[1]));
183                         release_mem_region((long) hi->addr[1], hi->len[1]);
184                         hi->addr_mapped[1] = 0;
185                 }
186         }
187 }
188
189
190 void
191 cleanup_devs(void)
192 {
193         hdw_info_t *hi;
194         int         i;
195
196         for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
197                 if (hi->pci_slot == 0xff || !hi->ndev)
198                         break;
199                 c4_stopwd(netdev_priv(hi->ndev));
200 #ifdef CONFIG_PROC_FS
201                 sbecom_proc_brd_cleanup(netdev_priv(hi->ndev));
202 #endif
203                 unregister_netdev(hi->ndev);
204                 free_irq(hi->pdev[0]->irq, hi->ndev);
205 #ifdef CONFIG_SBE_PMCC4_NCOMM
206                 free_irq(hi->pdev[1]->irq, hi->ndev);
207 #endif
208                 OS_kfree(hi->ndev);
209         }
210 }
211
212
213 static int  __init
214 c4_hdw_init(struct pci_dev *pdev, int found)
215 {
216         hdw_info_t *hi;
217         int         i;
218         int         fun, slot;
219         unsigned char busno = 0xff;
220
221         /* our MUSYCC chip supports two functions, 0 & 1 */
222         fun = PCI_FUNC(pdev->devfn);
223         if (fun > 1) {
224                 pr_warning("unexpected devfun: 0x%x\n", pdev->devfn);
225                 return 0;
226         }
227
228         /* obtain bus number */
229         if (pdev->bus)
230                 busno = pdev->bus->number;
231         else
232                 busno = 0; /* default for system PCI inconsistency */
233         slot = pdev->devfn & ~0x07;
234
235         /*
236          * Functions 0 & 1 for a given board (identified by same bus(busno) and
237          * slot(slot)) are placed into the same 'hardware' structure.  The first
238          * part of the board's functionality will be placed into an unpopulated
239          * element, identified by "slot==(0xff)".  The second part of a board's
240          * functionality will match the previously loaded slot/busno.
241          */
242         for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
243                 /*
244                  * match with board's first found interface, otherwise this is
245                  * fisrt found
246                  */
247                 if ((hi->pci_slot == 0xff) ||   /* new board */
248                     ((hi->pci_slot == slot) && (hi->bus == pdev->bus)))
249                         break;                  /* found for-loop exit */
250         }
251
252         /* no match in above loop means MAX exceeded */
253         if (i == MAX_BOARDS) {
254                 pr_warning("exceeded number of allowed devices (>%d)?\n",
255                            MAX_BOARDS);
256                 return 0;
257         }
258
259         if (pdev->bus)
260                 hi->pci_busno = pdev->bus->number;
261         else
262                 hi->pci_busno = 0; /* default for system PCI inconsistency */
263
264         hi->pci_slot = slot;
265         pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &hi->pci_pin[fun]);
266         pci_read_config_byte(pdev, PCI_REVISION_ID, &hi->revid[fun]);
267         hi->bus = pdev->bus;
268         hi->addr[fun] = pci_resource_start(pdev, 0);
269         hi->len[fun] = pci_resource_end(pdev, 0) - hi->addr[fun] + 1;
270         hi->pdev[fun] = pdev;
271
272         {
273                 /*
274                  * create device name from module name, plus add the appropriate
275                  * board number
276                  */
277                 char       *cp = hi->devname;
278
279                 strcpy(cp, KBUILD_MODNAME);
280                 cp += strlen(cp);          /* reposition */
281                 *cp++ = '-';
282                 *cp++ = '0' + (found / 2);  /* there are two found interfaces per
283                 * board */
284                 *cp = 0;                    /* termination */
285         }
286
287         return 1;
288 }
289
290 status_t __init
291 c4hw_attach_all(void)
292 {
293         hdw_info_t *hi;
294         struct pci_dev *pdev = NULL;
295         int         found = 0, i, j;
296
297         error_flag = 0;
298         prep_hdw_info();
299         /*** scan PCI bus for all possible boards */
300         while ((pdev = pci_get_device(PCI_VENDOR_ID_CONEXANT,
301                                       PCI_DEVICE_ID_CN8474,
302                                       pdev))) {
303                 if (c4_hdw_init(pdev, found))
304                         found++;
305         }
306
307         if (!found) {
308                 pr_warning("No boards found\n");
309                 return -ENODEV;
310         }
311
312         /* sanity check for consistent hardware found */
313         for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
314                 if (hi->pci_slot != 0xff && (!hi->addr[0] || !hi->addr[1])) {
315                         pr_warning("%s: something very wrong with pci_get_device\n",
316                                    hi->devname);
317                         return -EIO;
318                 }
319         }
320         /* bring board's memory regions on/line */
321         for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
322                 if (hi->pci_slot == 0xff)
323                         break;
324                 for (j = 0; j < 2; j++) {
325                         if (!request_mem_region(hi->addr[j], hi->len[j], hi->devname)) {
326                                 pr_warning("%s: memory in use, addr=0x%lx, len=0x%lx ?\n",
327                                            hi->devname, hi->addr[j], hi->len[j]);
328                                 cleanup_ioremap();
329                                 return -ENOMEM;
330                         }
331
332                         hi->addr_mapped[j] = (unsigned long)ioremap(hi->addr[j], hi->len[j]);
333                         if (!hi->addr_mapped[j]) {
334                                 pr_warning("%s: ioremap fails, addr=0x%lx, len=0x%lx ?\n",
335                                            hi->devname, hi->addr[j], hi->len[j]);
336                                 cleanup_ioremap();
337                                 return -ENOMEM;
338                         }
339 #ifdef SBE_MAP_DEBUG
340                         pr_warning("%s: io remapped from phys %x to virt %x\n",
341                                    hi->devname, (u_int32_t) hi->addr[j],
342                                    (u_int32_t) hi->addr_mapped[j]);
343 #endif
344                 }
345         }
346
347         drvr_state = SBE_DRVR_AVAILABLE;
348
349         /* Have now memory mapped all boards.  Now allow board's access to system */
350         for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++) {
351                 if (hi->pci_slot == 0xff)
352                         break;
353                 if (pci_enable_device(hi->pdev[0]) ||
354                     pci_enable_device(hi->pdev[1])) {
355                         drvr_state = SBE_DRVR_DOWN;
356                         pr_warning("%s: failed to enable card %d slot %d\n",
357                                    hi->devname, i, hi->pci_slot);
358                         cleanup_devs();
359                         cleanup_ioremap();
360                         return -EIO;
361                 }
362                 pci_set_master(hi->pdev[0]);
363                 pci_set_master(hi->pdev[1]);
364                 hi->ndev = c4_add_dev(hi, i, (long) hi->addr_mapped[0],
365                                       (long) hi->addr_mapped[1],
366                                       hi->pdev[0]->irq,
367                                       hi->pdev[1]->irq);
368                 if (!hi->ndev) {
369                         drvr_state = SBE_DRVR_DOWN;
370                         cleanup_ioremap();
371                         /* NOTE: c4_add_dev() does its own device cleanup */
372 #if 0
373                         cleanup_devs();
374 #endif
375                         return error_flag; /* error_flag set w/in add_dev() */
376                 }
377                 show_two(hi, i); /* displays found information */
378         }
379         return 0;
380 }
381
382 /***  End-of-File  ***/