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