diff options
Diffstat (limited to 'roms/skiboot/external/xscom-utils/sram.c')
-rw-r--r-- | roms/skiboot/external/xscom-utils/sram.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/roms/skiboot/external/xscom-utils/sram.c b/roms/skiboot/external/xscom-utils/sram.c new file mode 100644 index 000000000..efe08d8e7 --- /dev/null +++ b/roms/skiboot/external/xscom-utils/sram.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* Copyright 2014-2019 IBM Corp. */ + +#include <stdint.h> +#include <stdio.h> +#include <stdbool.h> +#include <stdlib.h> +#include <time.h> + +#include "xscom.h" + +#define DBG(fmt...) do { if (verbose) printf(fmt); } while(0) +#define ERR(fmt...) do { fprintf(stderr, fmt); } while(0) + +#define OCB_PIB_BASE_P8 0x0006B000 +#define OCB_PIB_BASE_P9 0x0006D000 + +#define OCBCSR0 0x11 +#define OCBCSR0_AND 0x12 +#define OCBCSR0_OR 0x13 +#define OCB_STREAM_MODE PPC_BIT(4) +#define OCB_STREAM_TYPE PPC_BIT(5) +#define OCBAR0 0x10 +#define OCBDR0 0x15 + +#define PVR_TYPE_P8E 0x004b /* Murano */ +#define PVR_TYPE_P8 0x004d /* Venice */ +#define PVR_TYPE_P8NVL 0x004c /* Naples */ +#define PVR_TYPE_P9 0x004e +#define PVR_TYPE_P9P 0x004f /* Axone */ +#define PVR_TYPE_P10 0x0080 + +#ifdef __powerpc__ +static uint64_t get_xscom_base(void) +{ + unsigned int pvr; + + asm volatile("mfpvr %0" : "=r" (pvr)); + + switch (pvr >> 16) { + case PVR_TYPE_P9: + case PVR_TYPE_P9P: + case PVR_TYPE_P10: /* P10 OCB_PIB OCC Control Register is same for P9 and P10 */ + return OCB_PIB_BASE_P9; + + case PVR_TYPE_P8E: + case PVR_TYPE_P8: + case PVR_TYPE_P8NVL: + return OCB_PIB_BASE_P8; + } + + ERR("Unknown processor, exiting\n"); + exit(1); + return 0; +} +#else +/* Just so it compiles on x86 */ +static uint64_t get_xscom_base(void) { return 0; } +#endif + +int sram_read(uint32_t chip_id, int chan, uint32_t addr, uint64_t *val) +{ + uint64_t sdat, base = get_xscom_base(); + uint32_t coff = chan * 0x20; + int rc; + + /* Read for debug purposes */ + rc = xscom_read(chip_id, base + OCBCSR0 + coff, &sdat); + if (rc) { + ERR("xscom OCBCSR0 read error %d\n", rc); + return -1; + } + + /* Create an AND mask to clear bit 4 and 5 and poke the AND register */ + sdat = ~(OCB_STREAM_MODE | OCB_STREAM_TYPE); + rc = xscom_write(chip_id, base + OCBCSR0_AND + coff, sdat); + if (rc) { + ERR("xscom OCBCSR0_AND write error %d\n", rc); + return -1; + } + + sdat = ((uint64_t)addr) << 32; + rc = xscom_write(chip_id, base + OCBAR0 + coff, sdat); + if (rc) { + ERR("xscom OCBAR0 write error %d\n", rc); + return -1; + } + + rc = xscom_read(chip_id, base + OCBDR0 + coff, val); + if (rc) { + ERR("xscom OCBDR0 read error %d\n", rc); + return -1; + } + return 0; +} + +int sram_write(uint32_t chip_id, int chan, uint32_t addr, uint64_t val) +{ + uint64_t sdat, base = get_xscom_base(); + uint32_t coff = chan * 0x20; + int rc; + +#if 0 + if (dummy) { + printf("[dummy] write chip %d OCC sram 0x%08x = %016lx\n", + chip_id, addr, val); + return 0; + } +#endif + + /* Read for debug purposes */ + rc = xscom_read(chip_id, base + OCBCSR0 + coff, &sdat); + if (rc) { + ERR("xscom OCBCSR0 read error %d\n", rc); + return -1; + } + + /* Create an AND mask to clear bit 4 and 5 and poke the AND register */ + sdat = ~(OCB_STREAM_MODE | OCB_STREAM_TYPE); + rc = xscom_write(chip_id, base + OCBCSR0_AND + coff, sdat); + if (rc) { + ERR("xscom OCBCSR0_AND write error %d\n", rc); + return -1; + } + + sdat = ((uint64_t)addr) << 32; + rc = xscom_write(chip_id, base + OCBAR0 + coff, sdat); + if (rc) { + ERR("xscom OCBAR0 write error %d\n", rc); + return -1; + } + + rc = xscom_write(chip_id, base + OCBDR0 + coff, val); + if (rc) { + ERR("xscom OCBDR0 write error %d\n", rc); + return -1; + } + return 0; +} |