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