xref: /freebsd/sys/dev/imcsmb/imcsmb.c (revision dd21556857e8d40f66bf5ad54754d9d52669ebf7)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Authors: Joe Kloss; Ravi Pokala (rpokala@freebsd.org)
5  *
6  * Copyright (c) 2017-2018 Panasas
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /* A detailed description of this device is present in imcsmb_pci.c */
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
36 #include <sys/endian.h>
37 #include <sys/errno.h>
38 #include <sys/lock.h>
39 #include <sys/mutex.h>
40 #include <sys/syslog.h>
41 #include <sys/bus.h>
42 
43 #include <machine/bus.h>
44 #include <machine/atomic.h>
45 
46 #include <dev/pci/pcivar.h>
47 #include <dev/pci/pcireg.h>
48 
49 #include <dev/smbus/smbconf.h>
50 
51 #include "imcsmb_reg.h"
52 #include "imcsmb_var.h"
53 
54 /* Device methods */
55 static int imcsmb_attach(device_t dev);
56 static int imcsmb_probe(device_t dev);
57 
58 /* SMBus methods */
59 static int imcsmb_callback(device_t dev, int index, void *data);
60 static int imcsmb_readb(device_t dev, u_char slave, char cmd, char *byte);
61 static int imcsmb_readw(device_t dev, u_char slave, char cmd, short *word);
62 static int imcsmb_writeb(device_t dev, u_char slave, char cmd, char byte);
63 static int imcsmb_writew(device_t dev, u_char slave, char cmd, short word);
64 
65 /* All the read/write methods wrap around this. */
66 static int imcsmb_transfer(device_t dev, u_char slave, char cmd, void *data,
67     int word_op, int write_op);
68 
69 /**
70  * device_attach() method. Set up the softc, including getting the set of the
71  * parent imcsmb_pci's registers that we will use. Create the smbus(4) device,
72  * which any SMBus slave device drivers will connect to.
73  *
74  * @author rpokala
75  *
76  * @param[in,out] dev
77  *      Device being attached.
78  */
79 static int
80 imcsmb_attach(device_t dev)
81 {
82 	struct imcsmb_softc *sc;
83 	int rc;
84 
85 	/* Initialize private state */
86 	sc = device_get_softc(dev);
87 	sc->dev = dev;
88 	sc->imcsmb_pci = device_get_parent(dev);
89 	sc->regs = device_get_ivars(dev);
90 
91 	/* Create the smbus child */
92 	sc->smbus = device_add_child(dev, "smbus", DEVICE_UNIT_ANY);
93 	if (sc->smbus == NULL) {
94 		/* Nothing has been allocated, so there's no cleanup. */
95 		device_printf(dev, "Child smbus not added\n");
96 		rc = ENXIO;
97 		goto out;
98 	}
99 
100 	/* Attach the smbus child. */
101 	bus_attach_children(dev);
102 	rc = 0;
103 
104 out:
105 	return (rc);
106 }
107 
108 /**
109  * device_probe() method. All the actual probing was done by the imcsmb_pci
110  * parent, so just report success.
111  *
112  * @author Joe Kloss
113  *
114  * @param[in,out] dev
115  *      Device being probed.
116  */
117 static int
118 imcsmb_probe(device_t dev)
119 {
120 
121 	device_set_desc(dev, "iMC SMBus controller");
122 	return (BUS_PROBE_DEFAULT);
123 }
124 
125 /**
126  * smbus_callback() method. Call the parent imcsmb_pci's request or release
127  * function to quiesce / restart firmware tasks which might use the SMBus.
128  *
129  * @author rpokala
130  *
131  * @param[in] dev
132  *      Device being requested or released.
133  *
134  * @param[in] index
135  *      Either SMB_REQUEST_BUS or SMB_RELEASE_BUS.
136  *
137  * @param[in] data
138  *      Tell's the rest of the SMBus subsystem to allow or disallow waiting;
139  *      this driver only works with SMB_DONTWAIT.
140  */
141 static int
142 imcsmb_callback(device_t dev, int index, void *data)
143 {
144 	struct imcsmb_softc *sc;
145 	int *how;
146 	int rc;
147 
148 	sc = device_get_softc(dev);
149 	how = (int *) data;
150 
151 	switch (index) {
152 	case SMB_REQUEST_BUS: {
153 		if (*how != SMB_DONTWAIT) {
154 			rc = EINVAL;
155 			goto out;
156 		}
157 		rc = imcsmb_pci_request_bus(sc->imcsmb_pci);
158 		break;
159 	}
160 	case SMB_RELEASE_BUS:
161 		imcsmb_pci_release_bus(sc->imcsmb_pci);
162 		rc = 0;
163 		break;
164 	default:
165 		rc = EINVAL;
166 		break;
167 	}
168 
169 out:
170 	return (rc);
171 }
172 
173 /**
174  * smbus_readb() method. Thin wrapper around imcsmb_transfer().
175  *
176  * @author Joe Kloss
177  *
178  * @param[in] dev
179  *
180  * @param[in] slave
181  *      The SMBus address of the target device.
182  *
183  * @param[in] cmd
184  *      The SMBus command for the target device; this is the offset for SPDs,
185  *      or the register number for TSODs.
186  *
187  * @param[out] byte
188  *      The byte which was read.
189  */
190 static int
191 imcsmb_readb(device_t dev, u_char slave, char cmd, char *byte)
192 {
193 
194 	return (imcsmb_transfer(dev, slave, cmd, byte, FALSE, FALSE));
195 }
196 
197 /**
198  * smbus_readw() method. Thin wrapper around imcsmb_transfer().
199  *
200  * @author Joe Kloss
201  *
202  * @param[in] dev
203  *
204  * @param[in] slave
205  *      The SMBus address of the target device.
206  *
207  * @param[in] cmd
208  *      The SMBus command for the target device; this is the offset for SPDs,
209  *      or the register number for TSODs.
210  *
211  * @param[out] word
212  *      The word which was read.
213  */
214 static int
215 imcsmb_readw(device_t dev, u_char slave, char cmd, short *word)
216 {
217 
218 	return (imcsmb_transfer(dev, slave, cmd, word, TRUE, FALSE));
219 }
220 
221 /**
222  * smbus_writeb() method. Thin wrapper around imcsmb_transfer().
223  *
224  * @author Joe Kloss
225  *
226  * @param[in] dev
227  *
228  * @param[in] slave
229  *      The SMBus address of the target device.
230  *
231  * @param[in] cmd
232  *      The SMBus command for the target device; this is the offset for SPDs,
233  *      or the register number for TSODs.
234  *
235  * @param[in] byte
236  *      The byte to write.
237  */
238 static int
239 imcsmb_writeb(device_t dev, u_char slave, char cmd, char byte)
240 {
241 
242 	return (imcsmb_transfer(dev, slave, cmd, &byte, FALSE, TRUE));
243 }
244 
245 /**
246  * smbus_writew() method. Thin wrapper around imcsmb_transfer().
247  *
248  * @author Joe Kloss
249  *
250  * @param[in] dev
251  *
252  * @param[in] slave
253  *      The SMBus address of the target device.
254  *
255  * @param[in] cmd
256  *      The SMBus command for the target device; this is the offset for SPDs,
257  *      or the register number for TSODs.
258  *
259  * @param[in] word
260  *      The word to write.
261  */
262 static int
263 imcsmb_writew(device_t dev, u_char slave, char cmd, short word)
264 {
265 
266 	return (imcsmb_transfer(dev, slave, cmd, &word, TRUE, TRUE));
267 }
268 
269 /**
270  * Manipulate the PCI control registers to read data from or write data to the
271  * SMBus controller.
272  *
273  * @author Joe Kloss, rpokala
274  *
275  * @param[in] dev
276  *
277  * @param[in] slave
278  *      The SMBus address of the target device.
279  *
280  * @param[in] cmd
281  *      The SMBus command for the target device; this is the offset for SPDs,
282  *      or the register number for TSODs.
283  *
284  * @param[in,out] data
285  *      Pointer to either the value to be written, or where to place the value
286  *      which was read.
287  *
288  * @param[in] word_op
289  *      Bool: is this a word operation?
290  *
291  * @param[in] write_op
292  *      Bool: is this a write operation?
293  */
294 static int
295 imcsmb_transfer(device_t dev, u_char slave, char cmd, void *data, int word_op,
296     int write_op)
297 {
298 	struct imcsmb_softc *sc;
299 	int i;
300 	int rc;
301 	uint32_t cmd_val;
302 	uint32_t cntl_val;
303 	uint32_t orig_cntl_val;
304 	uint32_t stat_val;
305 	uint16_t *word;
306 	uint16_t lword;
307 	uint8_t *byte;
308 	uint8_t lbyte;
309 
310 	sc = device_get_softc(dev);
311 	byte = data;
312 	word = data;
313 	lbyte = *byte;
314 	lword = *word;
315 
316 	/* We modify the value of the control register; save the original, so
317 	 * we can restore it later
318 	 */
319 	orig_cntl_val = pci_read_config(sc->imcsmb_pci,
320 	    sc->regs->smb_cntl, 4);
321 	cntl_val = orig_cntl_val;
322 
323 	/*
324 	 * Set up the SMBCNTL register
325 	 */
326 
327 	/* [31:28] Clear the existing value of the DTI bits, then set them to
328 	 * the four high bits of the slave address.
329 	 */
330 	cntl_val &= ~IMCSMB_CNTL_DTI_MASK;
331 	cntl_val |= ((uint32_t) slave & 0xf0) << 24;
332 
333 	/* [27:27] Set the CLK_OVERRIDE bit, to enable normal operation */
334 	cntl_val |= IMCSMB_CNTL_CLK_OVERRIDE;
335 
336 	/* [26:26] Clear the WRITE_DISABLE bit; the datasheet says this isn't
337 	 * necessary, but empirically, it is.
338 	 */
339 	cntl_val &= ~IMCSMB_CNTL_WRITE_DISABLE_BIT;
340 
341 	/* [9:9] Clear the POLL_EN bit, to stop the hardware TSOD polling. */
342 	cntl_val &= ~IMCSMB_CNTL_POLL_EN;
343 
344 	/*
345 	 * Set up the SMBCMD register
346 	 */
347 
348 	/* [31:31] Set the TRIGGER bit; when this gets written, the controller
349 	 * will issue the command.
350 	 */
351 	cmd_val = IMCSMB_CMD_TRIGGER_BIT;
352 
353 	/* [29:29] For word operations, set the WORD_ACCESS bit. */
354 	if (word_op) {
355 		cmd_val |= IMCSMB_CMD_WORD_ACCESS;
356 	}
357 
358 	/* [27:27] For write operations, set the WRITE bit. */
359 	if (write_op) {
360 		cmd_val |= IMCSMB_CMD_WRITE_BIT;
361 	}
362 
363 	/* [26:24] The three non-DTI, non-R/W bits of the slave address. */
364 	cmd_val |= (uint32_t) ((slave & 0xe) << 23);
365 
366 	/* [23:16] The command (offset in the case of an EEPROM, or register in
367 	 * the case of TSOD or NVDIMM controller).
368 	 */
369 	cmd_val |= (uint32_t) ((uint8_t) cmd << 16);
370 
371 	/* [15:0] The data to be written for a write operation. */
372 	if (write_op) {
373 		if (word_op) {
374 			/* The datasheet says the controller uses different
375 			 * endianness for word operations on I2C vs SMBus!
376 			 *      I2C: [15:8] = MSB; [7:0] = LSB
377 			 *      SMB: [15:8] = LSB; [7:0] = MSB
378 			 * As a practical matter, this controller is very
379 			 * specifically for use with DIMMs, the SPD (and
380 			 * NVDIMM controllers) are only accessed as bytes,
381 			 * the temperature sensor is only accessed as words, and
382 			 * the temperature sensors are I2C. Thus, byte-swap the
383 			 * word.
384 			 */
385 			lword = htobe16(lword);
386 		} else {
387 			/* For byte operations, the data goes in the LSB, and
388 			 * the MSB is a don't care.
389 			 */
390 			lword = (uint16_t) (lbyte & 0xff);
391 		}
392 		cmd_val |= lword;
393 	}
394 
395 	/* Write the updated value to the control register first, to disable
396 	 * the hardware TSOD polling.
397 	 */
398 	pci_write_config(sc->imcsmb_pci, sc->regs->smb_cntl, cntl_val, 4);
399 
400 	/* Poll on the BUSY bit in the status register until clear, or timeout.
401 	 * We just cleared the auto-poll bit, so we need to make sure the device
402 	 * is idle before issuing a command. We can safely timeout after 35 ms,
403 	 * as this is the maximum time the SMBus spec allows for a transaction.
404 	 */
405 	for (i = 4; i != 0; i--) {
406 		stat_val = pci_read_config(sc->imcsmb_pci, sc->regs->smb_stat,
407 		    4);
408 		if ((stat_val & IMCSMB_STATUS_BUSY_BIT) == 0) {
409 			break;
410 		}
411 		pause("imcsmb", 10 * hz / 1000);
412 	}
413 
414 	if (i == 0) {
415 		device_printf(sc->dev,
416 		    "transfer: timeout waiting for device to settle\n");
417 	}
418 
419 	/* Now that polling has stopped, we can write the command register. This
420 	 * starts the SMBus command.
421 	 */
422 	pci_write_config(sc->imcsmb_pci, sc->regs->smb_cmd, cmd_val, 4);
423 
424 	/* Wait for WRITE_DATA_DONE/READ_DATA_VALID to be set, or timeout and
425 	 * fail. We wait up to 35ms.
426 	 */
427 	for (i = 35000; i != 0; i -= 10)
428 	{
429 		DELAY(10);
430 		stat_val = pci_read_config(sc->imcsmb_pci, sc->regs->smb_stat,
431 		    4);
432 		/* For a write, the bits holding the data contain the data being
433 		 * written. You'd think that would cause the READ_DATA_VALID bit
434 		 * to be cleared, because the data bits no longer contain valid
435 		 * data from the most recent read operation. While that would be
436 		 * logical, that's not the case here: READ_DATA_VALID is only
437 		 * cleared when starting a read operation, and WRITE_DATA_DONE
438 		 * is only cleared when starting a write operation.
439 		 */
440 		if (write_op) {
441 			if ((stat_val & IMCSMB_STATUS_WRITE_DATA_DONE) != 0) {
442 				break;
443 			}
444 		} else {
445 			if ((stat_val & IMCSMB_STATUS_READ_DATA_VALID) != 0) {
446 				break;
447 			}
448 		}
449 	}
450 	if (i == 0) {
451 		rc = SMB_ETIMEOUT;
452 		device_printf(dev, "transfer timeout\n");
453 		goto out;
454 	}
455 
456 	/* It is generally the case that this bit indicates non-ACK, but it
457 	 * could also indicate other bus errors. There's no way to tell the
458 	 * difference.
459 	 */
460 	if ((stat_val & IMCSMB_STATUS_BUS_ERROR_BIT) != 0) {
461 		/* While it is not documented, empirically, SPD page-change
462 		 * commands (writes with DTI = 0x60) always complete with the
463 		 * error bit set. So, ignore it in those cases.
464 		 */
465 		if ((slave & 0xf0) != 0x60) {
466 			rc = SMB_ENOACK;
467 			goto out;
468 		}
469 	}
470 
471 	/* For a read operation, copy the data out */
472 	if (write_op == 0) {
473 		if (word_op) {
474 			/* The data is returned in bits [15:0]; as discussed
475 			 * above, byte-swap.
476 			 */
477 			lword = (uint16_t) (stat_val & 0xffff);
478 			lword = htobe16(lword);
479 			*word = lword;
480 		} else {
481 			/* The data is returned in bits [7:0] */
482 			lbyte = (uint8_t) (stat_val & 0xff);
483 			*byte = lbyte;
484 		}
485 	}
486 
487 	/* A lack of an error is, de facto, success. */
488 	rc = SMB_ENOERR;
489 
490 out:
491 	/* Restore the original value of the control register. */
492 	pci_write_config(sc->imcsmb_pci, sc->regs->smb_cntl, orig_cntl_val, 4);
493 	return (rc);
494 }
495 
496 /* Device methods */
497 static device_method_t imcsmb_methods[] = {
498 	/* Device interface */
499 	DEVMETHOD(device_attach,	imcsmb_attach),
500 	DEVMETHOD(device_detach,	bus_generic_detach),
501 	DEVMETHOD(device_probe,		imcsmb_probe),
502 
503 	/* smbus methods */
504 	DEVMETHOD(smbus_callback,	imcsmb_callback),
505 	DEVMETHOD(smbus_readb,		imcsmb_readb),
506 	DEVMETHOD(smbus_readw,		imcsmb_readw),
507 	DEVMETHOD(smbus_writeb,		imcsmb_writeb),
508 	DEVMETHOD(smbus_writew,		imcsmb_writew),
509 
510 	DEVMETHOD_END
511 };
512 
513 static driver_t imcsmb_driver = {
514 	.name = "imcsmb",
515 	.methods = imcsmb_methods,
516 	.size = sizeof(struct imcsmb_softc),
517 };
518 
519 DRIVER_MODULE(imcsmb, imcsmb_pci, imcsmb_driver, 0, 0);
520 MODULE_DEPEND(imcsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
521 MODULE_VERSION(imcsmb, 1);
522 
523 DRIVER_MODULE(smbus, imcsmb, smbus_driver, 0, 0);
524 
525 /* vi: set ts=8 sw=4 sts=8 noet: */
526