~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/alpha/kernel/core_lca.c

Version: ~ [ linux-5.11 ] ~ [ linux-5.10.17 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.99 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.176 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.221 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.257 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.257 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *      linux/arch/alpha/kernel/core_lca.c
  3  *
  4  * Written by David Mosberger (davidm@cs.arizona.edu) with some code
  5  * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
  6  * bios code.
  7  *
  8  * Code common to all LCA core logic chips.
  9  */
 10 
 11 #define __EXTERN_INLINE inline
 12 #include <asm/io.h>
 13 #include <asm/core_lca.h>
 14 #undef __EXTERN_INLINE
 15 
 16 #include <linux/types.h>
 17 #include <linux/pci.h>
 18 #include <linux/init.h>
 19 #include <linux/tty.h>
 20 
 21 #include <asm/ptrace.h>
 22 #include <asm/irq_regs.h>
 23 #include <asm/smp.h>
 24 
 25 #include "proto.h"
 26 #include "pci_impl.h"
 27 
 28 
 29 /*
 30  * BIOS32-style PCI interface:
 31  */
 32 
 33 /*
 34  * Machine check reasons.  Defined according to PALcode sources
 35  * (osf.h and platform.h).
 36  */
 37 #define MCHK_K_TPERR            0x0080
 38 #define MCHK_K_TCPERR           0x0082
 39 #define MCHK_K_HERR             0x0084
 40 #define MCHK_K_ECC_C            0x0086
 41 #define MCHK_K_ECC_NC           0x0088
 42 #define MCHK_K_UNKNOWN          0x008A
 43 #define MCHK_K_CACKSOFT         0x008C
 44 #define MCHK_K_BUGCHECK         0x008E
 45 #define MCHK_K_OS_BUGCHECK      0x0090
 46 #define MCHK_K_DCPERR           0x0092
 47 #define MCHK_K_ICPERR           0x0094
 48 
 49 
 50 /*
 51  * Platform-specific machine-check reasons:
 52  */
 53 #define MCHK_K_SIO_SERR         0x204   /* all platforms so far */
 54 #define MCHK_K_SIO_IOCHK        0x206   /* all platforms so far */
 55 #define MCHK_K_DCSR             0x208   /* all but Noname */
 56 
 57 
 58 /*
 59  * Given a bus, device, and function number, compute resulting
 60  * configuration space address and setup the LCA_IOC_CONF register
 61  * accordingly.  It is therefore not safe to have concurrent
 62  * invocations to configuration space access routines, but there
 63  * really shouldn't be any need for this.
 64  *
 65  * Type 0:
 66  *
 67  *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
 68  *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
 69  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 70  * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0|
 71  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 72  *
 73  *      31:11   Device select bit.
 74  *      10:8    Function number
 75  *       7:2    Register number
 76  *
 77  * Type 1:
 78  *
 79  *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
 80  *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
 81  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 82  * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
 83  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 84  *
 85  *      31:24   reserved
 86  *      23:16   bus number (8 bits = 128 possible buses)
 87  *      15:11   Device number (5 bits)
 88  *      10:8    function number
 89  *       7:2    register number
 90  *  
 91  * Notes:
 92  *      The function number selects which function of a multi-function device 
 93  *      (e.g., SCSI and Ethernet).
 94  * 
 95  *      The register selects a DWORD (32 bit) register offset.  Hence it
 96  *      doesn't get shifted by 2 bits as we want to "drop" the bottom two
 97  *      bits.
 98  */
 99 
100 static int
101 mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
102              unsigned long *pci_addr)
103 {
104         unsigned long addr;
105         u8 bus = pbus->number;
106 
107         if (bus == 0) {
108                 int device = device_fn >> 3;
109                 int func = device_fn & 0x7;
110 
111                 /* Type 0 configuration cycle.  */
112 
113                 if (device > 12) {
114                         return -1;
115                 }
116 
117                 *(vulp)LCA_IOC_CONF = 0;
118                 addr = (1 << (11 + device)) | (func << 8) | where;
119         } else {
120                 /* Type 1 configuration cycle.  */
121                 *(vulp)LCA_IOC_CONF = 1;
122                 addr = (bus << 16) | (device_fn << 8) | where;
123         }
124         *pci_addr = addr;
125         return 0;
126 }
127 
128 static unsigned int
129 conf_read(unsigned long addr)
130 {
131         unsigned long flags, code, stat0;
132         unsigned int value;
133 
134         local_irq_save(flags);
135 
136         /* Reset status register to avoid loosing errors.  */
137         stat0 = *(vulp)LCA_IOC_STAT0;
138         *(vulp)LCA_IOC_STAT0 = stat0;
139         mb();
140 
141         /* Access configuration space.  */
142         value = *(vuip)addr;
143         draina();
144 
145         stat0 = *(vulp)LCA_IOC_STAT0;
146         if (stat0 & LCA_IOC_STAT0_ERR) {
147                 code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
148                         & LCA_IOC_STAT0_CODE_MASK);
149                 if (code != 1) {
150                         printk("lca.c:conf_read: got stat0=%lx\n", stat0);
151                 }
152 
153                 /* Reset error status.  */
154                 *(vulp)LCA_IOC_STAT0 = stat0;
155                 mb();
156 
157                 /* Reset machine check.  */
158                 wrmces(0x7);
159 
160                 value = 0xffffffff;
161         }
162         local_irq_restore(flags);
163         return value;
164 }
165 
166 static void
167 conf_write(unsigned long addr, unsigned int value)
168 {
169         unsigned long flags, code, stat0;
170 
171         local_irq_save(flags);  /* avoid getting hit by machine check */
172 
173         /* Reset status register to avoid loosing errors.  */
174         stat0 = *(vulp)LCA_IOC_STAT0;
175         *(vulp)LCA_IOC_STAT0 = stat0;
176         mb();
177 
178         /* Access configuration space.  */
179         *(vuip)addr = value;
180         draina();
181 
182         stat0 = *(vulp)LCA_IOC_STAT0;
183         if (stat0 & LCA_IOC_STAT0_ERR) {
184                 code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
185                         & LCA_IOC_STAT0_CODE_MASK);
186                 if (code != 1) {
187                         printk("lca.c:conf_write: got stat0=%lx\n", stat0);
188                 }
189 
190                 /* Reset error status.  */
191                 *(vulp)LCA_IOC_STAT0 = stat0;
192                 mb();
193 
194                 /* Reset machine check. */
195                 wrmces(0x7);
196         }
197         local_irq_restore(flags);
198 }
199 
200 static int
201 lca_read_config(struct pci_bus *bus, unsigned int devfn, int where,
202                 int size, u32 *value)
203 {
204         unsigned long addr, pci_addr;
205         long mask;
206         int shift;
207 
208         if (mk_conf_addr(bus, devfn, where, &pci_addr))
209                 return PCIBIOS_DEVICE_NOT_FOUND;
210 
211         shift = (where & 3) * 8;
212         mask = (size - 1) * 8;
213         addr = (pci_addr << 5) + mask + LCA_CONF;
214         *value = conf_read(addr) >> (shift);
215         return PCIBIOS_SUCCESSFUL;
216 }
217 
218 static int 
219 lca_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
220                  u32 value)
221 {
222         unsigned long addr, pci_addr;
223         long mask;
224 
225         if (mk_conf_addr(bus, devfn, where, &pci_addr))
226                 return PCIBIOS_DEVICE_NOT_FOUND;
227 
228         mask = (size - 1) * 8;
229         addr = (pci_addr << 5) + mask + LCA_CONF;
230         conf_write(addr, value << ((where & 3) * 8));
231         return PCIBIOS_SUCCESSFUL;
232 }
233 
234 struct pci_ops lca_pci_ops = 
235 {
236         .read =         lca_read_config,
237         .write =        lca_write_config,
238 };
239 
240 void
241 lca_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
242 {
243         wmb();
244         *(vulp)LCA_IOC_TBIA = 0;
245         mb();
246 }
247 
248 void __init
249 lca_init_arch(void)
250 {
251         struct pci_controller *hose;
252 
253         /*
254          * Create our single hose.
255          */
256 
257         pci_isa_hose = hose = alloc_pci_controller();
258         hose->io_space = &ioport_resource;
259         hose->mem_space = &iomem_resource;
260         hose->index = 0;
261 
262         hose->sparse_mem_base = LCA_SPARSE_MEM - IDENT_ADDR;
263         hose->dense_mem_base = LCA_DENSE_MEM - IDENT_ADDR;
264         hose->sparse_io_base = LCA_IO - IDENT_ADDR;
265         hose->dense_io_base = 0;
266 
267         /*
268          * Set up the PCI to main memory translation windows.
269          *
270          * Mimic the SRM settings for the direct-map window.
271          *   Window 0 is scatter-gather 8MB at 8MB (for isa).
272          *   Window 1 is direct access 1GB at 1GB.
273          *
274          * Note that we do not try to save any of the DMA window CSRs
275          * before setting them, since we cannot read those CSRs on LCA.
276          */
277         hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
278         hose->sg_pci = NULL;
279         __direct_map_base = 0x40000000;
280         __direct_map_size = 0x40000000;
281 
282         *(vulp)LCA_IOC_W_BASE0 = hose->sg_isa->dma_base | (3UL << 32);
283         *(vulp)LCA_IOC_W_MASK0 = (hose->sg_isa->size - 1) & 0xfff00000;
284         *(vulp)LCA_IOC_T_BASE0 = virt_to_phys(hose->sg_isa->ptes);
285 
286         *(vulp)LCA_IOC_W_BASE1 = __direct_map_base | (2UL << 32);
287         *(vulp)LCA_IOC_W_MASK1 = (__direct_map_size - 1) & 0xfff00000;
288         *(vulp)LCA_IOC_T_BASE1 = 0;
289 
290         *(vulp)LCA_IOC_TB_ENA = 0x80;
291 
292         lca_pci_tbi(hose, 0, -1);
293 
294         /*
295          * Disable PCI parity for now.  The NCR53c810 chip has
296          * troubles meeting the PCI spec which results in
297          * data parity errors.
298          */
299         *(vulp)LCA_IOC_PAR_DIS = 1UL<<5;
300 
301         /*
302          * Finally, set up for restoring the correct HAE if using SRM.
303          * Again, since we cannot read many of the CSRs on the LCA,
304          * one of which happens to be the HAE, we save the value that
305          * the SRM will expect...
306          */
307         if (alpha_using_srm)
308                 srm_hae = 0x80000000UL;
309 }
310 
311 /*
312  * Constants used during machine-check handling.  I suppose these
313  * could be moved into lca.h but I don't see much reason why anybody
314  * else would want to use them.
315  */
316 
317 #define ESR_EAV         (1UL<< 0)       /* error address valid */
318 #define ESR_CEE         (1UL<< 1)       /* correctable error */
319 #define ESR_UEE         (1UL<< 2)       /* uncorrectable error */
320 #define ESR_WRE         (1UL<< 3)       /* write-error */
321 #define ESR_SOR         (1UL<< 4)       /* error source */
322 #define ESR_CTE         (1UL<< 7)       /* cache-tag error */
323 #define ESR_MSE         (1UL<< 9)       /* multiple soft errors */
324 #define ESR_MHE         (1UL<<10)       /* multiple hard errors */
325 #define ESR_NXM         (1UL<<12)       /* non-existent memory */
326 
327 #define IOC_ERR         (  1<<4)        /* ioc logs an error */
328 #define IOC_CMD_SHIFT   0
329 #define IOC_CMD         (0xf<<IOC_CMD_SHIFT)
330 #define IOC_CODE_SHIFT  8
331 #define IOC_CODE        (0xf<<IOC_CODE_SHIFT)
332 #define IOC_LOST        (  1<<5)
333 #define IOC_P_NBR       ((__u32) ~((1<<13) - 1))
334 
335 static void
336 mem_error(unsigned long esr, unsigned long ear)
337 {
338         printk("    %s %s error to %s occurred at address %x\n",
339                ((esr & ESR_CEE) ? "Correctable" :
340                 (esr & ESR_UEE) ? "Uncorrectable" : "A"),
341                (esr & ESR_WRE) ? "write" : "read",
342                (esr & ESR_SOR) ? "memory" : "b-cache",
343                (unsigned) (ear & 0x1ffffff8));
344         if (esr & ESR_CTE) {
345                 printk("    A b-cache tag parity error was detected.\n");
346         }
347         if (esr & ESR_MSE) {
348                 printk("    Several other correctable errors occurred.\n");
349         }
350         if (esr & ESR_MHE) {
351                 printk("    Several other uncorrectable errors occurred.\n");
352         }
353         if (esr & ESR_NXM) {
354                 printk("    Attempted to access non-existent memory.\n");
355         }
356 }
357 
358 static void
359 ioc_error(__u32 stat0, __u32 stat1)
360 {
361         static const char * const pci_cmd[] = {
362                 "Interrupt Acknowledge", "Special", "I/O Read", "I/O Write",
363                 "Rsvd 1", "Rsvd 2", "Memory Read", "Memory Write", "Rsvd3",
364                 "Rsvd4", "Configuration Read", "Configuration Write",
365                 "Memory Read Multiple", "Dual Address", "Memory Read Line",
366                 "Memory Write and Invalidate"
367         };
368         static const char * const err_name[] = {
369                 "exceeded retry limit", "no device", "bad data parity",
370                 "target abort", "bad address parity", "page table read error",
371                 "invalid page", "data error"
372         };
373         unsigned code = (stat0 & IOC_CODE) >> IOC_CODE_SHIFT;
374         unsigned cmd  = (stat0 & IOC_CMD)  >> IOC_CMD_SHIFT;
375 
376         printk("    %s initiated PCI %s cycle to address %x"
377                " failed due to %s.\n",
378                code > 3 ? "PCI" : "CPU", pci_cmd[cmd], stat1, err_name[code]);
379 
380         if (code == 5 || code == 6) {
381                 printk("    (Error occurred at PCI memory address %x.)\n",
382                        (stat0 & ~IOC_P_NBR));
383         }
384         if (stat0 & IOC_LOST) {
385                 printk("    Other PCI errors occurred simultaneously.\n");
386         }
387 }
388 
389 void
390 lca_machine_check(unsigned long vector, unsigned long la_ptr)
391 {
392         const char * reason;
393         union el_lca el;
394 
395         el.c = (struct el_common *) la_ptr;
396 
397         wrmces(rdmces());       /* reset machine check pending flag */
398 
399         printk(KERN_CRIT "LCA machine check: vector=%#lx pc=%#lx code=%#x\n",
400                vector, get_irq_regs()->pc, (unsigned int) el.c->code);
401 
402         /*
403          * The first quadword after the common header always seems to
404          * be the machine check reason---don't know why this isn't
405          * part of the common header instead.  In the case of a long
406          * logout frame, the upper 32 bits is the machine check
407          * revision level, which we ignore for now.
408          */
409         switch ((unsigned int) el.c->code) {
410         case MCHK_K_TPERR:      reason = "tag parity error"; break;
411         case MCHK_K_TCPERR:     reason = "tag control parity error"; break;
412         case MCHK_K_HERR:       reason = "access to non-existent memory"; break;
413         case MCHK_K_ECC_C:      reason = "correctable ECC error"; break;
414         case MCHK_K_ECC_NC:     reason = "non-correctable ECC error"; break;
415         case MCHK_K_CACKSOFT:   reason = "MCHK_K_CACKSOFT"; break;
416         case MCHK_K_BUGCHECK:   reason = "illegal exception in PAL mode"; break;
417         case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break;
418         case MCHK_K_DCPERR:     reason = "d-cache parity error"; break;
419         case MCHK_K_ICPERR:     reason = "i-cache parity error"; break;
420         case MCHK_K_SIO_SERR:   reason = "SIO SERR occurred on PCI bus"; break;
421         case MCHK_K_SIO_IOCHK:  reason = "SIO IOCHK occurred on ISA bus"; break;
422         case MCHK_K_DCSR:       reason = "MCHK_K_DCSR"; break;
423         case MCHK_K_UNKNOWN:
424         default:                reason = "unknown"; break;
425         }
426 
427         switch (el.c->size) {
428         case sizeof(struct el_lca_mcheck_short):
429                 printk(KERN_CRIT
430                        "  Reason: %s (short frame%s, dc_stat=%#lx):\n",
431                        reason, el.c->retry ? ", retryable" : "",
432                        el.s->dc_stat);
433                 if (el.s->esr & ESR_EAV) {
434                         mem_error(el.s->esr, el.s->ear);
435                 }
436                 if (el.s->ioc_stat0 & IOC_ERR) {
437                         ioc_error(el.s->ioc_stat0, el.s->ioc_stat1);
438                 }
439                 break;
440 
441         case sizeof(struct el_lca_mcheck_long):
442                 printk(KERN_CRIT "  Reason: %s (long frame%s):\n",
443                        reason, el.c->retry ? ", retryable" : "");
444                 printk(KERN_CRIT
445                        "    reason: %#lx  exc_addr: %#lx  dc_stat: %#lx\n", 
446                        el.l->pt[0], el.l->exc_addr, el.l->dc_stat);
447                 printk(KERN_CRIT "    car: %#lx\n", el.l->car);
448                 if (el.l->esr & ESR_EAV) {
449                         mem_error(el.l->esr, el.l->ear);
450                 }
451                 if (el.l->ioc_stat0 & IOC_ERR) {
452                         ioc_error(el.l->ioc_stat0, el.l->ioc_stat1);
453                 }
454                 break;
455 
456         default:
457                 printk(KERN_CRIT "  Unknown errorlog size %d\n", el.c->size);
458         }
459 
460         /* Dump the logout area to give all info.  */
461 #ifdef CONFIG_VERBOSE_MCHECK
462         if (alpha_verbose_mcheck > 1) {
463                 unsigned long * ptr = (unsigned long *) la_ptr;
464                 long i;
465                 for (i = 0; i < el.c->size / sizeof(long); i += 2) {
466                         printk(KERN_CRIT " +%8lx %016lx %016lx\n",
467                                i*sizeof(long), ptr[i], ptr[i+1]);
468                 }
469         }
470 #endif /* CONFIG_VERBOSE_MCHECK */
471 }
472 
473 /*
474  * The following routines are needed to support the SPEED changing
475  * necessary to successfully manage the thermal problem on the AlphaBook1.
476  */
477 
478 void
479 lca_clock_print(void)
480 {
481         long    pmr_reg;
482 
483         pmr_reg = LCA_READ_PMR;
484 
485         printk("Status of clock control:\n");
486         printk("\tPrimary clock divisor\t0x%lx\n", LCA_GET_PRIMARY(pmr_reg));
487         printk("\tOverride clock divisor\t0x%lx\n", LCA_GET_OVERRIDE(pmr_reg));
488         printk("\tInterrupt override is %s\n",
489                (pmr_reg & LCA_PMR_INTO) ? "on" : "off"); 
490         printk("\tDMA override is %s\n",
491                (pmr_reg & LCA_PMR_DMAO) ? "on" : "off"); 
492 
493 }
494 
495 int
496 lca_get_clock(void)
497 {
498         long    pmr_reg;
499 
500         pmr_reg = LCA_READ_PMR;
501         return(LCA_GET_PRIMARY(pmr_reg));
502 
503 }
504 
505 void
506 lca_clock_fiddle(int divisor)
507 {
508         long    pmr_reg;
509 
510         pmr_reg = LCA_READ_PMR;
511         LCA_SET_PRIMARY_CLOCK(pmr_reg, divisor);
512         /* lca_norm_clock = divisor; */
513         LCA_WRITE_PMR(pmr_reg);
514         mb();
515 }
516 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp