blob: 87df70e10ba0e95856ce772fee0d58e7dc31ff09 [file] [log] [blame]
// 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 */
#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:
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;
}