cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fsp2.c (9903B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * FSP-2 board specific routines
      4 *
      5 * Based on earlier code:
      6 *    Matt Porter <mporter@kernel.crashing.org>
      7 *    Copyright 2002-2005 MontaVista Software Inc.
      8 *
      9 *    Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
     10 *    Copyright (c) 2003-2005 Zultys Technologies
     11 *
     12 *    Rewritten and ported to the merged powerpc tree:
     13 *    Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
     14 */
     15
     16#include <linux/init.h>
     17#include <linux/of_fdt.h>
     18#include <linux/of_platform.h>
     19#include <linux/rtc.h>
     20
     21#include <asm/machdep.h>
     22#include <asm/udbg.h>
     23#include <asm/time.h>
     24#include <asm/uic.h>
     25#include <asm/ppc4xx.h>
     26#include <asm/dcr.h>
     27#include <linux/interrupt.h>
     28#include <linux/of_irq.h>
     29#include "fsp2.h"
     30
     31#define FSP2_BUS_ERR	"ibm,bus-error-irq"
     32#define FSP2_CMU_ERR	"ibm,cmu-error-irq"
     33#define FSP2_CONF_ERR	"ibm,conf-error-irq"
     34#define FSP2_OPBD_ERR	"ibm,opbd-error-irq"
     35#define FSP2_MCUE	"ibm,mc-ue-irq"
     36#define FSP2_RST_WRN	"ibm,reset-warning-irq"
     37
     38static __initdata struct of_device_id fsp2_of_bus[] = {
     39	{ .compatible = "ibm,plb4", },
     40	{ .compatible = "ibm,plb6", },
     41	{ .compatible = "ibm,opb", },
     42	{},
     43};
     44
     45static void l2regs(void)
     46{
     47	pr_err("L2 Controller:\n");
     48	pr_err("MCK:      0x%08x\n", mfl2(L2MCK));
     49	pr_err("INT:      0x%08x\n", mfl2(L2INT));
     50	pr_err("PLBSTAT0: 0x%08x\n", mfl2(L2PLBSTAT0));
     51	pr_err("PLBSTAT1: 0x%08x\n", mfl2(L2PLBSTAT1));
     52	pr_err("ARRSTAT0: 0x%08x\n", mfl2(L2ARRSTAT0));
     53	pr_err("ARRSTAT1: 0x%08x\n", mfl2(L2ARRSTAT1));
     54	pr_err("ARRSTAT2: 0x%08x\n", mfl2(L2ARRSTAT2));
     55	pr_err("CPUSTAT:  0x%08x\n", mfl2(L2CPUSTAT));
     56	pr_err("RACSTAT0: 0x%08x\n", mfl2(L2RACSTAT0));
     57	pr_err("WACSTAT0: 0x%08x\n", mfl2(L2WACSTAT0));
     58	pr_err("WACSTAT1: 0x%08x\n", mfl2(L2WACSTAT1));
     59	pr_err("WACSTAT2: 0x%08x\n", mfl2(L2WACSTAT2));
     60	pr_err("WDFSTAT:  0x%08x\n", mfl2(L2WDFSTAT));
     61	pr_err("LOG0:     0x%08x\n", mfl2(L2LOG0));
     62	pr_err("LOG1:     0x%08x\n", mfl2(L2LOG1));
     63	pr_err("LOG2:     0x%08x\n", mfl2(L2LOG2));
     64	pr_err("LOG3:     0x%08x\n", mfl2(L2LOG3));
     65	pr_err("LOG4:     0x%08x\n", mfl2(L2LOG4));
     66	pr_err("LOG5:     0x%08x\n", mfl2(L2LOG5));
     67}
     68
     69static void show_plbopb_regs(u32 base, int num)
     70{
     71	pr_err("\nPLBOPB Bridge %d:\n", num);
     72	pr_err("GESR0: 0x%08x\n", mfdcr(base + PLB4OPB_GESR0));
     73	pr_err("GESR1: 0x%08x\n", mfdcr(base + PLB4OPB_GESR1));
     74	pr_err("GESR2: 0x%08x\n", mfdcr(base + PLB4OPB_GESR2));
     75	pr_err("GEARU: 0x%08x\n", mfdcr(base + PLB4OPB_GEARU));
     76	pr_err("GEAR:  0x%08x\n", mfdcr(base + PLB4OPB_GEAR));
     77}
     78
     79static irqreturn_t bus_err_handler(int irq, void *data)
     80{
     81	pr_err("Bus Error\n");
     82
     83	l2regs();
     84
     85	pr_err("\nPLB6 Controller:\n");
     86	pr_err("BC_SHD: 0x%08x\n", mfdcr(DCRN_PLB6_SHD));
     87	pr_err("BC_ERR: 0x%08x\n", mfdcr(DCRN_PLB6_ERR));
     88
     89	pr_err("\nPLB6-to-PLB4 Bridge:\n");
     90	pr_err("ESR:  0x%08x\n", mfdcr(DCRN_PLB6PLB4_ESR));
     91	pr_err("EARH: 0x%08x\n", mfdcr(DCRN_PLB6PLB4_EARH));
     92	pr_err("EARL: 0x%08x\n", mfdcr(DCRN_PLB6PLB4_EARL));
     93
     94	pr_err("\nPLB4-to-PLB6 Bridge:\n");
     95	pr_err("ESR:  0x%08x\n", mfdcr(DCRN_PLB4PLB6_ESR));
     96	pr_err("EARH: 0x%08x\n", mfdcr(DCRN_PLB4PLB6_EARH));
     97	pr_err("EARL: 0x%08x\n", mfdcr(DCRN_PLB4PLB6_EARL));
     98
     99	pr_err("\nPLB6-to-MCIF Bridge:\n");
    100	pr_err("BESR0: 0x%08x\n", mfdcr(DCRN_PLB6MCIF_BESR0));
    101	pr_err("BESR1: 0x%08x\n", mfdcr(DCRN_PLB6MCIF_BESR1));
    102	pr_err("BEARH: 0x%08x\n", mfdcr(DCRN_PLB6MCIF_BEARH));
    103	pr_err("BEARL: 0x%08x\n", mfdcr(DCRN_PLB6MCIF_BEARL));
    104
    105	pr_err("\nPLB4 Arbiter:\n");
    106	pr_err("P0ESRH 0x%08x\n", mfdcr(DCRN_PLB4_P0ESRH));
    107	pr_err("P0ESRL 0x%08x\n", mfdcr(DCRN_PLB4_P0ESRL));
    108	pr_err("P0EARH 0x%08x\n", mfdcr(DCRN_PLB4_P0EARH));
    109	pr_err("P0EARH 0x%08x\n", mfdcr(DCRN_PLB4_P0EARH));
    110	pr_err("P1ESRH 0x%08x\n", mfdcr(DCRN_PLB4_P1ESRH));
    111	pr_err("P1ESRL 0x%08x\n", mfdcr(DCRN_PLB4_P1ESRL));
    112	pr_err("P1EARH 0x%08x\n", mfdcr(DCRN_PLB4_P1EARH));
    113	pr_err("P1EARH 0x%08x\n", mfdcr(DCRN_PLB4_P1EARH));
    114
    115	show_plbopb_regs(DCRN_PLB4OPB0_BASE, 0);
    116	show_plbopb_regs(DCRN_PLB4OPB1_BASE, 1);
    117	show_plbopb_regs(DCRN_PLB4OPB2_BASE, 2);
    118	show_plbopb_regs(DCRN_PLB4OPB3_BASE, 3);
    119
    120	pr_err("\nPLB4-to-AHB Bridge:\n");
    121	pr_err("ESR:   0x%08x\n", mfdcr(DCRN_PLB4AHB_ESR));
    122	pr_err("SEUAR: 0x%08x\n", mfdcr(DCRN_PLB4AHB_SEUAR));
    123	pr_err("SELAR: 0x%08x\n", mfdcr(DCRN_PLB4AHB_SELAR));
    124
    125	pr_err("\nAHB-to-PLB4 Bridge:\n");
    126	pr_err("\nESR: 0x%08x\n", mfdcr(DCRN_AHBPLB4_ESR));
    127	pr_err("\nEAR: 0x%08x\n", mfdcr(DCRN_AHBPLB4_EAR));
    128	panic("Bus Error\n");
    129}
    130
    131static irqreturn_t cmu_err_handler(int irq, void *data) {
    132	pr_err("CMU Error\n");
    133	pr_err("FIR0: 0x%08x\n", mfcmu(CMUN_FIR0));
    134	panic("CMU Error\n");
    135}
    136
    137static irqreturn_t conf_err_handler(int irq, void *data) {
    138	pr_err("Configuration Logic Error\n");
    139	pr_err("CONF_FIR: 0x%08x\n", mfdcr(DCRN_CONF_FIR_RWC));
    140	pr_err("RPERR0:   0x%08x\n", mfdcr(DCRN_CONF_RPERR0));
    141	pr_err("RPERR1:   0x%08x\n", mfdcr(DCRN_CONF_RPERR1));
    142	panic("Configuration Logic Error\n");
    143}
    144
    145static irqreturn_t opbd_err_handler(int irq, void *data) {
    146	panic("OPBD Error\n");
    147}
    148
    149static irqreturn_t mcue_handler(int irq, void *data) {
    150	pr_err("DDR: Uncorrectable Error\n");
    151	pr_err("MCSTAT:            0x%08x\n",
    152		mfdcr(DCRN_DDR34_BASE + DCRN_DDR34_MCSTAT));
    153	pr_err("MCOPT1:            0x%08x\n",
    154		mfdcr(DCRN_DDR34_BASE + DCRN_DDR34_MCOPT1));
    155	pr_err("MCOPT2:            0x%08x\n",
    156		mfdcr(DCRN_DDR34_BASE + DCRN_DDR34_MCOPT2));
    157	pr_err("PHYSTAT:           0x%08x\n",
    158		mfdcr(DCRN_DDR34_BASE + DCRN_DDR34_PHYSTAT));
    159	pr_err("CFGR0:             0x%08x\n",
    160		mfdcr(DCRN_DDR34_BASE + DCRN_DDR34_CFGR0));
    161	pr_err("CFGR1:             0x%08x\n",
    162		mfdcr(DCRN_DDR34_BASE + DCRN_DDR34_CFGR1));
    163	pr_err("CFGR2:             0x%08x\n",
    164		mfdcr(DCRN_DDR34_BASE + DCRN_DDR34_CFGR2));
    165	pr_err("CFGR3:             0x%08x\n",
    166		mfdcr(DCRN_DDR34_BASE + DCRN_DDR34_CFGR3));
    167	pr_err("SCRUB_CNTL:        0x%08x\n",
    168		mfdcr(DCRN_DDR34_BASE + DCRN_DDR34_SCRUB_CNTL));
    169	pr_err("ECCERR_PORT0:      0x%08x\n",
    170		mfdcr(DCRN_DDR34_BASE + DCRN_DDR34_ECCERR_PORT0));
    171	pr_err("ECCERR_ADDR_PORT0: 0x%08x\n",
    172		mfdcr(DCRN_DDR34_BASE + DCRN_DDR34_ECCERR_ADDR_PORT0));
    173	pr_err("ECCERR_CNT_PORT0:  0x%08x\n",
    174		mfdcr(DCRN_DDR34_BASE + DCRN_DDR34_ECCERR_COUNT_PORT0));
    175	pr_err("ECC_CHECK_PORT0:   0x%08x\n",
    176		mfdcr(DCRN_DDR34_BASE + DCRN_DDR34_ECC_CHECK_PORT0));
    177	pr_err("MCER0:            0x%08x\n",
    178		mfdcr(DCRN_CW_BASE + DCRN_CW_MCER0));
    179	pr_err("MCER1:            0x%08x\n",
    180		mfdcr(DCRN_CW_BASE + DCRN_CW_MCER1));
    181	pr_err("BESR:             0x%08x\n",
    182		mfdcr(DCRN_PLB6MCIF_BESR0));
    183	pr_err("BEARL:            0x%08x\n",
    184		mfdcr(DCRN_PLB6MCIF_BEARL));
    185	pr_err("BEARH:            0x%08x\n",
    186		mfdcr(DCRN_PLB6MCIF_BEARH));
    187	panic("DDR: Uncorrectable Error\n");
    188}
    189
    190static irqreturn_t rst_wrn_handler(int irq, void *data) {
    191	u32 crcs = mfcmu(CMUN_CRCS);
    192	switch (crcs & CRCS_STAT_MASK) {
    193	case CRCS_STAT_CHIP_RST_B:
    194		panic("Received chassis-initiated reset request");
    195	default:
    196		panic("Unknown external reset: CRCS=0x%x", crcs);
    197	}
    198}
    199
    200static void __init node_irq_request(const char *compat, irq_handler_t errirq_handler)
    201{
    202	struct device_node *np;
    203	unsigned int irq;
    204	int32_t rc;
    205
    206	for_each_compatible_node(np, NULL, compat) {
    207		irq = irq_of_parse_and_map(np, 0);
    208		if (irq == NO_IRQ) {
    209			pr_err("device tree node %pOFn is missing a interrupt",
    210			      np);
    211			of_node_put(np);
    212			return;
    213		}
    214
    215		rc = request_irq(irq, errirq_handler, 0, np->name, np);
    216		if (rc) {
    217			pr_err("fsp_of_probe: request_irq failed: np=%pOF rc=%d",
    218			      np, rc);
    219			of_node_put(np);
    220			return;
    221		}
    222	}
    223}
    224
    225static void __init critical_irq_setup(void)
    226{
    227	node_irq_request(FSP2_CMU_ERR, cmu_err_handler);
    228	node_irq_request(FSP2_BUS_ERR, bus_err_handler);
    229	node_irq_request(FSP2_CONF_ERR, conf_err_handler);
    230	node_irq_request(FSP2_OPBD_ERR, opbd_err_handler);
    231	node_irq_request(FSP2_MCUE, mcue_handler);
    232	node_irq_request(FSP2_RST_WRN, rst_wrn_handler);
    233}
    234
    235static int __init fsp2_device_probe(void)
    236{
    237	of_platform_bus_probe(NULL, fsp2_of_bus, NULL);
    238	return 0;
    239}
    240machine_device_initcall(fsp2, fsp2_device_probe);
    241
    242static int __init fsp2_probe(void)
    243{
    244	u32 val;
    245	unsigned long root = of_get_flat_dt_root();
    246
    247	if (!of_flat_dt_is_compatible(root, "ibm,fsp2"))
    248		return 0;
    249
    250	/* Clear BC_ERR and mask snoopable request plb errors. */
    251	val = mfdcr(DCRN_PLB6_CR0);
    252	val |= 0x20000000;
    253	mtdcr(DCRN_PLB6_BASE, val);
    254	mtdcr(DCRN_PLB6_HD, 0xffff0000);
    255	mtdcr(DCRN_PLB6_SHD, 0xffff0000);
    256
    257	/* TVSENSE reset is blocked (clock gated) by the POR default of the TVS
    258	 * sleep config bit. As a consequence, TVSENSE will provide erratic
    259	 * sensor values, which may result in spurious (parity) errors
    260	 * recorded in the CMU FIR and leading to erroneous interrupt requests
    261	 * once the CMU interrupt is unmasked.
    262	 */
    263
    264	/* 1. set TVS1[UNDOZE] */
    265	val = mfcmu(CMUN_TVS1);
    266	val |= 0x4;
    267	mtcmu(CMUN_TVS1, val);
    268
    269	/* 2. clear FIR[TVS] and FIR[TVSPAR] */
    270	val = mfcmu(CMUN_FIR0);
    271	val |= 0x30000000;
    272	mtcmu(CMUN_FIR0, val);
    273
    274	/* L2 machine checks */
    275	mtl2(L2PLBMCKEN0, 0xffffffff);
    276	mtl2(L2PLBMCKEN1, 0x0000ffff);
    277	mtl2(L2ARRMCKEN0, 0xffffffff);
    278	mtl2(L2ARRMCKEN1, 0xffffffff);
    279	mtl2(L2ARRMCKEN2, 0xfffff000);
    280	mtl2(L2CPUMCKEN,  0xffffffff);
    281	mtl2(L2RACMCKEN0, 0xffffffff);
    282	mtl2(L2WACMCKEN0, 0xffffffff);
    283	mtl2(L2WACMCKEN1, 0xffffffff);
    284	mtl2(L2WACMCKEN2, 0xffffffff);
    285	mtl2(L2WDFMCKEN,  0xffffffff);
    286
    287	/* L2 interrupts */
    288	mtl2(L2PLBINTEN1, 0xffff0000);
    289
    290	/*
    291	 * At a global level, enable all L2 machine checks and interrupts
    292	 * reported by the L2 subsystems, except for the external machine check
    293	 * input (UIC0.1).
    294	 */
    295	mtl2(L2MCKEN, 0x000007ff);
    296	mtl2(L2INTEN, 0x000004ff);
    297
    298	/* Enable FSP-2 configuration logic parity errors */
    299	mtdcr(DCRN_CONF_EIR_RS, 0x80000000);
    300	return 1;
    301}
    302
    303static void __init fsp2_irq_init(void)
    304{
    305	uic_init_tree();
    306	critical_irq_setup();
    307}
    308
    309define_machine(fsp2) {
    310	.name			= "FSP-2",
    311	.probe			= fsp2_probe,
    312	.progress		= udbg_progress,
    313	.init_IRQ		= fsp2_irq_init,
    314	.get_irq		= uic_get_irq,
    315	.restart		= ppc4xx_reset_system,
    316	.calibrate_decr		= generic_calibrate_decr,
    317};