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