1 /* Copyright 2014-2016 IBM Corp. 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 * implied. 13 * See the License for the specific language governing permissions and 14 * imitations under the License. 15 */ 16 17 #include <stdint.h> 18 #include <stdio.h> 19 #include <stdbool.h> 20 #include <stdlib.h> 21 #include <time.h> 22 23 #include "xscom.h" 24 25 #define DBG(fmt...) do { if (verbose) printf(fmt); } while(0) 26 #define ERR(fmt...) do { fprintf(stderr, fmt); } while(0) 27 28 #define OCB_PIB_BASE_P8 0x0006B000 29 #define OCB_PIB_BASE_P9 0x0006D000 30 31 #define OCBCSR0 0x11 32 #define OCBCSR0_AND 0x12 33 #define OCBCSR0_OR 0x13 34 #define OCB_STREAM_MODE PPC_BIT(4) 35 #define OCB_STREAM_TYPE PPC_BIT(5) 36 #define OCBAR0 0x10 37 #define OCBDR0 0x15 38 39 #define PVR_TYPE_P8E 0x004b /* Murano */ 40 #define PVR_TYPE_P8 0x004d /* Venice */ 41 #define PVR_TYPE_P8NVL 0x004c /* Naples */ 42 #define PVR_TYPE_P9 0x004e 43 #define PVR_TYPE_P9P 0x004f /* Axone */ 44 45 #ifdef __powerpc__ 46 static uint64_t get_xscom_base(void) 47 { 48 unsigned int pvr; 49 50 asm volatile("mfpvr %0" : "=r" (pvr)); 51 52 switch (pvr >> 16) { 53 case PVR_TYPE_P9: 54 case PVR_TYPE_P9P: 55 return OCB_PIB_BASE_P9; 56 57 case PVR_TYPE_P8E: 58 case PVR_TYPE_P8: 59 case PVR_TYPE_P8NVL: 60 return OCB_PIB_BASE_P8; 61 } 62 63 ERR("Unknown processor, exiting\n"); 64 exit(1); 65 return 0; 66 } 67 #else 68 /* Just so it compiles on x86 */ 69 static uint64_t get_xscom_base(void) { return 0; } 70 #endif 71 72 int sram_read(uint32_t chip_id, int chan, uint32_t addr, uint64_t *val) 73 { 74 uint64_t sdat, base = get_xscom_base(); 75 uint32_t coff = chan * 0x20; 76 int rc; 77 78 /* Read for debug purposes */ 79 rc = xscom_read(chip_id, base + OCBCSR0 + coff, &sdat); 80 if (rc) { 81 ERR("xscom OCBCSR0 read error %d\n", rc); 82 return -1; 83 } 84 85 /* Create an AND mask to clear bit 4 and 5 and poke the AND register */ 86 sdat = ~(OCB_STREAM_MODE | OCB_STREAM_TYPE); 87 rc = xscom_write(chip_id, base + OCBCSR0_AND + coff, sdat); 88 if (rc) { 89 ERR("xscom OCBCSR0_AND write error %d\n", rc); 90 return -1; 91 } 92 93 sdat = ((uint64_t)addr) << 32; 94 rc = xscom_write(chip_id, base + OCBAR0 + coff, sdat); 95 if (rc) { 96 ERR("xscom OCBAR0 write error %d\n", rc); 97 return -1; 98 } 99 100 rc = xscom_read(chip_id, base + OCBDR0 + coff, val); 101 if (rc) { 102 ERR("xscom OCBDR0 read error %d\n", rc); 103 return -1; 104 } 105 return 0; 106 } 107 108 int sram_write(uint32_t chip_id, int chan, uint32_t addr, uint64_t val) 109 { 110 uint64_t sdat, base = get_xscom_base(); 111 uint32_t coff = chan * 0x20; 112 int rc; 113 114 #if 0 115 if (dummy) { 116 printf("[dummy] write chip %d OCC sram 0x%08x = %016lx\n", 117 chip_id, addr, val); 118 return 0; 119 } 120 #endif 121 122 /* Read for debug purposes */ 123 rc = xscom_read(chip_id, base + OCBCSR0 + coff, &sdat); 124 if (rc) { 125 ERR("xscom OCBCSR0 read error %d\n", rc); 126 return -1; 127 } 128 129 /* Create an AND mask to clear bit 4 and 5 and poke the AND register */ 130 sdat = ~(OCB_STREAM_MODE | OCB_STREAM_TYPE); 131 rc = xscom_write(chip_id, base + OCBCSR0_AND + coff, sdat); 132 if (rc) { 133 ERR("xscom OCBCSR0_AND write error %d\n", rc); 134 return -1; 135 } 136 137 sdat = ((uint64_t)addr) << 32; 138 rc = xscom_write(chip_id, base + OCBAR0 + coff, sdat); 139 if (rc) { 140 ERR("xscom OCBAR0 write error %d\n", rc); 141 return -1; 142 } 143 144 rc = xscom_write(chip_id, base + OCBDR0 + coff, val); 145 if (rc) { 146 ERR("xscom OCBDR0 write error %d\n", rc); 147 return -1; 148 } 149 return 0; 150 } 151