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