^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2008 Nuovation System Designs, LLC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Grant Erickson <gerickson@nuovations.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/edac.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/dcr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "edac_module.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "ppc4xx_edac.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * This file implements a driver for monitoring and handling events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * associated with the IMB DDR2 ECC controller found in the AMCC/IBM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * 405EX[r], 440SP, 440SPe, 460EX, 460GT and 460SX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * As realized in the 405EX[r], this controller features:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * - Support for registered- and non-registered DDR1 and DDR2 memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * - 32-bit or 16-bit memory interface with optional ECC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * o ECC support includes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * - 4-bit SEC/DED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * - Aligned-nibble error detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * - Bypass mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * - Two (2) memory banks/ranks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * - Up to 1 GiB per bank/rank in 32-bit mode and up to 512 MiB per
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * bank/rank in 16-bit mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * As realized in the 440SP and 440SPe, this controller changes/adds:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * - 64-bit or 32-bit memory interface with optional ECC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * o ECC support includes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * - 8-bit SEC/DED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * - Aligned-nibble error detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * - Bypass mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * - Up to 4 GiB per bank/rank in 64-bit mode and up to 2 GiB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * per bank/rank in 32-bit mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * As realized in the 460EX and 460GT, this controller changes/adds:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * - 64-bit or 32-bit memory interface with optional ECC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * o ECC support includes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * - 8-bit SEC/DED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * - Aligned-nibble error detect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * - Bypass mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * - Four (4) memory banks/ranks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * - Up to 16 GiB per bank/rank in 64-bit mode and up to 8 GiB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * per bank/rank in 32-bit mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * At present, this driver has ONLY been tested against the controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * realization in the 405EX[r] on the AMCC Kilauea and Haleakala
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * boards (256 MiB w/o ECC memory soldered onto the board) and a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * proprietary board based on those designs (128 MiB ECC memory, also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * soldered onto the board).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * Dynamic feature detection and handling needs to be added for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * other realizations of this controller listed above.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * Eventually, this driver will likely be adapted to the above variant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * realizations of this controller as well as broken apart to handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * the other known ECC-capable controllers prevalent in other 4xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * processors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * - IBM SDRAM (405GP, 405CR and 405EP) "ibm,sdram-4xx"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * - IBM DDR1 (440GP, 440GX, 440EP and 440GR) "ibm,sdram-4xx-ddr"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * - Denali DDR1/DDR2 (440EPX and 440GRX) "denali,sdram-4xx-ddr2"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * For this controller, unfortunately, correctable errors report
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * nothing more than the beat/cycle and byte/lane the correction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * occurred on and the check bit group that covered the error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * In contrast, uncorrectable errors also report the failing address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * the bus master and the transaction direction (i.e. read or write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * Regardless of whether the error is a CE or a UE, we report the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * following pieces of information in the driver-unique message to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * EDAC subsystem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * - Device tree path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * - Bank(s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * - Check bit error group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * - Beat(s)/lane(s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* Preprocessor Definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define EDAC_OPSTATE_INT_STR "interrupt"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #define EDAC_OPSTATE_POLL_STR "polled"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define EDAC_OPSTATE_UNKNOWN_STR "unknown"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define PPC4XX_EDAC_MODULE_NAME "ppc4xx_edac"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define PPC4XX_EDAC_MODULE_REVISION "v1.0.0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #define PPC4XX_EDAC_MESSAGE_SIZE 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * Kernel logging without an EDAC instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define ppc4xx_edac_printk(level, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) edac_printk(level, "PPC4xx MC", fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * Kernel logging with an EDAC instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define ppc4xx_edac_mc_printk(level, mci, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) edac_mc_chipset_printk(mci, level, "PPC4xx", fmt, ##arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * Macros to convert bank configuration size enumerations into MiB and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * page values.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) #define SDRAM_MBCF_SZ_MiB_MIN 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) #define SDRAM_MBCF_SZ_TO_MiB(n) (SDRAM_MBCF_SZ_MiB_MIN \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) << (SDRAM_MBCF_SZ_DECODE(n)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define SDRAM_MBCF_SZ_TO_PAGES(n) (SDRAM_MBCF_SZ_MiB_MIN \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) << (20 - PAGE_SHIFT + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) SDRAM_MBCF_SZ_DECODE(n)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * The ibm,sdram-4xx-ddr2 Device Control Registers (DCRs) are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * indirectly accessed and have a base and length defined by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * device tree. The base can be anything; however, we expect the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * length to be precisely two registers, the first for the address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * window and the second for the data window.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define SDRAM_DCR_RESOURCE_LEN 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define SDRAM_DCR_ADDR_OFFSET 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define SDRAM_DCR_DATA_OFFSET 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * Device tree interrupt indices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define INTMAP_ECCDED_INDEX 0 /* Double-bit Error Detect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) #define INTMAP_ECCSEC_INDEX 1 /* Single-bit Error Correct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /* Type Definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * PPC4xx SDRAM memory controller private instance data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct ppc4xx_edac_pdata {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) dcr_host_t dcr_host; /* Indirect DCR address/data window mapping */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int sec; /* Single-bit correctable error IRQ assigned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) int ded; /* Double-bit detectable error IRQ assigned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) } irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * Various status data gathered and manipulated when checking and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * reporting ECC status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct ppc4xx_ecc_status {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) u32 ecces;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) u32 besr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) u32 bearh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) u32 bearl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) u32 wmirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* Function Prototypes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) static int ppc4xx_edac_probe(struct platform_device *device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static int ppc4xx_edac_remove(struct platform_device *device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* Global Variables */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * Device tree node type and compatible tuples this driver can match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static const struct of_device_id ppc4xx_edac_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .compatible = "ibm,sdram-4xx-ddr2"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) MODULE_DEVICE_TABLE(of, ppc4xx_edac_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static struct platform_driver ppc4xx_edac_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .probe = ppc4xx_edac_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .remove = ppc4xx_edac_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .name = PPC4XX_EDAC_MODULE_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .of_match_table = ppc4xx_edac_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * TODO: The row and channel parameters likely need to be dynamically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * set based on the aforementioned variant controller realizations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static const unsigned ppc4xx_edac_nr_csrows = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static const unsigned ppc4xx_edac_nr_chans = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * Strings associated with PLB master IDs capable of being posted in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * SDRAM_BESR or SDRAM_WMIRQ on uncorrectable ECC errors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static const char * const ppc4xx_plb_masters[9] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) [SDRAM_PLB_M0ID_ICU] = "ICU",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) [SDRAM_PLB_M0ID_PCIE0] = "PCI-E 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) [SDRAM_PLB_M0ID_PCIE1] = "PCI-E 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) [SDRAM_PLB_M0ID_DMA] = "DMA",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) [SDRAM_PLB_M0ID_DCU] = "DCU",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) [SDRAM_PLB_M0ID_OPB] = "OPB",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) [SDRAM_PLB_M0ID_MAL] = "MAL",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) [SDRAM_PLB_M0ID_SEC] = "SEC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) [SDRAM_PLB_M0ID_AHB] = "AHB"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * mfsdram - read and return controller register data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * @dcr_host: A pointer to the DCR mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * @idcr_n: The indirect DCR register to read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * This routine reads and returns the data associated with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * controller's specified indirect DCR register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * Returns the read data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static inline u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) mfsdram(const dcr_host_t *dcr_host, unsigned int idcr_n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return __mfdcri(dcr_host->base + SDRAM_DCR_ADDR_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) dcr_host->base + SDRAM_DCR_DATA_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) idcr_n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * mtsdram - write controller register data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * @dcr_host: A pointer to the DCR mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * @idcr_n: The indirect DCR register to write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * @value: The data to write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * This routine writes the provided data to the controller's specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * indirect DCR register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) mtsdram(const dcr_host_t *dcr_host, unsigned int idcr_n, u32 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return __mtdcri(dcr_host->base + SDRAM_DCR_ADDR_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) dcr_host->base + SDRAM_DCR_DATA_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) idcr_n,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * ppc4xx_edac_check_bank_error - check a bank for an ECC bank error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * @status: A pointer to the ECC status structure to check for an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * ECC bank error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * @bank: The bank to check for an ECC error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * This routine determines whether the specified bank has an ECC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * Returns true if the specified bank has an ECC error; otherwise,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * false.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) ppc4xx_edac_check_bank_error(const struct ppc4xx_ecc_status *status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) unsigned int bank)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) switch (bank) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return status->ecces & SDRAM_ECCES_BK0ER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return status->ecces & SDRAM_ECCES_BK1ER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * ppc4xx_edac_generate_bank_message - generate interpretted bank status message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * @mci: A pointer to the EDAC memory controller instance associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * with the bank message being generated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * @status: A pointer to the ECC status structure to generate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * message from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * @buffer: A pointer to the buffer in which to generate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * @size: The size, in bytes, of space available in buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * This routine generates to the provided buffer the portion of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * driver-unique report message associated with the ECCESS[BKNER]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * field of the specified ECC status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * Returns the number of characters generated on success; otherwise, <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) ppc4xx_edac_generate_bank_message(const struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) const struct ppc4xx_ecc_status *status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) int n, total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) unsigned int row, rows;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) n = snprintf(buffer, size, "%s: Banks: ", mci->dev_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (n < 0 || n >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) buffer += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) size -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) total += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) for (rows = 0, row = 0; row < mci->nr_csrows; row++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (ppc4xx_edac_check_bank_error(status, row)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) n = snprintf(buffer, size, "%s%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) (rows++ ? ", " : ""), row);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (n < 0 || n >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) buffer += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) size -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) total += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) n = snprintf(buffer, size, "%s; ", rows ? "" : "None");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (n < 0 || n >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) buffer += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) size -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) total += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * ppc4xx_edac_generate_checkbit_message - generate interpretted checkbit message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * @mci: A pointer to the EDAC memory controller instance associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * with the checkbit message being generated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * @status: A pointer to the ECC status structure to generate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * message from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * @buffer: A pointer to the buffer in which to generate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * @size: The size, in bytes, of space available in buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * This routine generates to the provided buffer the portion of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * driver-unique report message associated with the ECCESS[CKBER]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * field of the specified ECC status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * Returns the number of characters generated on success; otherwise, <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) ppc4xx_edac_generate_checkbit_message(const struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) const struct ppc4xx_ecc_status *status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) const struct ppc4xx_edac_pdata *pdata = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) const char *ckber = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) switch (status->ecces & SDRAM_ECCES_CKBER_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) case SDRAM_ECCES_CKBER_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) ckber = "None";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) case SDRAM_ECCES_CKBER_32_ECC_0_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) ckber = "ECC0:3";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case SDRAM_ECCES_CKBER_32_ECC_4_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) switch (mfsdram(&pdata->dcr_host, SDRAM_MCOPT1) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) SDRAM_MCOPT1_WDTH_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) case SDRAM_MCOPT1_WDTH_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) ckber = "ECC0:3";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) case SDRAM_MCOPT1_WDTH_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) ckber = "ECC4:8";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ckber = "Unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) case SDRAM_ECCES_CKBER_32_ECC_0_8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) ckber = "ECC0:8";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) ckber = "Unknown";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return snprintf(buffer, size, "Checkbit Error: %s", ckber);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * ppc4xx_edac_generate_lane_message - generate interpretted byte lane message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * @mci: A pointer to the EDAC memory controller instance associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * with the byte lane message being generated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * @status: A pointer to the ECC status structure to generate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * message from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * @buffer: A pointer to the buffer in which to generate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * @size: The size, in bytes, of space available in buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * This routine generates to the provided buffer the portion of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * driver-unique report message associated with the ECCESS[BNCE]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * field of the specified ECC status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * Returns the number of characters generated on success; otherwise, <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) ppc4xx_edac_generate_lane_message(const struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) const struct ppc4xx_ecc_status *status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) int n, total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) unsigned int lane, lanes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) const unsigned int first_lane = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) const unsigned int lane_count = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) n = snprintf(buffer, size, "; Byte Lane Errors: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (n < 0 || n >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) buffer += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) size -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) total += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) for (lanes = 0, lane = first_lane; lane < lane_count; lane++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if ((status->ecces & SDRAM_ECCES_BNCE_ENCODE(lane)) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) n = snprintf(buffer, size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) "%s%u",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) (lanes++ ? ", " : ""), lane);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (n < 0 || n >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) buffer += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) size -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) total += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) n = snprintf(buffer, size, "%s; ", lanes ? "" : "None");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (n < 0 || n >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) buffer += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) size -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) total += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * ppc4xx_edac_generate_ecc_message - generate interpretted ECC status message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * @mci: A pointer to the EDAC memory controller instance associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * with the ECCES message being generated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) * @status: A pointer to the ECC status structure to generate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * message from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * @buffer: A pointer to the buffer in which to generate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * @size: The size, in bytes, of space available in buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) * This routine generates to the provided buffer the portion of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * driver-unique report message associated with the ECCESS register of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * the specified ECC status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * Returns the number of characters generated on success; otherwise, <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) ppc4xx_edac_generate_ecc_message(const struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) const struct ppc4xx_ecc_status *status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) int n, total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) n = ppc4xx_edac_generate_bank_message(mci, status, buffer, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (n < 0 || n >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) buffer += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) size -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) total += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) n = ppc4xx_edac_generate_checkbit_message(mci, status, buffer, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (n < 0 || n >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) buffer += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) size -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) total += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) n = ppc4xx_edac_generate_lane_message(mci, status, buffer, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (n < 0 || n >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) buffer += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) size -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) total += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * ppc4xx_edac_generate_plb_message - generate interpretted PLB status message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * @mci: A pointer to the EDAC memory controller instance associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * with the PLB message being generated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * @status: A pointer to the ECC status structure to generate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * message from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * @buffer: A pointer to the buffer in which to generate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) * @size: The size, in bytes, of space available in buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * This routine generates to the provided buffer the portion of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * driver-unique report message associated with the PLB-related BESR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * and/or WMIRQ registers of the specified ECC status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * Returns the number of characters generated on success; otherwise, <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) ppc4xx_edac_generate_plb_message(const struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) const struct ppc4xx_ecc_status *status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) unsigned int master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) bool read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if ((status->besr & SDRAM_BESR_MASK) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if ((status->besr & SDRAM_BESR_M0ET_MASK) == SDRAM_BESR_M0ET_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) read = ((status->besr & SDRAM_BESR_M0RW_MASK) == SDRAM_BESR_M0RW_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) master = SDRAM_BESR_M0ID_DECODE(status->besr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return snprintf(buffer, size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) "%s error w/ PLB master %u \"%s\"; ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) (read ? "Read" : "Write"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) master,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) (((master >= SDRAM_PLB_M0ID_FIRST) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) (master <= SDRAM_PLB_M0ID_LAST)) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) ppc4xx_plb_masters[master] : "UNKNOWN"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * ppc4xx_edac_generate_message - generate interpretted status message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * @mci: A pointer to the EDAC memory controller instance associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) * with the driver-unique message being generated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * @status: A pointer to the ECC status structure to generate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * message from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * @buffer: A pointer to the buffer in which to generate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * @size: The size, in bytes, of space available in buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * This routine generates to the provided buffer the driver-unique
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * EDAC report message from the specified ECC status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) ppc4xx_edac_generate_message(const struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) const struct ppc4xx_ecc_status *status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) int n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (buffer == NULL || size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) n = ppc4xx_edac_generate_ecc_message(mci, status, buffer, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (n < 0 || n >= size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) buffer += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) size -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ppc4xx_edac_generate_plb_message(mci, status, buffer, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * ppc4xx_ecc_dump_status - dump controller ECC status registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * @mci: A pointer to the EDAC memory controller instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * associated with the status being dumped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * @status: A pointer to the ECC status structure to generate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) * dump from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) * This routine dumps to the kernel log buffer the raw and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * interpretted specified ECC status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) ppc4xx_ecc_dump_status(const struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) const struct ppc4xx_ecc_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) char message[PPC4XX_EDAC_MESSAGE_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) ppc4xx_edac_generate_message(mci, status, message, sizeof(message));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) ppc4xx_edac_mc_printk(KERN_INFO, mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) "\tECCES: 0x%08x\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) "\tWMIRQ: 0x%08x\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) "\tBESR: 0x%08x\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) "\tBEAR: 0x%08x%08x\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) "\t%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) status->ecces,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) status->wmirq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) status->besr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) status->bearh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) status->bearl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) message);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) #endif /* DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) * ppc4xx_ecc_get_status - get controller ECC status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * @mci: A pointer to the EDAC memory controller instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * associated with the status being retrieved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * @status: A pointer to the ECC status structure to populate the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) * ECC status with.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) * This routine reads and masks, as appropriate, all the relevant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * status registers that deal with ibm,sdram-4xx-ddr2 ECC errors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) * While we read all of them, for correctable errors, we only expect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) * to deal with ECCES. For uncorrectable errors, we expect to deal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * with all of them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) ppc4xx_ecc_get_status(const struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) struct ppc4xx_ecc_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) const struct ppc4xx_edac_pdata *pdata = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) const dcr_host_t *dcr_host = &pdata->dcr_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) status->ecces = mfsdram(dcr_host, SDRAM_ECCES) & SDRAM_ECCES_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) status->wmirq = mfsdram(dcr_host, SDRAM_WMIRQ) & SDRAM_WMIRQ_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) status->besr = mfsdram(dcr_host, SDRAM_BESR) & SDRAM_BESR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) status->bearl = mfsdram(dcr_host, SDRAM_BEARL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) status->bearh = mfsdram(dcr_host, SDRAM_BEARH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * ppc4xx_ecc_clear_status - clear controller ECC status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * @mci: A pointer to the EDAC memory controller instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * associated with the status being cleared.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * @status: A pointer to the ECC status structure containing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * values to write to clear the ECC status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * This routine clears--by writing the masked (as appropriate) status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * values back to--the status registers that deal with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * ibm,sdram-4xx-ddr2 ECC errors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) ppc4xx_ecc_clear_status(const struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) const struct ppc4xx_ecc_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) const struct ppc4xx_edac_pdata *pdata = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) const dcr_host_t *dcr_host = &pdata->dcr_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) mtsdram(dcr_host, SDRAM_ECCES, status->ecces & SDRAM_ECCES_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) mtsdram(dcr_host, SDRAM_WMIRQ, status->wmirq & SDRAM_WMIRQ_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) mtsdram(dcr_host, SDRAM_BESR, status->besr & SDRAM_BESR_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) mtsdram(dcr_host, SDRAM_BEARL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) mtsdram(dcr_host, SDRAM_BEARH, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * ppc4xx_edac_handle_ce - handle controller correctable ECC error (CE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * @mci: A pointer to the EDAC memory controller instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) * associated with the correctable error being handled and reported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * @status: A pointer to the ECC status structure associated with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * the correctable error being handled and reported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) * This routine handles an ibm,sdram-4xx-ddr2 controller ECC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) * correctable error. Per the aforementioned discussion, there's not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * enough status available to use the full EDAC correctable error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) * interface, so we just pass driver-unique message to the "no info"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) ppc4xx_edac_handle_ce(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) const struct ppc4xx_ecc_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) int row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) char message[PPC4XX_EDAC_MESSAGE_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) ppc4xx_edac_generate_message(mci, status, message, sizeof(message));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) for (row = 0; row < mci->nr_csrows; row++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (ppc4xx_edac_check_bank_error(status, row))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) row, 0, -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) message, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) * ppc4xx_edac_handle_ue - handle controller uncorrectable ECC error (UE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) * @mci: A pointer to the EDAC memory controller instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) * associated with the uncorrectable error being handled and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) * reported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) * @status: A pointer to the ECC status structure associated with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) * the uncorrectable error being handled and reported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) * This routine handles an ibm,sdram-4xx-ddr2 controller ECC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * uncorrectable error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) ppc4xx_edac_handle_ue(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) const struct ppc4xx_ecc_status *status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) const u64 bear = ((u64)status->bearh << 32 | status->bearl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) const unsigned long page = bear >> PAGE_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) const unsigned long offset = bear & ~PAGE_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) int row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) char message[PPC4XX_EDAC_MESSAGE_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) ppc4xx_edac_generate_message(mci, status, message, sizeof(message));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) for (row = 0; row < mci->nr_csrows; row++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (ppc4xx_edac_check_bank_error(status, row))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) page, offset, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) row, 0, -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) message, "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) * ppc4xx_edac_check - check controller for ECC errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) * @mci: A pointer to the EDAC memory controller instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * associated with the ibm,sdram-4xx-ddr2 controller being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * checked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * This routine is used to check and post ECC errors and is called by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * both the EDAC polling thread and this driver's CE and UE interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) ppc4xx_edac_check(struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) static unsigned int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) struct ppc4xx_ecc_status status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) ppc4xx_ecc_get_status(mci, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) #ifdef DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (count++ % 30 == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) ppc4xx_ecc_dump_status(mci, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (status.ecces & SDRAM_ECCES_UE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) ppc4xx_edac_handle_ue(mci, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (status.ecces & SDRAM_ECCES_CE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) ppc4xx_edac_handle_ce(mci, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) ppc4xx_ecc_clear_status(mci, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * ppc4xx_edac_isr - SEC (CE) and DED (UE) interrupt service routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) * @irq: The virtual interrupt number being serviced.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * @dev_id: A pointer to the EDAC memory controller instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) * associated with the interrupt being handled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) * This routine implements the interrupt handler for both correctable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * (CE) and uncorrectable (UE) ECC errors for the ibm,sdram-4xx-ddr2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) * controller. It simply calls through to the same routine used during
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) * polling to check, report and clear the ECC status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) * Unconditionally returns IRQ_HANDLED.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) static irqreturn_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) ppc4xx_edac_isr(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) struct mem_ctl_info *mci = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) ppc4xx_edac_check(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * ppc4xx_edac_get_dtype - return the controller memory width
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * @mcopt1: The 32-bit Memory Controller Option 1 register value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * currently set for the controller, from which the width
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) * is derived.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * This routine returns the EDAC device type width appropriate for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) * current controller configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * TODO: This needs to be conditioned dynamically through feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * flags or some such when other controller variants are supported as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * the 405EX[r] is 16-/32-bit and the others are 32-/64-bit with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * 16- and 64-bit field definition/value/enumeration (b1) overloaded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) * among them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * Returns a device type width enumeration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) static enum dev_type ppc4xx_edac_get_dtype(u32 mcopt1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) switch (mcopt1 & SDRAM_MCOPT1_WDTH_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) case SDRAM_MCOPT1_WDTH_16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return DEV_X2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) case SDRAM_MCOPT1_WDTH_32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return DEV_X4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return DEV_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) * ppc4xx_edac_get_mtype - return controller memory type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * @mcopt1: The 32-bit Memory Controller Option 1 register value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) * currently set for the controller, from which the memory type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) * is derived.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * This routine returns the EDAC memory type appropriate for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * current controller configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * Returns a memory type enumeration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) static enum mem_type ppc4xx_edac_get_mtype(u32 mcopt1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) bool rden = ((mcopt1 & SDRAM_MCOPT1_RDEN_MASK) == SDRAM_MCOPT1_RDEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) switch (mcopt1 & SDRAM_MCOPT1_DDR_TYPE_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) case SDRAM_MCOPT1_DDR2_TYPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return rden ? MEM_RDDR2 : MEM_DDR2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) case SDRAM_MCOPT1_DDR1_TYPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return rden ? MEM_RDDR : MEM_DDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return MEM_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) * ppc4xx_edac_init_csrows - initialize driver instance rows
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) * @mci: A pointer to the EDAC memory controller instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) * associated with the ibm,sdram-4xx-ddr2 controller for which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) * the csrows (i.e. banks/ranks) are being initialized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * @mcopt1: The 32-bit Memory Controller Option 1 register value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) * currently set for the controller, from which bank width
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) * and memory typ information is derived.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) * This routine initializes the virtual "chip select rows" associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) * with the EDAC memory controller instance. An ibm,sdram-4xx-ddr2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) * controller bank/rank is mapped to a row.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) * Returns 0 if OK; otherwise, -EINVAL if the memory bank size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * configuration cannot be determined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) static int ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) const struct ppc4xx_edac_pdata *pdata = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) enum mem_type mtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) enum dev_type dtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) enum edac_type edac_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) int row, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) u32 mbxcf, size, nr_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) /* Establish the memory type and width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) mtype = ppc4xx_edac_get_mtype(mcopt1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) dtype = ppc4xx_edac_get_dtype(mcopt1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) /* Establish EDAC mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (mci->edac_cap & EDAC_FLAG_SECDED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) edac_mode = EDAC_SECDED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) else if (mci->edac_cap & EDAC_FLAG_EC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) edac_mode = EDAC_EC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) edac_mode = EDAC_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * Initialize each chip select row structure which correspond
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) * 1:1 with a controller bank/rank.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) for (row = 0; row < mci->nr_csrows; row++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct csrow_info *csi = mci->csrows[row];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) * Get the configuration settings for this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) * row/bank/rank and skip disabled banks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) mbxcf = mfsdram(&pdata->dcr_host, SDRAM_MBXCF(row));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) if ((mbxcf & SDRAM_MBCF_BE_MASK) != SDRAM_MBCF_BE_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) /* Map the bank configuration size setting to pages. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) size = mbxcf & SDRAM_MBCF_SZ_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) case SDRAM_MBCF_SZ_4MB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) case SDRAM_MBCF_SZ_8MB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) case SDRAM_MBCF_SZ_16MB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) case SDRAM_MBCF_SZ_32MB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) case SDRAM_MBCF_SZ_64MB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) case SDRAM_MBCF_SZ_128MB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) case SDRAM_MBCF_SZ_256MB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) case SDRAM_MBCF_SZ_512MB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) case SDRAM_MBCF_SZ_1GB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) case SDRAM_MBCF_SZ_2GB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) case SDRAM_MBCF_SZ_4GB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) case SDRAM_MBCF_SZ_8GB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) nr_pages = SDRAM_MBCF_SZ_TO_PAGES(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) ppc4xx_edac_mc_printk(KERN_ERR, mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) "Unrecognized memory bank %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) "size 0x%08x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) row, SDRAM_MBCF_SZ_DECODE(size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) status = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) * It's unclear exactly what grain should be set to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) * here. The SDRAM_ECCES register allows resolution of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * an error down to a nibble which would potentially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) * argue for a grain of '1' byte, even though we only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * know the associated address for uncorrectable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) * errors. This value is not used at present for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * anything other than error reporting so getting it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) * wrong should be of little consequence. Other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) * possible values would be the PLB width (16), the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * page size (PAGE_SIZE) or the memory width (2 or 4).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) for (j = 0; j < csi->nr_channels; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) struct dimm_info *dimm = csi->channels[j]->dimm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) dimm->nr_pages = nr_pages / csi->nr_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) dimm->grain = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) dimm->mtype = mtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) dimm->dtype = dtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) dimm->edac_mode = edac_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) * ppc4xx_edac_mc_init - initialize driver instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) * @mci: A pointer to the EDAC memory controller instance being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) * initialized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) * @op: A pointer to the OpenFirmware device tree node associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) * with the controller this EDAC instance is bound to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) * @dcr_host: A pointer to the DCR data containing the DCR mapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) * for this controller instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) * @mcopt1: The 32-bit Memory Controller Option 1 register value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) * currently set for the controller, from which ECC capabilities
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) * and scrub mode are derived.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) * This routine performs initialization of the EDAC memory controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) * instance and related driver-private data associated with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) * ibm,sdram-4xx-ddr2 memory controller the instance is bound to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) * Returns 0 if OK; otherwise, < 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) static int ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) struct platform_device *op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) const dcr_host_t *dcr_host, u32 mcopt1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) const u32 memcheck = (mcopt1 & SDRAM_MCOPT1_MCHK_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) struct ppc4xx_edac_pdata *pdata = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) const struct device_node *np = op->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (of_match_device(ppc4xx_edac_match, &op->dev) == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) /* Initial driver pointers and private data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) mci->pdev = &op->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) dev_set_drvdata(mci->pdev, mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) pdata = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) pdata->dcr_host = *dcr_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) /* Initialize controller capabilities and configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) mci->mtype_cap = (MEM_FLAG_DDR | MEM_FLAG_RDDR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) MEM_FLAG_DDR2 | MEM_FLAG_RDDR2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) mci->edac_ctl_cap = (EDAC_FLAG_NONE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) EDAC_FLAG_EC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) EDAC_FLAG_SECDED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) mci->scrub_cap = SCRUB_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) mci->scrub_mode = SCRUB_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) * Update the actual capabilites based on the MCOPT1[MCHK]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) * settings. Scrubbing is only useful if reporting is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) switch (memcheck) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) case SDRAM_MCOPT1_MCHK_CHK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) mci->edac_cap = EDAC_FLAG_EC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) case SDRAM_MCOPT1_MCHK_CHK_REP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) mci->edac_cap = (EDAC_FLAG_EC | EDAC_FLAG_SECDED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) mci->scrub_mode = SCRUB_SW_SRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) mci->edac_cap = EDAC_FLAG_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) /* Initialize strings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) mci->mod_name = PPC4XX_EDAC_MODULE_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) mci->ctl_name = ppc4xx_edac_match->compatible,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) mci->dev_name = np->full_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) /* Initialize callbacks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) mci->edac_check = ppc4xx_edac_check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) mci->ctl_page_to_phys = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) /* Initialize chip select rows */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) status = ppc4xx_edac_init_csrows(mci, mcopt1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) ppc4xx_edac_mc_printk(KERN_ERR, mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) "Failed to initialize rows!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) * ppc4xx_edac_register_irq - setup and register controller interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) * @op: A pointer to the OpenFirmware device tree node associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) * with the controller this EDAC instance is bound to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) * @mci: A pointer to the EDAC memory controller instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) * associated with the ibm,sdram-4xx-ddr2 controller for which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) * interrupts are being registered.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) * This routine parses the correctable (CE) and uncorrectable error (UE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) * interrupts from the device tree node and maps and assigns them to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) * the associated EDAC memory controller instance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) * Returns 0 if OK; otherwise, -ENODEV if the interrupts could not be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) * mapped and assigned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) static int ppc4xx_edac_register_irq(struct platform_device *op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) struct mem_ctl_info *mci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) int ded_irq, sec_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) struct ppc4xx_edac_pdata *pdata = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) struct device_node *np = op->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) ded_irq = irq_of_parse_and_map(np, INTMAP_ECCDED_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) sec_irq = irq_of_parse_and_map(np, INTMAP_ECCSEC_INDEX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) if (!ded_irq || !sec_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) ppc4xx_edac_mc_printk(KERN_ERR, mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) "Unable to map interrupts.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) status = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) status = request_irq(ded_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) ppc4xx_edac_isr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) "[EDAC] MC ECCDED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) ppc4xx_edac_mc_printk(KERN_ERR, mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) "Unable to request irq %d for ECC DED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) ded_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) status = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) status = request_irq(sec_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) ppc4xx_edac_isr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) "[EDAC] MC ECCSEC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) if (status < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) ppc4xx_edac_mc_printk(KERN_ERR, mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) "Unable to request irq %d for ECC SEC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) sec_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) status = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) goto fail2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) ppc4xx_edac_mc_printk(KERN_INFO, mci, "ECCDED irq is %d\n", ded_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) ppc4xx_edac_mc_printk(KERN_INFO, mci, "ECCSEC irq is %d\n", sec_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) pdata->irqs.ded = ded_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) pdata->irqs.sec = sec_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) fail2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) free_irq(sec_irq, mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) fail1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) free_irq(ded_irq, mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) * ppc4xx_edac_map_dcrs - locate and map controller registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) * @np: A pointer to the device tree node containing the DCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) * resources to map.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) * @dcr_host: A pointer to the DCR data to populate with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) * DCR mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) * This routine attempts to locate in the device tree and map the DCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) * register resources associated with the controller's indirect DCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) * address and data windows.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) * Returns 0 if the DCRs were successfully mapped; otherwise, < 0 on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) * error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) static int ppc4xx_edac_map_dcrs(const struct device_node *np,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) dcr_host_t *dcr_host)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) unsigned int dcr_base, dcr_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) if (np == NULL || dcr_host == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) /* Get the DCR resource extent and sanity check the values. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) dcr_base = dcr_resource_start(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) dcr_len = dcr_resource_len(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) if (dcr_base == 0 || dcr_len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) ppc4xx_edac_printk(KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) "Failed to obtain DCR property.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if (dcr_len != SDRAM_DCR_RESOURCE_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) ppc4xx_edac_printk(KERN_ERR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) "Unexpected DCR length %d, expected %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) dcr_len, SDRAM_DCR_RESOURCE_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /* Attempt to map the DCR extent. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) *dcr_host = dcr_map(np, dcr_base, dcr_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) if (!DCR_MAP_OK(*dcr_host)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) ppc4xx_edac_printk(KERN_INFO, "Failed to map DCRs.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) * ppc4xx_edac_probe - check controller and bind driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) * @op: A pointer to the OpenFirmware device tree node associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) * with the controller being probed for driver binding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) * This routine probes a specific ibm,sdram-4xx-ddr2 controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) * instance for binding with the driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) * Returns 0 if the controller instance was successfully bound to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) * driver; otherwise, < 0 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) static int ppc4xx_edac_probe(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) int status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) u32 mcopt1, memcheck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) dcr_host_t dcr_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) const struct device_node *np = op->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) struct mem_ctl_info *mci = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) struct edac_mc_layer layers[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) static int ppc4xx_edac_instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) * At this point, we only support the controller realized on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) * the AMCC PPC 405EX[r]. Reject anything else.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) if (!of_device_is_compatible(np, "ibm,sdram-405ex") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) !of_device_is_compatible(np, "ibm,sdram-405exr")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) ppc4xx_edac_printk(KERN_NOTICE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) "Only the PPC405EX[r] is supported.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) * Next, get the DCR property and attempt to map it so that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) * can probe the controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) status = ppc4xx_edac_map_dcrs(np, &dcr_host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * First determine whether ECC is enabled at all. If not,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * there is no useful checking or monitoring that can be done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) * for this controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) mcopt1 = mfsdram(&dcr_host, SDRAM_MCOPT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) memcheck = (mcopt1 & SDRAM_MCOPT1_MCHK_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) if (memcheck == SDRAM_MCOPT1_MCHK_NON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) ppc4xx_edac_printk(KERN_INFO, "%pOF: No ECC memory detected or "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) "ECC is disabled.\n", np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) status = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) * At this point, we know ECC is enabled, allocate an EDAC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) * controller instance and perform the appropriate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) * initialization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) layers[0].size = ppc4xx_edac_nr_csrows;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) layers[0].is_virt_csrow = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) layers[1].type = EDAC_MC_LAYER_CHANNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) layers[1].size = ppc4xx_edac_nr_chans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) layers[1].is_virt_csrow = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) mci = edac_mc_alloc(ppc4xx_edac_instance, ARRAY_SIZE(layers), layers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) sizeof(struct ppc4xx_edac_pdata));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) if (mci == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) ppc4xx_edac_printk(KERN_ERR, "%pOF: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) "Failed to allocate EDAC MC instance!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) status = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) status = ppc4xx_edac_mc_init(mci, op, &dcr_host, mcopt1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) if (status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) ppc4xx_edac_mc_printk(KERN_ERR, mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) "Failed to initialize instance!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) * We have a valid, initialized EDAC instance bound to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) * controller. Attempt to register it with the EDAC subsystem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) * and, if necessary, register interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (edac_mc_add_mc(mci)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) ppc4xx_edac_mc_printk(KERN_ERR, mci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) "Failed to add instance!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) status = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) if (edac_op_state == EDAC_OPSTATE_INT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) status = ppc4xx_edac_register_irq(op, mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) if (status)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) goto fail1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) ppc4xx_edac_instance++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) fail1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) edac_mc_del_mc(mci->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) edac_mc_free(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) * ppc4xx_edac_remove - unbind driver from controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) * @op: A pointer to the OpenFirmware device tree node associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) * with the controller this EDAC instance is to be unbound/removed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) * from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) * This routine unbinds the EDAC memory controller instance associated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) * with the specified ibm,sdram-4xx-ddr2 controller described by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) * OpenFirmware device tree node passed as a parameter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) * Unconditionally returns 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) ppc4xx_edac_remove(struct platform_device *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) struct mem_ctl_info *mci = dev_get_drvdata(&op->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) struct ppc4xx_edac_pdata *pdata = mci->pvt_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (edac_op_state == EDAC_OPSTATE_INT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) free_irq(pdata->irqs.sec, mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) free_irq(pdata->irqs.ded, mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) dcr_unmap(pdata->dcr_host, SDRAM_DCR_RESOURCE_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) edac_mc_del_mc(mci->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) edac_mc_free(mci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) * ppc4xx_edac_opstate_init - initialize EDAC reporting method
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) * This routine ensures that the EDAC memory controller reporting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) * method is mapped to a sane value as the EDAC core defines the value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) * to EDAC_OPSTATE_INVAL by default. We don't call the global
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) * opstate_init as that defaults to polling and we want interrupt as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) * the default.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) static inline void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) ppc4xx_edac_opstate_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) switch (edac_op_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) case EDAC_OPSTATE_POLL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) case EDAC_OPSTATE_INT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) edac_op_state = EDAC_OPSTATE_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) ppc4xx_edac_printk(KERN_INFO, "Reporting type: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) ((edac_op_state == EDAC_OPSTATE_POLL) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) EDAC_OPSTATE_POLL_STR :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) ((edac_op_state == EDAC_OPSTATE_INT) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) EDAC_OPSTATE_INT_STR :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) EDAC_OPSTATE_UNKNOWN_STR)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) * ppc4xx_edac_init - driver/module insertion entry point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) * This routine is the driver/module insertion entry point. It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) * initializes the EDAC memory controller reporting state and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) * registers the driver as an OpenFirmware device tree platform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) * driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) static int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) ppc4xx_edac_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) ppc4xx_edac_printk(KERN_INFO, PPC4XX_EDAC_MODULE_REVISION "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) ppc4xx_edac_opstate_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) return platform_driver_register(&ppc4xx_edac_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) * ppc4xx_edac_exit - driver/module removal entry point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) * This routine is the driver/module removal entry point. It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) * unregisters the driver as an OpenFirmware device tree platform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) * driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) static void __exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) ppc4xx_edac_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) platform_driver_unregister(&ppc4xx_edac_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) module_init(ppc4xx_edac_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) module_exit(ppc4xx_edac_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) MODULE_AUTHOR("Grant Erickson <gerickson@nuovations.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) MODULE_DESCRIPTION("EDAC MC Driver for the PPC4xx IBM DDR2 Memory Controller");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) module_param(edac_op_state, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting State: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) "0=" EDAC_OPSTATE_POLL_STR ", 2=" EDAC_OPSTATE_INT_STR);