151 lines
3.6 KiB
C
151 lines
3.6 KiB
C
|
/* Copyright 2014-2016 IBM Corp.
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||
|
* implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* imitations under the License.
|
||
|
*/
|
||
|
|
||
|
#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;
|
||
|
}
|