Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /* Copyright 2017-2019 IBM Corp. */
3 : :
4 : : #include <device.h>
5 : : #include <cpu.h>
6 : : #include <vpd.h>
7 : : #include <interrupts.h>
8 : : #include <ccan/str/str.h>
9 : : #include <chip.h>
10 : : #include <i2c.h>
11 : :
12 : : #include "spira.h"
13 : : #include "hdata.h"
14 : :
15 : : /*
16 : : * These should probably be in hw/p8-i2c.c. However, that would require the HDAT
17 : : * test to #include hw/p8-i2c.c which is probably going to be more trouble than
18 : : * it's worth. So these helpers are here instead.
19 : : */
20 : 0 : struct dt_node *p8_i2c_add_master_node(struct dt_node *xscom, int eng_id)
21 : : {
22 : : uint64_t clk, size, xscom_base;
23 : : struct dt_node *i2cm;
24 : :
25 : 0 : dt_for_each_compatible(xscom, i2cm, "ibm,power8-i2cm")
26 : 0 : if (dt_prop_get_u32(i2cm, "chip-engine#") == eng_id)
27 : 0 : return i2cm;
28 : :
29 : : /* XXX: Might need to be updated for new chips */
30 : 0 : if (proc_gen >= proc_gen_p9)
31 : 0 : size = 0x1000;
32 : : else
33 : 0 : size = 0x20;
34 : :
35 : 0 : xscom_base = 0xa0000 + size * eng_id;
36 : :
37 : 0 : i2cm = dt_new_addr(xscom, "i2cm", xscom_base);
38 : 0 : if (!i2cm)
39 : 0 : return NULL;
40 : :
41 : 0 : if (proc_gen >= proc_gen_p9) {
42 : 0 : dt_add_property_strings(i2cm, "compatible", "ibm,power8-i2cm",
43 : : "ibm,power9-i2cm");
44 : : } else {
45 : 0 : dt_add_property_strings(i2cm, "compatible", "ibm,power8-i2cm");
46 : : }
47 : :
48 : 0 : dt_add_property_cells(i2cm, "reg", xscom_base, size);
49 : 0 : dt_add_property_cells(i2cm, "#size-cells", 0);
50 : 0 : dt_add_property_cells(i2cm, "#address-cells", 1);
51 : 0 : dt_add_property_cells(i2cm, "chip-engine#", eng_id);
52 : :
53 : : /*
54 : : * The i2cm runs at 1/4th the PIB frequency. If we don't know the PIB
55 : : * frequency then pick 150MHz which should be in the right ballpark.
56 : : */
57 : 0 : clk = dt_prop_get_u64_def(xscom, "bus-frequency", 0);
58 : 0 : if (clk)
59 : 0 : dt_add_property_cells(i2cm, "clock-frequency", clk / 4);
60 : : else
61 : 0 : dt_add_property_cells(i2cm, "clock-frequency", 150000000);
62 : :
63 : 0 : return i2cm;
64 : : }
65 : :
66 : 0 : struct dt_node *__p8_i2c_add_port_node(struct dt_node *master, int port_id,
67 : : uint32_t bus_speed)
68 : : {
69 : : struct dt_node *port;
70 : : uint32_t speed;
71 : :
72 : 0 : dt_for_each_child(master, port)
73 : 0 : if (dt_prop_get_u32(port, "reg") == port_id)
74 : 0 : goto check_speed;
75 : :
76 : 0 : port = dt_new_addr(master, "i2c-bus", port_id);
77 : 0 : if (!port)
78 : 0 : return NULL;
79 : :
80 : 0 : dt_add_property_cells(port, "reg", port_id);
81 : 0 : dt_add_property_cells(port, "#size-cells", 0);
82 : 0 : dt_add_property_cells(port, "#address-cells", 1);
83 : :
84 : : /* The P9 I2C master is fully compatible with the P8 one */
85 : 0 : if (proc_gen >= proc_gen_p9) {
86 : 0 : dt_add_property_strings(port, "compatible", "ibm,opal-i2c",
87 : : "ibm,power8-i2c-port", "ibm,power9-i2c-port");
88 : : } else {
89 : 0 : dt_add_property_strings(port, "compatible", "ibm,opal-i2c",
90 : : "ibm,power8-i2c-port");
91 : : }
92 : :
93 : 0 : check_speed:
94 : 0 : speed = dt_prop_get_u32_def(port, "bus-frequency", 0xffffffff);
95 : 0 : if (bus_speed < speed) {
96 : 0 : dt_check_del_prop(port, "bus-frequency");
97 : 0 : dt_add_property_cells(port, "bus-frequency", bus_speed);
98 : : }
99 : :
100 : 0 : return port;
101 : : }
102 : :
103 : :
104 : 0 : struct dt_node *p8_i2c_add_port_node(struct dt_node *xscom, int eng_id,
105 : : int port_id, uint32_t bus_freq)
106 : : {
107 : : struct dt_node *i2cm;
108 : :
109 : 0 : i2cm = p8_i2c_add_master_node(xscom, eng_id);
110 : 0 : if (!i2cm)
111 : 0 : return NULL;
112 : :
113 : 0 : return __p8_i2c_add_port_node(i2cm, port_id, bus_freq);
114 : : }
115 : :
116 : : struct i2c_dev {
117 : : uint8_t i2cm_engine;
118 : : uint8_t i2cm_port;
119 : : __be16 i2c_bus_freq;
120 : :
121 : : /* i2c slave info */
122 : : uint8_t type;
123 : : uint8_t dev_addr;
124 : : uint8_t dev_port;
125 : : uint8_t __reserved;
126 : :
127 : : __be32 purpose;
128 : : __be32 i2c_link;
129 : : __be16 slca_index;
130 : : };
131 : :
132 : : struct hdat_i2c_type {
133 : : uint32_t id;
134 : : const char *name;
135 : : const char *compat;
136 : : };
137 : :
138 : : static struct hdat_i2c_type hdat_i2c_devs[] = {
139 : : { 0x1, "gpio", "nxp,pca9551" },
140 : : /* XXX: Please verify that all VPD EEPROMs are of this type */
141 : : { 0x2, "eeprom", "atmel,24c128" },
142 : : { 0x3, "tpm", "nuvoton,npct650" },
143 : : { 0x4, "i2c", NULL }, /* MEX-FPGA */
144 : : { 0x5, "i2c", NULL }, /* UCX90xx devs for PCI Hotplug */
145 : : { 0x6, "gpio", "nxp,pca9552" },
146 : : { 0x7, "gpio", "nxp,pca9553" },
147 : : { 0x8, "gpio", "nxp,pca9554" },
148 : : { 0x9, "gpio", "nxp,pca9555" },
149 : : { 0xa, "i2c", NULL }, /* SMP/OpenCAPI Cable */
150 : : { 0xb, "eeprom", "atmel,24c256" },
151 : : { 0xc, "i2c", NULL }, /* Thermal Sensor */
152 : : { 0xd, "eeprom", "atmel,24c04" },
153 : : { 0xe, "eeprom", "atmel,24c512" },
154 : : { 0xf, "eeprom", "atmel,24c32" },
155 : : { 0x10, "eeprom", "atmel,24c64" },
156 : : { 0x11, "eeprom", "atmel,24c16" },
157 : : { 0x12, "i2c", NULL }, /* NVDIA GPU */
158 : : { 0x13, "i2c", "nxp,lpc11u35" },
159 : : { 0x15, "tpm", "nuvoton,npct75x" },
160 : : };
161 : :
162 : : struct hdat_i2c_info {
163 : : uint32_t id;
164 : : bool allowed; /* true if the host may use the device */
165 : : const char *label;
166 : : };
167 : :
168 : : static struct hdat_i2c_info hdat_i2c_extra_info[] = {
169 : : { 0x1, false, "led-controller" },
170 : : { 0x2, false, "pci-hotplug-pgood" },
171 : : { 0x3, false, "pci-hotplug-control" },
172 : : { 0x4, true, "tpm" },
173 : : { 0x5, true, "module-vpd" },
174 : : { 0x6, true, "dimm-spd" },
175 : : { 0x7, true, "proc-vpd" },
176 : : { 0x8, false, "sbe-eeprom"},
177 : : { 0x9, true, "planar-vpd" },
178 : : { 0xa, false, "opencapi-topology" },
179 : : { 0xb, false, "opencapi-micro-reset" },
180 : : { 0xc, false, "nvlink-cable" },
181 : : { 0xd, false, "secure-window-open" },
182 : : { 0xe, false, "physical-presence" },
183 : : { 0xf, false, "mex-fpga" },
184 : : { 0x10, false, "thermal-sensor" },
185 : : { 0x11, false, "host-i2c-enable" },
186 : : { 0x12, false, "gpu-config" },
187 : : };
188 : :
189 : : /*
190 : : * this is pretty half-assed, to generate the labels properly we need to look
191 : : * up associated SLCA index and determine what kind of module the device is on
192 : : * and why
193 : : */
194 : 0 : static struct hdat_i2c_type *map_type(uint32_t type)
195 : : {
196 : : int i;
197 : :
198 : 0 : for (i = 0; i < ARRAY_SIZE(hdat_i2c_devs); i++)
199 : 0 : if (hdat_i2c_devs[i].id == type)
200 : 0 : return &hdat_i2c_devs[i];
201 : :
202 : 0 : return NULL;
203 : : }
204 : :
205 : 0 : static struct hdat_i2c_info *get_info(uint32_t type)
206 : : {
207 : : static struct hdat_i2c_info no_info =
208 : : { .id = 0x0, .allowed = false, .label = "" };
209 : : int i;
210 : :
211 : 0 : for (i = 0; i < ARRAY_SIZE(hdat_i2c_extra_info); i++)
212 : 0 : if (hdat_i2c_extra_info[i].id == type)
213 : 0 : return &hdat_i2c_extra_info[i];
214 : :
215 : 0 : return &no_info;
216 : : }
217 : :
218 : 0 : static bool is_zeros(const void *p, size_t size)
219 : : {
220 : 0 : const char *c = p;
221 : : size_t i;
222 : :
223 : 0 : for (i = 0; i < size; i++)
224 : 0 : if (c[i] != 0)
225 : 0 : return false;
226 : :
227 : 0 : return true;
228 : : }
229 : :
230 : : struct host_i2c_hdr {
231 : : const struct HDIF_array_hdr hdr;
232 : : __be32 version;
233 : : } __packed __align(0x4);
234 : :
235 : 0 : int parse_i2c_devs(const struct HDIF_common_hdr *hdr, int idata_index,
236 : : struct dt_node *xscom)
237 : : {
238 : : struct dt_node *bus, *node;
239 : : const struct hdat_i2c_type *type;
240 : : const struct hdat_i2c_info *info;
241 : : const struct i2c_dev *dev;
242 : : const char *name, *compat;
243 : : const struct host_i2c_hdr *ahdr;
244 : : uint32_t dev_addr;
245 : : uint32_t version;
246 : : uint32_t size;
247 : : uint32_t purpose;
248 : : int i, count;
249 : :
250 : : /*
251 : : * This code makes a few assumptions about XSCOM addrs, etc
252 : : * and will need updating for new processors
253 : : */
254 : 0 : assert(proc_gen == proc_gen_p9 || proc_gen == proc_gen_p10);
255 : :
256 : : /*
257 : : * Emit an error if we get a newer version. This is an interim measure
258 : : * until the new version format is finalised.
259 : : */
260 : 0 : ahdr = HDIF_get_idata(hdr, idata_index, &size);
261 : 0 : if (!ahdr || !size)
262 : 0 : return -1;
263 : :
264 : : /*
265 : : * Some hostboots don't correctly fill the version field. On these
266 : : * the offset from the start of the header to the start of the array
267 : : * is 16 bytes.
268 : : */
269 : 0 : if (be32_to_cpu(ahdr->hdr.offset) == 16) {
270 : 0 : version = 1;
271 : 0 : prerror("I2C: HDAT device array has no version! Assuming v1\n");
272 : : } else {
273 : 0 : version = be32_to_cpu(ahdr->version);
274 : : }
275 : :
276 : 0 : if (version == 2) {
277 : 0 : prlog(PR_INFO, "I2C: v%d found, but not supported. Parsing as v1\n",
278 : : version);
279 : 0 : } else if (version > 2) {
280 : 0 : prerror("I2C: v%d found, but not supported! THIS IS A BUG\n",
281 : : version);
282 : 0 : return -1;
283 : : }
284 : :
285 : 0 : count = HDIF_get_iarray_size(hdr, idata_index);
286 : 0 : for (i = 0; i < count; i++) {
287 : 0 : dev = HDIF_get_iarray_item(hdr, idata_index, i, &size);
288 : :
289 : : /*
290 : : * XXX: Some broken hostboots populate i2c devs with zeros.
291 : : * Workaround them for now.
292 : : */
293 : 0 : if (is_zeros(dev, size)) {
294 : 0 : prerror("I2C: Ignoring broken i2c dev %d\n", i);
295 : 0 : continue;
296 : : }
297 : :
298 : : /*
299 : : * On some systems the CFAM I2C master is represented in the
300 : : * host I2C table as engine 6. There are only 4 (0, 1, 2, 3)
301 : : * engines accessible to the host via XSCOM so filter out
302 : : * engines outside this range so we don't create bogus
303 : : * i2cm@<addr> nodes.
304 : : */
305 : 0 : if (dev->i2cm_engine >= 4 &&
306 : 0 : (proc_gen == proc_gen_p9 || proc_gen == proc_gen_p10))
307 : 0 : continue;
308 : :
309 : 0 : bus = p8_i2c_add_port_node(xscom, dev->i2cm_engine, dev->i2cm_port,
310 : 0 : be16_to_cpu(dev->i2c_bus_freq) * 1000);
311 : :
312 : 0 : if (!bus) {
313 : 0 : prerror("Unable to add node for e%dp%d under %s\n",
314 : : dev->i2cm_engine, dev->i2cm_port, xscom->name);
315 : 0 : continue;
316 : : }
317 : :
318 : : /*
319 : : * Looks like hostboot gives the address as an 8 bit, left
320 : : * justified quantity (i.e it includes the R/W bit). So we need
321 : : * to strip it off to get an address linux can use.
322 : : */
323 : 0 : dev_addr = dev->dev_addr >> 1;
324 : :
325 : 0 : purpose = be32_to_cpu(dev->purpose);
326 : 0 : type = map_type(dev->type);
327 : 0 : info = get_info(purpose);
328 : :
329 : : /* HACK: Hostboot doesn't export the correct type information
330 : : * for the DIMM SPD EEPROMs. This is a problem because SPD
331 : : * EEPROMs have a different wire protocol to the atmel,24XXXX
332 : : * series. The main difference being that SPD EEPROMs have an
333 : : * 8bit offset rather than a 16bit offset. This means that the
334 : : * driver will send 2 bytes when doing a random read,
335 : : * potentially overwriting part of the SPD information.
336 : : *
337 : : * Just to make things interested the FSP also gets the device
338 : : * type wrong. To work around both just set the device-type to
339 : : * "spd" for anything in the 0x50 to 0x57 range since that's the
340 : : * SPD eeprom range.
341 : : *
342 : : * XXX: Future chips might not use engine 3 for the DIMM buses.
343 : : */
344 : 0 : if (dev->i2cm_engine == 3 && dev_addr >= 0x50
345 : 0 : && dev_addr < 0x58) {
346 : 0 : compat = "spd";
347 : 0 : name = "eeprom";
348 : 0 : } else if (type) {
349 : 0 : compat = type->compat;
350 : 0 : name = type->name;
351 : : } else {
352 : 0 : name = "unknown";
353 : 0 : compat = NULL;
354 : : }
355 : :
356 : : /*
357 : : * An i2c device is unknown if either the i2c device list is
358 : : * outdated or the device is marked as unknown (0xFF) in the
359 : : * hdat. Log both cases to see what/where/why.
360 : : */
361 : 0 : if (!type || dev->type == 0xFF) {
362 : 0 : prlog(PR_NOTICE, "HDAT I2C: found e%dp%d - %s@%x dp:%02x (%#x:%s)\n",
363 : : dev->i2cm_engine, dev->i2cm_port, name, dev_addr,
364 : : dev->dev_port, purpose, info->label);
365 : 0 : continue;
366 : : }
367 : :
368 : 0 : prlog(PR_DEBUG, "HDAT I2C: found e%dp%d - %s@%x dp:%02x (%#x:%s)\n",
369 : : dev->i2cm_engine, dev->i2cm_port, name, dev_addr,
370 : : dev->dev_port, purpose, info->label);
371 : :
372 : : /*
373 : : * Multi-port device require special handling since we need to
374 : : * generate the device-specific DT bindings. For now we're just
375 : : * going to ignore them since these devices are owned by FW
376 : : * any way.
377 : : */
378 : 0 : if (dev->dev_port != 0xff)
379 : 0 : continue;
380 : :
381 : 0 : node = dt_new_addr(bus, name, dev_addr);
382 : 0 : if (!node)
383 : 0 : continue;
384 : :
385 : 0 : dt_add_property_cells(node, "reg", dev_addr);
386 : 0 : dt_add_property_cells(node, "link-id",
387 : : be32_to_cpu(dev->i2c_link));
388 : 0 : if (compat)
389 : 0 : dt_add_property_string(node, "compatible", compat);
390 : 0 : if (info->label)
391 : 0 : dt_add_property_string(node, "label", info->label);
392 : 0 : if (!info->allowed)
393 : 0 : dt_add_property_string(node, "status", "reserved");
394 : :
395 : : /*
396 : : * Set a default timeout of 2s on the ports with a TPM. This is
397 : : * to work around a bug with certain TPM firmwares that can
398 : : * clock stretch for long periods of time and will lock up
399 : : * until they are power cycled if a STOP condition is sent
400 : : * during this period.
401 : : */
402 : 0 : if (dev->type == 0x3)
403 : 0 : dt_add_property_cells(bus, "timeout-ms", 2000);
404 : :
405 : : /* XXX: SLCA index? */
406 : : }
407 : :
408 : 0 : return 0;
409 : : }
|