FreeBSD/Linux Kernel Cross Reference
sys/dev/ismt/ismt.c
1 /*-
2 * Copyright (C) 2014 Intel Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Intel Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
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 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/bus.h>
36 #include <sys/errno.h>
37 #include <sys/kernel.h>
38 #include <sys/lock.h>
39 #include <sys/module.h>
40 #include <sys/priority.h>
41 #include <sys/proc.h>
42 #include <sys/syslog.h>
43
44 #include <machine/bus.h>
45 #include <sys/rman.h>
46 #include <machine/resource.h>
47
48 #include <dev/pci/pcireg.h>
49 #include <dev/pci/pcivar.h>
50 #include <dev/smbus/smbconf.h>
51
52 #include "smbus_if.h"
53
54 #define ISMT_DESC_ENTRIES 32
55
56 /* Hardware Descriptor Constants - Control Field */
57 #define ISMT_DESC_CWRL 0x01 /* Command/Write Length */
58 #define ISMT_DESC_BLK 0X04 /* Perform Block Transaction */
59 #define ISMT_DESC_FAIR 0x08 /* Set fairness flag upon successful arbit. */
60 #define ISMT_DESC_PEC 0x10 /* Packet Error Code */
61 #define ISMT_DESC_I2C 0x20 /* I2C Enable */
62 #define ISMT_DESC_INT 0x40 /* Interrupt */
63 #define ISMT_DESC_SOE 0x80 /* Stop On Error */
64
65 /* Hardware Descriptor Constants - Status Field */
66 #define ISMT_DESC_SCS 0x01 /* Success */
67 #define ISMT_DESC_DLTO 0x04 /* Data Low Time Out */
68 #define ISMT_DESC_NAK 0x08 /* NAK Received */
69 #define ISMT_DESC_CRC 0x10 /* CRC Error */
70 #define ISMT_DESC_CLTO 0x20 /* Clock Low Time Out */
71 #define ISMT_DESC_COL 0x40 /* Collisions */
72 #define ISMT_DESC_LPR 0x80 /* Large Packet Received */
73
74 /* Macros */
75 #define ISMT_DESC_ADDR_RW(addr, is_read) ((addr) | (is_read))
76
77 /* iSMT General Register address offsets (SMBBAR + <addr>) */
78 #define ISMT_GR_GCTRL 0x000 /* General Control */
79 #define ISMT_GR_SMTICL 0x008 /* SMT Interrupt Cause Location */
80 #define ISMT_GR_ERRINTMSK 0x010 /* Error Interrupt Mask */
81 #define ISMT_GR_ERRAERMSK 0x014 /* Error AER Mask */
82 #define ISMT_GR_ERRSTS 0x018 /* Error Status */
83 #define ISMT_GR_ERRINFO 0x01c /* Error Information */
84
85 /* iSMT Master Registers */
86 #define ISMT_MSTR_MDBA 0x100 /* Master Descriptor Base Address */
87 #define ISMT_MSTR_MCTRL 0x108 /* Master Control */
88 #define ISMT_MSTR_MSTS 0x10c /* Master Status */
89 #define ISMT_MSTR_MDS 0x110 /* Master Descriptor Size */
90 #define ISMT_MSTR_RPOLICY 0x114 /* Retry Policy */
91
92 /* iSMT Miscellaneous Registers */
93 #define ISMT_SPGT 0x300 /* SMBus PHY Global Timing */
94
95 /* General Control Register (GCTRL) bit definitions */
96 #define ISMT_GCTRL_TRST 0x04 /* Target Reset */
97 #define ISMT_GCTRL_KILL 0x08 /* Kill */
98 #define ISMT_GCTRL_SRST 0x40 /* Soft Reset */
99
100 /* Master Control Register (MCTRL) bit definitions */
101 #define ISMT_MCTRL_SS 0x01 /* Start/Stop */
102 #define ISMT_MCTRL_MEIE 0x10 /* Master Error Interrupt Enable */
103 #define ISMT_MCTRL_FMHP 0x00ff0000 /* Firmware Master Head Ptr (FMHP) */
104
105 /* Master Status Register (MSTS) bit definitions */
106 #define ISMT_MSTS_HMTP 0xff0000 /* HW Master Tail Pointer (HMTP) */
107 #define ISMT_MSTS_MIS 0x20 /* Master Interrupt Status (MIS) */
108 #define ISMT_MSTS_MEIS 0x10 /* Master Error Int Status (MEIS) */
109 #define ISMT_MSTS_IP 0x01 /* In Progress */
110
111 /* Master Descriptor Size (MDS) bit definitions */
112 #define ISMT_MDS_MASK 0xff /* Master Descriptor Size mask (MDS) */
113
114 /* SMBus PHY Global Timing Register (SPGT) bit definitions */
115 #define ISMT_SPGT_SPD_MASK 0xc0000000 /* SMBus Speed mask */
116 #define ISMT_SPGT_SPD_80K 0x00 /* 80 kHz */
117 #define ISMT_SPGT_SPD_100K (0x1 << 30) /* 100 kHz */
118 #define ISMT_SPGT_SPD_400K (0x2 << 30) /* 400 kHz */
119 #define ISMT_SPGT_SPD_1M (0x3 << 30) /* 1 MHz */
120
121 /* MSI Control Register (MSICTL) bit definitions */
122 #define ISMT_MSICTL_MSIE 0x01 /* MSI Enable */
123
124 #define ISMT_MAX_BLOCK_SIZE 32 /* per SMBus spec */
125
126 //#define ISMT_DEBUG device_printf
127 #ifndef ISMT_DEBUG
128 #define ISMT_DEBUG(...)
129 #endif
130
131 /* iSMT Hardware Descriptor */
132 struct ismt_desc {
133 uint8_t tgtaddr_rw; /* target address & r/w bit */
134 uint8_t wr_len_cmd; /* write length in bytes or a command */
135 uint8_t rd_len; /* read length */
136 uint8_t control; /* control bits */
137 uint8_t status; /* status bits */
138 uint8_t retry; /* collision retry and retry count */
139 uint8_t rxbytes; /* received bytes */
140 uint8_t txbytes; /* transmitted bytes */
141 uint32_t dptr_low; /* lower 32 bit of the data pointer */
142 uint32_t dptr_high; /* upper 32 bit of the data pointer */
143 } __packed;
144
145 #define DESC_SIZE (ISMT_DESC_ENTRIES * sizeof(struct ismt_desc))
146
147 #define DMA_BUFFER_SIZE 64
148
149 struct ismt_softc {
150 device_t pcidev;
151 device_t smbdev;
152
153 struct thread *bus_reserved;
154
155 int intr_rid;
156 struct resource *intr_res;
157 void *intr_handle;
158
159 bus_space_tag_t mmio_tag;
160 bus_space_handle_t mmio_handle;
161 int mmio_rid;
162 struct resource *mmio_res;
163
164 uint8_t head;
165
166 struct ismt_desc *desc;
167 bus_dma_tag_t desc_dma_tag;
168 bus_dmamap_t desc_dma_map;
169 uint64_t desc_bus_addr;
170
171 uint8_t *dma_buffer;
172 bus_dma_tag_t dma_buffer_dma_tag;
173 bus_dmamap_t dma_buffer_dma_map;
174 uint64_t dma_buffer_bus_addr;
175
176 uint8_t using_msi;
177 };
178
179 static void
180 ismt_intr(void *arg)
181 {
182 struct ismt_softc *sc = arg;
183 uint32_t val;
184
185 val = bus_read_4(sc->mmio_res, ISMT_MSTR_MSTS);
186 ISMT_DEBUG(sc->pcidev, "%s MSTS=0x%x\n", __func__, val);
187
188 val |= (ISMT_MSTS_MIS | ISMT_MSTS_MEIS);
189 bus_write_4(sc->mmio_res, ISMT_MSTR_MSTS, val);
190
191 wakeup(sc);
192 }
193
194 static int
195 ismt_callback(device_t dev, int index, void *data)
196 {
197 struct ismt_softc *sc;
198 int acquired, err;
199
200 sc = device_get_softc(dev);
201
202 switch (index) {
203 case SMB_REQUEST_BUS:
204 acquired = atomic_cmpset_ptr(
205 (uintptr_t *)&sc->bus_reserved,
206 (uintptr_t)NULL, (uintptr_t)curthread);
207 ISMT_DEBUG(dev, "SMB_REQUEST_BUS acquired=%d\n", acquired);
208 if (acquired)
209 err = 0;
210 else
211 err = EWOULDBLOCK;
212 break;
213 case SMB_RELEASE_BUS:
214 KASSERT(sc->bus_reserved == curthread,
215 ("SMB_RELEASE_BUS called by wrong thread\n"));
216 ISMT_DEBUG(dev, "SMB_RELEASE_BUS\n");
217 atomic_store_rel_ptr((uintptr_t *)&sc->bus_reserved,
218 (uintptr_t)NULL);
219 err = 0;
220 break;
221 default:
222 err = SMB_EABORT;
223 break;
224 }
225
226 return (err);
227 }
228
229 static struct ismt_desc *
230 ismt_alloc_desc(struct ismt_softc *sc)
231 {
232 struct ismt_desc *desc;
233
234 KASSERT(sc->bus_reserved == curthread,
235 ("curthread %p did not request bus (%p has reserved)\n",
236 curthread, sc->bus_reserved));
237
238 desc = &sc->desc[sc->head++];
239 if (sc->head == ISMT_DESC_ENTRIES)
240 sc->head = 0;
241
242 memset(desc, 0, sizeof(*desc));
243
244 return (desc);
245 }
246
247 static int
248 ismt_submit(struct ismt_softc *sc, struct ismt_desc *desc, uint8_t slave,
249 uint8_t is_read)
250 {
251 uint32_t err, fmhp, val;
252
253 desc->control |= ISMT_DESC_FAIR;
254 if (sc->using_msi)
255 desc->control |= ISMT_DESC_INT;
256
257 desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(slave, is_read);
258 desc->dptr_low = (sc->dma_buffer_bus_addr & 0xFFFFFFFFLL);
259 desc->dptr_high = (sc->dma_buffer_bus_addr >> 32);
260
261 wmb();
262
263 fmhp = sc->head << 16;
264 val = bus_read_4(sc->mmio_res, ISMT_MSTR_MCTRL);
265 val &= ~ISMT_MCTRL_FMHP;
266 val |= fmhp;
267 bus_write_4(sc->mmio_res, ISMT_MSTR_MCTRL, val);
268
269 /* set the start bit */
270 val = bus_read_4(sc->mmio_res, ISMT_MSTR_MCTRL);
271 val |= ISMT_MCTRL_SS;
272 bus_write_4(sc->mmio_res, ISMT_MSTR_MCTRL, val);
273
274 err = tsleep(sc, PWAIT, "ismt_wait", 5 * hz);
275
276 if (err != 0) {
277 ISMT_DEBUG(sc->pcidev, "%s timeout\n", __func__);
278 return (SMB_ETIMEOUT);
279 }
280
281 ISMT_DEBUG(sc->pcidev, "%s status=0x%x\n", __func__, desc->status);
282
283 if (desc->status & ISMT_DESC_SCS)
284 return (SMB_ENOERR);
285
286 if (desc->status & ISMT_DESC_NAK)
287 return (SMB_ENOACK);
288
289 if (desc->status & ISMT_DESC_CRC)
290 return (SMB_EBUSERR);
291
292 if (desc->status & ISMT_DESC_COL)
293 return (SMB_ECOLLI);
294
295 if (desc->status & ISMT_DESC_LPR)
296 return (SMB_EINVAL);
297
298 if (desc->status & (ISMT_DESC_DLTO | ISMT_DESC_CLTO))
299 return (SMB_ETIMEOUT);
300
301 return (SMB_EBUSERR);
302 }
303
304
305 static int
306 ismt_quick(device_t dev, u_char slave, int how)
307 {
308 struct ismt_desc *desc;
309 struct ismt_softc *sc;
310 int is_read;
311
312 ISMT_DEBUG(dev, "%s\n", __func__);
313
314 if (how != SMB_QREAD && how != SMB_QWRITE) {
315 return (SMB_ENOTSUPP);
316 }
317
318 sc = device_get_softc(dev);
319 desc = ismt_alloc_desc(sc);
320 is_read = (how == SMB_QREAD ? 1 : 0);
321 return (ismt_submit(sc, desc, slave, is_read));
322 }
323
324 static int
325 ismt_sendb(device_t dev, u_char slave, char byte)
326 {
327 struct ismt_desc *desc;
328 struct ismt_softc *sc;
329
330 ISMT_DEBUG(dev, "%s\n", __func__);
331
332 sc = device_get_softc(dev);
333 desc = ismt_alloc_desc(sc);
334 desc->control = ISMT_DESC_CWRL;
335 desc->wr_len_cmd = byte;
336
337 return (ismt_submit(sc, desc, slave, 0));
338 }
339
340 static int
341 ismt_recvb(device_t dev, u_char slave, char *byte)
342 {
343 struct ismt_desc *desc;
344 struct ismt_softc *sc;
345 int err;
346
347 ISMT_DEBUG(dev, "%s\n", __func__);
348
349 sc = device_get_softc(dev);
350 desc = ismt_alloc_desc(sc);
351 desc->rd_len = 1;
352
353 err = ismt_submit(sc, desc, slave, 1);
354
355 if (err != SMB_ENOERR)
356 return (err);
357
358 *byte = sc->dma_buffer[0];
359
360 return (err);
361 }
362
363 static int
364 ismt_writeb(device_t dev, u_char slave, char cmd, char byte)
365 {
366 struct ismt_desc *desc;
367 struct ismt_softc *sc;
368
369 ISMT_DEBUG(dev, "%s\n", __func__);
370
371 sc = device_get_softc(dev);
372 desc = ismt_alloc_desc(sc);
373 desc->wr_len_cmd = 2;
374 sc->dma_buffer[0] = cmd;
375 sc->dma_buffer[1] = byte;
376
377 return (ismt_submit(sc, desc, slave, 0));
378 }
379
380 static int
381 ismt_writew(device_t dev, u_char slave, char cmd, short word)
382 {
383 struct ismt_desc *desc;
384 struct ismt_softc *sc;
385
386 ISMT_DEBUG(dev, "%s\n", __func__);
387
388 sc = device_get_softc(dev);
389 desc = ismt_alloc_desc(sc);
390 desc->wr_len_cmd = 3;
391 sc->dma_buffer[0] = cmd;
392 sc->dma_buffer[1] = word & 0xFF;
393 sc->dma_buffer[2] = word >> 8;
394
395 return (ismt_submit(sc, desc, slave, 0));
396 }
397
398 static int
399 ismt_readb(device_t dev, u_char slave, char cmd, char *byte)
400 {
401 struct ismt_desc *desc;
402 struct ismt_softc *sc;
403 int err;
404
405 ISMT_DEBUG(dev, "%s\n", __func__);
406
407 sc = device_get_softc(dev);
408 desc = ismt_alloc_desc(sc);
409 desc->control = ISMT_DESC_CWRL;
410 desc->wr_len_cmd = cmd;
411 desc->rd_len = 1;
412
413 err = ismt_submit(sc, desc, slave, 1);
414
415 if (err != SMB_ENOERR)
416 return (err);
417
418 *byte = sc->dma_buffer[0];
419
420 return (err);
421 }
422
423 static int
424 ismt_readw(device_t dev, u_char slave, char cmd, short *word)
425 {
426 struct ismt_desc *desc;
427 struct ismt_softc *sc;
428 int err;
429
430 ISMT_DEBUG(dev, "%s\n", __func__);
431
432 sc = device_get_softc(dev);
433 desc = ismt_alloc_desc(sc);
434 desc->control = ISMT_DESC_CWRL;
435 desc->wr_len_cmd = cmd;
436 desc->rd_len = 2;
437
438 err = ismt_submit(sc, desc, slave, 1);
439
440 if (err != SMB_ENOERR)
441 return (err);
442
443 *word = sc->dma_buffer[0] | (sc->dma_buffer[1] << 8);
444
445 return (err);
446 }
447
448 static int
449 ismt_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata)
450 {
451 struct ismt_desc *desc;
452 struct ismt_softc *sc;
453 int err;
454
455 ISMT_DEBUG(dev, "%s\n", __func__);
456
457 sc = device_get_softc(dev);
458 desc = ismt_alloc_desc(sc);
459 desc->wr_len_cmd = 3;
460 desc->rd_len = 2;
461 sc->dma_buffer[0] = cmd;
462 sc->dma_buffer[1] = sdata & 0xff;
463 sc->dma_buffer[2] = sdata >> 8;
464
465 err = ismt_submit(sc, desc, slave, 0);
466
467 if (err != SMB_ENOERR)
468 return (err);
469
470 *rdata = sc->dma_buffer[0] | (sc->dma_buffer[1] << 8);
471
472 return (err);
473 }
474
475 static int
476 ismt_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
477 {
478 struct ismt_desc *desc;
479 struct ismt_softc *sc;
480
481 ISMT_DEBUG(dev, "%s\n", __func__);
482
483 if (count == 0 || count > ISMT_MAX_BLOCK_SIZE)
484 return (SMB_EINVAL);
485
486 sc = device_get_softc(dev);
487 desc = ismt_alloc_desc(sc);
488 desc->control = ISMT_DESC_I2C;
489 desc->wr_len_cmd = count + 1;
490 sc->dma_buffer[0] = cmd;
491 memcpy(&sc->dma_buffer[1], buf, count);
492
493 return (ismt_submit(sc, desc, slave, 0));
494 }
495
496 static int
497 ismt_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
498 {
499 struct ismt_desc *desc;
500 struct ismt_softc *sc;
501 int err;
502
503 ISMT_DEBUG(dev, "%s\n", __func__);
504
505 if (*count == 0 || *count > ISMT_MAX_BLOCK_SIZE)
506 return (SMB_EINVAL);
507
508 sc = device_get_softc(dev);
509 desc = ismt_alloc_desc(sc);
510 desc->control = ISMT_DESC_I2C | ISMT_DESC_CWRL;
511 desc->wr_len_cmd = cmd;
512 desc->rd_len = *count;
513
514 err = ismt_submit(sc, desc, slave, 0);
515
516 if (err != SMB_ENOERR)
517 return (err);
518
519 memcpy(buf, sc->dma_buffer, desc->rxbytes);
520 *count = desc->rxbytes;
521
522 return (err);
523 }
524
525 static int
526 ismt_detach(device_t dev)
527 {
528 struct ismt_softc *sc;
529 int error;
530
531 ISMT_DEBUG(dev, "%s\n", __func__);
532 sc = device_get_softc(dev);
533
534 error = bus_generic_detach(dev);
535 if (error)
536 return (error);
537
538 device_delete_child(dev, sc->smbdev);
539
540 if (sc->intr_handle != NULL) {
541 bus_teardown_intr(dev, sc->intr_res, sc->intr_handle);
542 sc->intr_handle = NULL;
543 }
544 if (sc->intr_res != NULL) {
545 bus_release_resource(dev,
546 SYS_RES_IRQ, sc->intr_rid, sc->intr_res);
547 sc->intr_res = NULL;
548 }
549 if (sc->using_msi == 1)
550 pci_release_msi(dev);
551
552 if (sc->mmio_res != NULL) {
553 bus_release_resource(dev,
554 SYS_RES_MEMORY, sc->mmio_rid, sc->mmio_res);
555 sc->mmio_res = NULL;
556 }
557
558 bus_dmamap_unload(sc->desc_dma_tag, sc->desc_dma_map);
559 bus_dmamap_unload(sc->dma_buffer_dma_tag, sc->dma_buffer_dma_map);
560
561 bus_dmamem_free(sc->desc_dma_tag, sc->desc,
562 sc->desc_dma_map);
563 bus_dmamem_free(sc->dma_buffer_dma_tag, sc->dma_buffer,
564 sc->dma_buffer_dma_map);
565
566 bus_dma_tag_destroy(sc->desc_dma_tag);
567 bus_dma_tag_destroy(sc->dma_buffer_dma_tag);
568
569 pci_disable_busmaster(dev);
570
571 return 0;
572 }
573
574 static void
575 ismt_single_map(void *arg, bus_dma_segment_t *seg, int nseg, int error)
576 {
577 uint64_t *bus_addr = (uint64_t *)arg;
578
579 KASSERT(error == 0, ("%s: error=%d\n", __func__, error));
580 KASSERT(nseg == 1, ("%s: nseg=%d\n", __func__, nseg));
581
582 *bus_addr = seg[0].ds_addr;
583 }
584
585 static int
586 ismt_attach(device_t dev)
587 {
588 struct ismt_softc *sc = device_get_softc(dev);
589 int err, num_vectors, val;
590
591 sc->pcidev = dev;
592 pci_enable_busmaster(dev);
593
594 if ((sc->smbdev = device_add_child(dev, "smbus", -1)) == NULL) {
595 device_printf(dev, "no smbus child found\n");
596 err = ENXIO;
597 goto fail;
598 }
599
600 sc->mmio_rid = PCIR_BAR(0);
601 sc->mmio_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
602 &sc->mmio_rid, RF_ACTIVE);
603 if (sc->mmio_res == NULL) {
604 device_printf(dev, "cannot allocate mmio region\n");
605 err = ENOMEM;
606 goto fail;
607 }
608
609 sc->mmio_tag = rman_get_bustag(sc->mmio_res);
610 sc->mmio_handle = rman_get_bushandle(sc->mmio_res);
611
612 /* Attach "smbus" child */
613 if ((err = bus_generic_attach(dev)) != 0) {
614 device_printf(dev, "failed to attach child: %d\n", err);
615 err = ENXIO;
616 goto fail;
617 }
618
619 bus_dma_tag_create(bus_get_dma_tag(dev), 4, PAGE_SIZE,
620 BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
621 DESC_SIZE, 1, DESC_SIZE,
622 0, NULL, NULL, &sc->desc_dma_tag);
623
624 bus_dma_tag_create(bus_get_dma_tag(dev), 4, PAGE_SIZE,
625 BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
626 DMA_BUFFER_SIZE, 1, DMA_BUFFER_SIZE,
627 0, NULL, NULL, &sc->dma_buffer_dma_tag);
628
629 bus_dmamap_create(sc->desc_dma_tag, 0,
630 &sc->desc_dma_map);
631 bus_dmamap_create(sc->dma_buffer_dma_tag, 0,
632 &sc->dma_buffer_dma_map);
633
634 bus_dmamem_alloc(sc->desc_dma_tag,
635 (void **)&sc->desc, BUS_DMA_WAITOK,
636 &sc->desc_dma_map);
637 bus_dmamem_alloc(sc->dma_buffer_dma_tag,
638 (void **)&sc->dma_buffer, BUS_DMA_WAITOK,
639 &sc->dma_buffer_dma_map);
640
641 bus_dmamap_load(sc->desc_dma_tag,
642 sc->desc_dma_map, sc->desc, DESC_SIZE,
643 ismt_single_map, &sc->desc_bus_addr, 0);
644 bus_dmamap_load(sc->dma_buffer_dma_tag,
645 sc->dma_buffer_dma_map, sc->dma_buffer, DMA_BUFFER_SIZE,
646 ismt_single_map, &sc->dma_buffer_bus_addr, 0);
647
648 bus_write_4(sc->mmio_res, ISMT_MSTR_MDBA,
649 (sc->desc_bus_addr & 0xFFFFFFFFLL));
650 bus_write_4(sc->mmio_res, ISMT_MSTR_MDBA + 4,
651 (sc->desc_bus_addr >> 32));
652
653 /* initialize the Master Control Register (MCTRL) */
654 bus_write_4(sc->mmio_res, ISMT_MSTR_MCTRL, ISMT_MCTRL_MEIE);
655
656 /* initialize the Master Status Register (MSTS) */
657 bus_write_4(sc->mmio_res, ISMT_MSTR_MSTS, 0);
658
659 /* initialize the Master Descriptor Size (MDS) */
660 val = bus_read_4(sc->mmio_res, ISMT_MSTR_MDS);
661 val &= ~ISMT_MDS_MASK;
662 val |= (ISMT_DESC_ENTRIES - 1);
663 bus_write_4(sc->mmio_res, ISMT_MSTR_MDS, val);
664
665 sc->using_msi = 1;
666
667 if (pci_msi_count(dev) == 0) {
668 sc->using_msi = 0;
669 goto intx;
670 }
671
672 num_vectors = 1;
673 if (pci_alloc_msi(dev, &num_vectors) != 0) {
674 sc->using_msi = 0;
675 goto intx;
676 }
677
678 sc->intr_rid = 1;
679 sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
680 &sc->intr_rid, RF_ACTIVE);
681
682 if (sc->intr_res == NULL) {
683 sc->using_msi = 0;
684 pci_release_msi(dev);
685 }
686
687 intx:
688 if (sc->using_msi == 0) {
689 sc->intr_rid = 0;
690 sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
691 &sc->intr_rid, RF_SHAREABLE | RF_ACTIVE);
692 if (sc->intr_res == NULL) {
693 device_printf(dev, "cannot allocate irq\n");
694 err = ENXIO;
695 goto fail;
696 }
697 }
698
699 ISMT_DEBUG(dev, "using_msi = %d\n", sc->using_msi);
700
701 err = bus_setup_intr(dev, sc->intr_res,
702 INTR_TYPE_MISC | INTR_MPSAFE, NULL, ismt_intr, sc,
703 &sc->intr_handle);
704 if (err != 0) {
705 device_printf(dev, "cannot setup interrupt\n");
706 err = ENXIO;
707 goto fail;
708 }
709
710 return (0);
711
712 fail:
713 ismt_detach(dev);
714 return (err);
715 }
716
717 #define ID_INTEL_S1200_SMT0 0x0c598086
718 #define ID_INTEL_S1200_SMT1 0x0c5a8086
719 #define ID_INTEL_C2000_SMT 0x1f158086
720 #define ID_INTEL_C3000_SMT 0x19ac8086
721
722 static int
723 ismt_probe(device_t dev)
724 {
725 const char *desc;
726
727 switch (pci_get_devid(dev)) {
728 case ID_INTEL_S1200_SMT0:
729 desc = "Atom Processor S1200 SMBus 2.0 Controller 0";
730 break;
731 case ID_INTEL_S1200_SMT1:
732 desc = "Atom Processor S1200 SMBus 2.0 Controller 1";
733 break;
734 case ID_INTEL_C2000_SMT:
735 desc = "Atom Processor C2000 SMBus 2.0";
736 break;
737 case ID_INTEL_C3000_SMT:
738 desc = "Atom Processor C3000 SMBus 2.0";
739 break;
740 default:
741 return (ENXIO);
742 }
743
744 device_set_desc(dev, desc);
745 return (BUS_PROBE_DEFAULT);
746 }
747
748 /* Device methods */
749 static device_method_t ismt_pci_methods[] = {
750 DEVMETHOD(device_probe, ismt_probe),
751 DEVMETHOD(device_attach, ismt_attach),
752 DEVMETHOD(device_detach, ismt_detach),
753
754 DEVMETHOD(smbus_callback, ismt_callback),
755 DEVMETHOD(smbus_quick, ismt_quick),
756 DEVMETHOD(smbus_sendb, ismt_sendb),
757 DEVMETHOD(smbus_recvb, ismt_recvb),
758 DEVMETHOD(smbus_writeb, ismt_writeb),
759 DEVMETHOD(smbus_writew, ismt_writew),
760 DEVMETHOD(smbus_readb, ismt_readb),
761 DEVMETHOD(smbus_readw, ismt_readw),
762 DEVMETHOD(smbus_pcall, ismt_pcall),
763 DEVMETHOD(smbus_bwrite, ismt_bwrite),
764 DEVMETHOD(smbus_bread, ismt_bread),
765
766 DEVMETHOD_END
767 };
768
769 static driver_t ismt_pci_driver = {
770 "ismt",
771 ismt_pci_methods,
772 sizeof(struct ismt_softc)
773 };
774
775 DRIVER_MODULE(ismt, pci, ismt_pci_driver, 0, 0);
776 DRIVER_MODULE(smbus, ismt, smbus_driver, 0, 0);
777
778 MODULE_DEPEND(ismt, pci, 1, 1, 1);
779 MODULE_DEPEND(ismt, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
780 MODULE_VERSION(ismt, 1);
Cache object: fbbe6782aff6599e278e394faa8aac21
|