Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/alpha/kernel/core_lca.c
10817 views
1
/*
2
* linux/arch/alpha/kernel/core_lca.c
3
*
4
* Written by David Mosberger ([email protected]) with some code
5
* taken from Dave Rusling's ([email protected]) 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 losing 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 losing 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
517