| @@ -1,855 +1,854 @@ | | | @@ -1,855 +1,854 @@ |
1 | /*- | | 1 | /*- |
2 | * Copyright (c) 2016 The NetBSD Foundation, Inc. | | 2 | * Copyright (c) 2016 The NetBSD Foundation, Inc. |
3 | * All rights reserved. | | 3 | * All rights reserved. |
4 | * | | 4 | * |
5 | * This code is derived from software contributed to The NetBSD Foundation | | 5 | * This code is derived from software contributed to The NetBSD Foundation |
6 | * by Masanobu SAITOH. | | 6 | * by Masanobu SAITOH. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | | 15 | * documentation and/or other materials provided with the distribution. |
16 | * | | 16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 17 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
19 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 19 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
20 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 20 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
27 | * POSSIBILITY OF SUCH DAMAGE. | | 27 | * POSSIBILITY OF SUCH DAMAGE. |
28 | */ | | 28 | */ |
29 | | | 29 | |
30 | /*- | | 30 | /*- |
31 | * Copyright (C) 2014 Intel Corporation | | 31 | * Copyright (C) 2014 Intel Corporation |
32 | * All rights reserved. | | 32 | * All rights reserved. |
33 | * | | 33 | * |
34 | * Redistribution and use in source and binary forms, with or without | | 34 | * Redistribution and use in source and binary forms, with or without |
35 | * modification, are permitted provided that the following conditions | | 35 | * modification, are permitted provided that the following conditions |
36 | * are met: | | 36 | * are met: |
37 | * 1. Redistributions of source code must retain the above copyright | | 37 | * 1. Redistributions of source code must retain the above copyright |
38 | * notice, this list of conditions and the following disclaimer. | | 38 | * notice, this list of conditions and the following disclaimer. |
39 | * 2. Redistributions in binary form must reproduce the above copyright | | 39 | * 2. Redistributions in binary form must reproduce the above copyright |
40 | * notice, this list of conditions and the following disclaimer in the | | 40 | * notice, this list of conditions and the following disclaimer in the |
41 | * documentation and/or other materials provided with the distribution. | | 41 | * documentation and/or other materials provided with the distribution. |
42 | * 3. Neither the name of Intel Corporation nor the names of its | | 42 | * 3. Neither the name of Intel Corporation nor the names of its |
43 | * contributors may be used to endorse or promote products derived from | | 43 | * contributors may be used to endorse or promote products derived from |
44 | * this software without specific prior written permission. | | 44 | * this software without specific prior written permission. |
45 | * | | 45 | * |
46 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | | 46 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
47 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 47 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
48 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 48 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
49 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | | 49 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
50 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 50 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
51 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 51 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
52 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 52 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
53 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 53 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
54 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 54 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
55 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 55 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
56 | * SUCH DAMAGE. | | 56 | * SUCH DAMAGE. |
57 | */ | | 57 | */ |
58 | | | 58 | |
59 | #include <sys/cdefs.h> | | 59 | #include <sys/cdefs.h> |
60 | #if 0 | | 60 | #if 0 |
61 | __FBSDID("$FreeBSD: head/sys/dev/ismt/ismt.c 266474 2014-05-20 19:55:06Z jimharris $"); | | 61 | __FBSDID("$FreeBSD: head/sys/dev/ismt/ismt.c 266474 2014-05-20 19:55:06Z jimharris $"); |
62 | #endif | | 62 | #endif |
63 | __KERNEL_RCSID(0, "$NetBSD: ismt.c,v 1.7.10.1 2021/03/24 14:21:08 thorpej Exp $"); | | 63 | __KERNEL_RCSID(0, "$NetBSD: ismt.c,v 1.7.10.2 2021/04/03 01:52:16 thorpej Exp $"); |
64 | | | 64 | |
65 | #include <sys/param.h> | | 65 | #include <sys/param.h> |
66 | #include <sys/systm.h> | | 66 | #include <sys/systm.h> |
67 | #include <sys/device.h> | | 67 | #include <sys/device.h> |
68 | #include <sys/errno.h> | | 68 | #include <sys/errno.h> |
69 | #include <sys/kernel.h> | | 69 | #include <sys/kernel.h> |
70 | #include <sys/module.h> | | 70 | #include <sys/module.h> |
71 | #include <sys/proc.h> | | 71 | #include <sys/proc.h> |
72 | | | 72 | |
73 | #include <sys/bus.h> | | 73 | #include <sys/bus.h> |
74 | | | 74 | |
75 | #include <dev/pci/pcidevs.h> | | 75 | #include <dev/pci/pcidevs.h> |
76 | #include <dev/pci/pcireg.h> | | 76 | #include <dev/pci/pcireg.h> |
77 | #include <dev/pci/pcivar.h> | | 77 | #include <dev/pci/pcivar.h> |
78 | | | 78 | |
79 | #include <dev/i2c/i2cvar.h> | | 79 | #include <dev/i2c/i2cvar.h> |
80 | | | 80 | |
81 | #define ISMT_DESC_ENTRIES 32 | | 81 | #define ISMT_DESC_ENTRIES 32 |
82 | | | 82 | |
83 | /* Hardware Descriptor Constants - Control Field */ | | 83 | /* Hardware Descriptor Constants - Control Field */ |
84 | #define ISMT_DESC_CWRL 0x01 /* Command/Write Length */ | | 84 | #define ISMT_DESC_CWRL 0x01 /* Command/Write Length */ |
85 | #define ISMT_DESC_BLK 0X04 /* Perform Block Transaction */ | | 85 | #define ISMT_DESC_BLK 0X04 /* Perform Block Transaction */ |
86 | #define ISMT_DESC_FAIR 0x08 /* Set fairness flag upon successful arbit. */ | | 86 | #define ISMT_DESC_FAIR 0x08 /* Set fairness flag upon successful arbit. */ |
87 | #define ISMT_DESC_PEC 0x10 /* Packet Error Code */ | | 87 | #define ISMT_DESC_PEC 0x10 /* Packet Error Code */ |
88 | #define ISMT_DESC_I2C 0x20 /* I2C Enable */ | | 88 | #define ISMT_DESC_I2C 0x20 /* I2C Enable */ |
89 | #define ISMT_DESC_INT 0x40 /* Interrupt */ | | 89 | #define ISMT_DESC_INT 0x40 /* Interrupt */ |
90 | #define ISMT_DESC_SOE 0x80 /* Stop On Error */ | | 90 | #define ISMT_DESC_SOE 0x80 /* Stop On Error */ |
91 | | | 91 | |
92 | /* Hardware Descriptor Constants - Status Field */ | | 92 | /* Hardware Descriptor Constants - Status Field */ |
93 | #define ISMT_DESC_SCS 0x01 /* Success */ | | 93 | #define ISMT_DESC_SCS 0x01 /* Success */ |
94 | #define ISMT_DESC_DLTO 0x04 /* Data Low Time Out */ | | 94 | #define ISMT_DESC_DLTO 0x04 /* Data Low Time Out */ |
95 | #define ISMT_DESC_NAK 0x08 /* NAK Received */ | | 95 | #define ISMT_DESC_NAK 0x08 /* NAK Received */ |
96 | #define ISMT_DESC_CRC 0x10 /* CRC Error */ | | 96 | #define ISMT_DESC_CRC 0x10 /* CRC Error */ |
97 | #define ISMT_DESC_CLTO 0x20 /* Clock Low Time Out */ | | 97 | #define ISMT_DESC_CLTO 0x20 /* Clock Low Time Out */ |
98 | #define ISMT_DESC_COL 0x40 /* Collisions */ | | 98 | #define ISMT_DESC_COL 0x40 /* Collisions */ |
99 | #define ISMT_DESC_LPR 0x80 /* Large Packet Received */ | | 99 | #define ISMT_DESC_LPR 0x80 /* Large Packet Received */ |
100 | | | 100 | |
101 | /* Macros */ | | 101 | /* Macros */ |
102 | #define ISMT_DESC_ADDR_RW(addr, is_read) (((addr) << 1) | (is_read)) | | 102 | #define ISMT_DESC_ADDR_RW(addr, is_read) (((addr) << 1) | (is_read)) |
103 | | | 103 | |
104 | /* iSMT General Register address offsets (SMBBAR + <addr>) */ | | 104 | /* iSMT General Register address offsets (SMBBAR + <addr>) */ |
105 | #define ISMT_GR_GCTRL 0x000 /* General Control */ | | 105 | #define ISMT_GR_GCTRL 0x000 /* General Control */ |
106 | #define ISMT_GR_SMTICL 0x008 /* SMT Interrupt Cause Location */ | | 106 | #define ISMT_GR_SMTICL 0x008 /* SMT Interrupt Cause Location */ |
107 | #define ISMT_GR_ERRINTMSK 0x010 /* Error Interrupt Mask */ | | 107 | #define ISMT_GR_ERRINTMSK 0x010 /* Error Interrupt Mask */ |
108 | #define ISMT_GR_ERRAERMSK 0x014 /* Error AER Mask */ | | 108 | #define ISMT_GR_ERRAERMSK 0x014 /* Error AER Mask */ |
109 | #define ISMT_GR_ERRSTS 0x018 /* Error Status */ | | 109 | #define ISMT_GR_ERRSTS 0x018 /* Error Status */ |
110 | #define ISMT_GR_ERRINFO 0x01c /* Error Information */ | | 110 | #define ISMT_GR_ERRINFO 0x01c /* Error Information */ |
111 | | | 111 | |
112 | /* iSMT Master Registers */ | | 112 | /* iSMT Master Registers */ |
113 | #define ISMT_MSTR_MDBA 0x100 /* Master Descriptor Base Address */ | | 113 | #define ISMT_MSTR_MDBA 0x100 /* Master Descriptor Base Address */ |
114 | #define ISMT_MSTR_MCTRL 0x108 /* Master Control */ | | 114 | #define ISMT_MSTR_MCTRL 0x108 /* Master Control */ |
115 | #define ISMT_MSTR_MSTS 0x10c /* Master Status */ | | 115 | #define ISMT_MSTR_MSTS 0x10c /* Master Status */ |
116 | #define ISMT_MSTR_MDS 0x110 /* Master Descriptor Size */ | | 116 | #define ISMT_MSTR_MDS 0x110 /* Master Descriptor Size */ |
117 | #define ISMT_MSTR_RPOLICY 0x114 /* Retry Policy */ | | 117 | #define ISMT_MSTR_RPOLICY 0x114 /* Retry Policy */ |
118 | | | 118 | |
119 | /* iSMT Miscellaneous Registers */ | | 119 | /* iSMT Miscellaneous Registers */ |
120 | #define ISMT_SPGT 0x300 /* SMBus PHY Global Timing */ | | 120 | #define ISMT_SPGT 0x300 /* SMBus PHY Global Timing */ |
121 | | | 121 | |
122 | /* General Control Register (GCTRL) bit definitions */ | | 122 | /* General Control Register (GCTRL) bit definitions */ |
123 | #define ISMT_GCTRL_TRST 0x04 /* Target Reset */ | | 123 | #define ISMT_GCTRL_TRST 0x04 /* Target Reset */ |
124 | #define ISMT_GCTRL_KILL 0x08 /* Kill */ | | 124 | #define ISMT_GCTRL_KILL 0x08 /* Kill */ |
125 | #define ISMT_GCTRL_SRST 0x40 /* Soft Reset */ | | 125 | #define ISMT_GCTRL_SRST 0x40 /* Soft Reset */ |
126 | | | 126 | |
127 | /* Master Control Register (MCTRL) bit definitions */ | | 127 | /* Master Control Register (MCTRL) bit definitions */ |
128 | #define ISMT_MCTRL_SS 0x01 /* Start/Stop */ | | 128 | #define ISMT_MCTRL_SS 0x01 /* Start/Stop */ |
129 | #define ISMT_MCTRL_MEIE 0x10 /* Master Error Interrupt Enable */ | | 129 | #define ISMT_MCTRL_MEIE 0x10 /* Master Error Interrupt Enable */ |
130 | #define ISMT_MCTRL_FMHP 0x00ff0000 /* Firmware Master Head Ptr (FMHP) */ | | 130 | #define ISMT_MCTRL_FMHP 0x00ff0000 /* Firmware Master Head Ptr (FMHP) */ |
131 | | | 131 | |
132 | /* Master Status Register (MSTS) bit definitions */ | | 132 | /* Master Status Register (MSTS) bit definitions */ |
133 | #define ISMT_MSTS_HMTP 0xff0000 /* HW Master Tail Pointer (HMTP) */ | | 133 | #define ISMT_MSTS_HMTP 0xff0000 /* HW Master Tail Pointer (HMTP) */ |
134 | #define ISMT_MSTS_MIS 0x20 /* Master Interrupt Status (MIS) */ | | 134 | #define ISMT_MSTS_MIS 0x20 /* Master Interrupt Status (MIS) */ |
135 | #define ISMT_MSTS_MEIS 0x10 /* Master Error Int Status (MEIS) */ | | 135 | #define ISMT_MSTS_MEIS 0x10 /* Master Error Int Status (MEIS) */ |
136 | #define ISMT_MSTS_IP 0x01 /* In Progress */ | | 136 | #define ISMT_MSTS_IP 0x01 /* In Progress */ |
137 | | | 137 | |
138 | /* Master Descriptor Size (MDS) bit definitions */ | | 138 | /* Master Descriptor Size (MDS) bit definitions */ |
139 | #define ISMT_MDS_MASK 0xff /* Master Descriptor Size mask (MDS) */ | | 139 | #define ISMT_MDS_MASK 0xff /* Master Descriptor Size mask (MDS) */ |
140 | | | 140 | |
141 | /* SMBus PHY Global Timing Register (SPGT) bit definitions */ | | 141 | /* SMBus PHY Global Timing Register (SPGT) bit definitions */ |
142 | #define ISMT_SPGT_SPD_MASK 0xc0000000 /* SMBus Speed mask */ | | 142 | #define ISMT_SPGT_SPD_MASK 0xc0000000 /* SMBus Speed mask */ |
143 | #define ISMT_SPGT_SPD_80K 0x00 /* 80 kHz */ | | 143 | #define ISMT_SPGT_SPD_80K 0x00 /* 80 kHz */ |
144 | #define ISMT_SPGT_SPD_100K (0x1 << 30) /* 100 kHz */ | | 144 | #define ISMT_SPGT_SPD_100K (0x1 << 30) /* 100 kHz */ |
145 | #define ISMT_SPGT_SPD_400K (0x2 << 30) /* 400 kHz */ | | 145 | #define ISMT_SPGT_SPD_400K (0x2 << 30) /* 400 kHz */ |
146 | #define ISMT_SPGT_SPD_1M (0x3 << 30) /* 1 MHz */ | | 146 | #define ISMT_SPGT_SPD_1M (0x3 << 30) /* 1 MHz */ |
147 | | | 147 | |
148 | /* MSI Control Register (MSICTL) bit definitions */ | | 148 | /* MSI Control Register (MSICTL) bit definitions */ |
149 | #define ISMT_MSICTL_MSIE 0x01 /* MSI Enable */ | | 149 | #define ISMT_MSICTL_MSIE 0x01 /* MSI Enable */ |
150 | | | 150 | |
151 | #define ISMT_MAX_BLOCK_SIZE 32 /* per SMBus spec */ | | 151 | #define ISMT_MAX_BLOCK_SIZE 32 /* per SMBus spec */ |
152 | | | 152 | |
153 | #define ISMT_INTR_TIMEOUT (hz / 50) /* 0.02s */ | | 153 | #define ISMT_INTR_TIMEOUT (hz / 50) /* 0.02s */ |
154 | #define ISMT_POLL_DELAY 100 /* 100usec */ | | 154 | #define ISMT_POLL_DELAY 100 /* 100usec */ |
155 | #define ISMT_POLL_COUNT 200 /* 100usec * 200 = 0.02s */ | | 155 | #define ISMT_POLL_COUNT 200 /* 100usec * 200 = 0.02s */ |
156 | | | 156 | |
157 | //#define ISMT_DEBUG aprint_debug_dev | | 157 | //#define ISMT_DEBUG aprint_debug_dev |
158 | #ifndef ISMT_DEBUG | | 158 | #ifndef ISMT_DEBUG |
159 | #define ISMT_DEBUG(...) | | 159 | #define ISMT_DEBUG(...) |
160 | #endif | | 160 | #endif |
161 | | | 161 | |
162 | #define ISMT_LOW(a) ((a) & 0xFFFFFFFFULL) | | 162 | #define ISMT_LOW(a) ((a) & 0xFFFFFFFFULL) |
163 | #define ISMT_HIGH(a) (((uint64_t)(a) >> 32) & 0xFFFFFFFFFULL) | | 163 | #define ISMT_HIGH(a) (((uint64_t)(a) >> 32) & 0xFFFFFFFFFULL) |
164 | | | 164 | |
165 | /* iSMT Hardware Descriptor */ | | 165 | /* iSMT Hardware Descriptor */ |
166 | struct ismt_desc { | | 166 | struct ismt_desc { |
167 | uint8_t tgtaddr_rw; /* target address & r/w bit */ | | 167 | uint8_t tgtaddr_rw; /* target address & r/w bit */ |
168 | uint8_t wr_len_cmd; /* write length in bytes or a command */ | | 168 | uint8_t wr_len_cmd; /* write length in bytes or a command */ |
169 | uint8_t rd_len; /* read length */ | | 169 | uint8_t rd_len; /* read length */ |
170 | uint8_t control; /* control bits */ | | 170 | uint8_t control; /* control bits */ |
171 | uint8_t status; /* status bits */ | | 171 | uint8_t status; /* status bits */ |
172 | uint8_t retry; /* collision retry and retry count */ | | 172 | uint8_t retry; /* collision retry and retry count */ |
173 | uint8_t rxbytes; /* received bytes */ | | 173 | uint8_t rxbytes; /* received bytes */ |
174 | uint8_t txbytes; /* transmitted bytes */ | | 174 | uint8_t txbytes; /* transmitted bytes */ |
175 | uint32_t dptr_low; /* lower 32 bit of the data pointer */ | | 175 | uint32_t dptr_low; /* lower 32 bit of the data pointer */ |
176 | uint32_t dptr_high; /* upper 32 bit of the data pointer */ | | 176 | uint32_t dptr_high; /* upper 32 bit of the data pointer */ |
177 | } __packed; | | 177 | } __packed; |
178 | | | 178 | |
179 | #define DESC_SIZE (ISMT_DESC_ENTRIES * sizeof(struct ismt_desc)) | | 179 | #define DESC_SIZE (ISMT_DESC_ENTRIES * sizeof(struct ismt_desc)) |
180 | | | 180 | |
181 | #define DMA_BUFFER_SIZE 64 | | 181 | #define DMA_BUFFER_SIZE 64 |
182 | | | 182 | |
183 | struct ismt_softc { | | 183 | struct ismt_softc { |
184 | device_t pcidev; | | 184 | device_t pcidev; |
185 | device_t smbdev; | | 185 | device_t smbdev; |
186 | | | 186 | |
187 | struct i2c_controller sc_i2c_tag; | | 187 | struct i2c_controller sc_i2c_tag; |
188 | | | 188 | |
189 | pci_chipset_tag_t sc_pc; | | 189 | pci_chipset_tag_t sc_pc; |
190 | pcitag_t sc_pcitag; | | 190 | pcitag_t sc_pcitag; |
191 | pci_intr_handle_t *sc_pihp; | | 191 | pci_intr_handle_t *sc_pihp; |
192 | void *sc_ih; | | 192 | void *sc_ih; |
193 | | | 193 | |
194 | bus_space_tag_t mmio_tag; | | 194 | bus_space_tag_t mmio_tag; |
195 | bus_space_handle_t mmio_handle; | | 195 | bus_space_handle_t mmio_handle; |
196 | bus_size_t mmio_size; | | 196 | bus_size_t mmio_size; |
197 | | | 197 | |
198 | uint8_t head; | | 198 | uint8_t head; |
199 | | | 199 | |
200 | struct ismt_desc *desc; | | 200 | struct ismt_desc *desc; |
201 | bus_dma_tag_t desc_dma_tag; | | 201 | bus_dma_tag_t desc_dma_tag; |
202 | bus_dmamap_t desc_dma_map; | | 202 | bus_dmamap_t desc_dma_map; |
203 | bus_dma_segment_t desc_dma_seg; | | 203 | bus_dma_segment_t desc_dma_seg; |
204 | int desc_rseg; | | 204 | int desc_rseg; |
205 | | | 205 | |
206 | uint8_t *dma_buffer; | | 206 | uint8_t *dma_buffer; |
207 | bus_dma_tag_t dma_buffer_dma_tag; | | 207 | bus_dma_tag_t dma_buffer_dma_tag; |
208 | bus_dmamap_t dma_buffer_dma_map; | | 208 | bus_dmamap_t dma_buffer_dma_map; |
209 | bus_dma_segment_t dma_buffer_dma_seg; | | 209 | bus_dma_segment_t dma_buffer_dma_seg; |
210 | int dma_buffer_rseg; | | 210 | int dma_buffer_rseg; |
211 | | | 211 | |
212 | uint8_t using_msi; | | 212 | uint8_t using_msi; |
213 | }; | | 213 | }; |
214 | | | 214 | |
215 | static int ismt_intr(void *); | | 215 | static int ismt_intr(void *); |
216 | static int ismt_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, | | 216 | static int ismt_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, |
217 | size_t, void *, size_t, int); | | 217 | size_t, void *, size_t, int); |
218 | static struct ismt_desc *ismt_alloc_desc(struct ismt_softc *); | | 218 | static struct ismt_desc *ismt_alloc_desc(struct ismt_softc *); |
219 | static int ismt_submit(struct ismt_softc *, struct ismt_desc *, | | 219 | static int ismt_submit(struct ismt_softc *, struct ismt_desc *, |
220 | i2c_addr_t, uint8_t, int); | | 220 | i2c_addr_t, uint8_t, int); |
221 | static int ismt_quick(struct ismt_softc *, i2c_addr_t, i2c_op_t, int); | | 221 | static int ismt_quick(struct ismt_softc *, i2c_addr_t, i2c_op_t, int); |
222 | static int ismt_sendb(struct ismt_softc *, i2c_addr_t, i2c_op_t, char, | | 222 | static int ismt_sendb(struct ismt_softc *, i2c_addr_t, i2c_op_t, char, |
223 | int); | | 223 | int); |
224 | static int ismt_recvb(struct ismt_softc *, i2c_addr_t, i2c_op_t, int); | | 224 | static int ismt_recvb(struct ismt_softc *, i2c_addr_t, i2c_op_t, int); |
225 | static int ismt_writeb(struct ismt_softc *, i2c_addr_t, i2c_op_t, uint8_t, | | 225 | static int ismt_writeb(struct ismt_softc *, i2c_addr_t, i2c_op_t, uint8_t, |
226 | char, int); | | 226 | char, int); |
227 | static int ismt_writew(struct ismt_softc *, i2c_addr_t, i2c_op_t, uint8_t, | | 227 | static int ismt_writew(struct ismt_softc *, i2c_addr_t, i2c_op_t, uint8_t, |
228 | uint16_t, int); | | 228 | uint16_t, int); |
229 | static int ismt_readb(struct ismt_softc *, i2c_addr_t, i2c_op_t, char, | | 229 | static int ismt_readb(struct ismt_softc *, i2c_addr_t, i2c_op_t, char, |
230 | int); | | 230 | int); |
231 | static int ismt_readw(struct ismt_softc *, i2c_addr_t, i2c_op_t, char, | | 231 | static int ismt_readw(struct ismt_softc *, i2c_addr_t, i2c_op_t, char, |
232 | int); | | 232 | int); |
233 | | | 233 | |
234 | static int ismt_match(device_t, cfdata_t, void *); | | 234 | static int ismt_match(device_t, cfdata_t, void *); |
235 | static void ismt_attach(device_t, device_t, void *); | | 235 | static void ismt_attach(device_t, device_t, void *); |
236 | static int ismt_detach(device_t, int); | | 236 | static int ismt_detach(device_t, int); |
237 | static int ismt_rescan(device_t, const char *, const int *); | | 237 | static int ismt_rescan(device_t, const char *, const int *); |
238 | static void ismt_config_interrupts(device_t); | | 238 | static void ismt_config_interrupts(device_t); |
239 | static void ismt_chdet(device_t, device_t); | | 239 | static void ismt_chdet(device_t, device_t); |
240 | | | 240 | |
241 | CFATTACH_DECL3_NEW(ismt, sizeof(struct ismt_softc), | | 241 | CFATTACH_DECL3_NEW(ismt, sizeof(struct ismt_softc), |
242 | ismt_match, ismt_attach, ismt_detach, NULL, ismt_rescan, ismt_chdet, | | 242 | ismt_match, ismt_attach, ismt_detach, NULL, ismt_rescan, ismt_chdet, |
243 | DVF_DETACH_SHUTDOWN); | | 243 | DVF_DETACH_SHUTDOWN); |
244 | | | 244 | |
245 | static int | | 245 | static int |
246 | ismt_intr(void *arg) | | 246 | ismt_intr(void *arg) |
247 | { | | 247 | { |
248 | struct ismt_softc *sc = arg; | | 248 | struct ismt_softc *sc = arg; |
249 | uint32_t val; | | 249 | uint32_t val; |
250 | | | 250 | |
251 | val = bus_space_read_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MSTS); | | 251 | val = bus_space_read_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MSTS); |
252 | if ((sc->using_msi == 0) | | 252 | if ((sc->using_msi == 0) |
253 | && (val & (ISMT_MSTS_MIS | ISMT_MSTS_MEIS)) == 0) | | 253 | && (val & (ISMT_MSTS_MIS | ISMT_MSTS_MEIS)) == 0) |
254 | return 0; /* Not for me */ | | 254 | return 0; /* Not for me */ |
255 | | | 255 | |
256 | ISMT_DEBUG(sc->pcidev, "%s MSTS = 0x%08x\n", __func__, val); | | 256 | ISMT_DEBUG(sc->pcidev, "%s MSTS = 0x%08x\n", __func__, val); |
257 | | | 257 | |
258 | val |= (ISMT_MSTS_MIS | ISMT_MSTS_MEIS); | | 258 | val |= (ISMT_MSTS_MIS | ISMT_MSTS_MEIS); |
259 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MSTS, val); | | 259 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MSTS, val); |
260 | | | 260 | |
261 | if (sc->using_msi) | | 261 | if (sc->using_msi) |
262 | wakeup(sc); | | 262 | wakeup(sc); |
263 | | | 263 | |
264 | return 1; | | 264 | return 1; |
265 | } | | 265 | } |
266 | | | 266 | |
267 | static int | | 267 | static int |
268 | ismt_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, | | 268 | ismt_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, |
269 | const void *cmd, size_t cmdlen, void *buf, size_t buflen, int flags) | | 269 | const void *cmd, size_t cmdlen, void *buf, size_t buflen, int flags) |
270 | { | | 270 | { |
271 | struct ismt_softc *sc = cookie; | | 271 | struct ismt_softc *sc = cookie; |
272 | uint8_t *p = buf; | | 272 | uint8_t *p = buf; |
273 | int rv; | | 273 | int rv; |
274 | | | 274 | |
275 | ISMT_DEBUG(sc->pcidev, "exec: op %d, addr 0x%02x, cmdlen %zu, " | | 275 | ISMT_DEBUG(sc->pcidev, "exec: op %d, addr 0x%02x, cmdlen %zu, " |
276 | " buflen %zu, flags 0x%02x\n", op, addr, cmdlen, buflen, flags); | | 276 | " buflen %zu, flags 0x%02x\n", op, addr, cmdlen, buflen, flags); |
277 | | | 277 | |
278 | if ((cmdlen == 0) && (buflen == 0)) | | 278 | if ((cmdlen == 0) && (buflen == 0)) |
279 | return ismt_quick(sc, addr, op, flags); | | 279 | return ismt_quick(sc, addr, op, flags); |
280 | | | 280 | |
281 | if (I2C_OP_READ_P(op) && (cmdlen == 0) && (buflen == 1)) { | | 281 | if (I2C_OP_READ_P(op) && (cmdlen == 0) && (buflen == 1)) { |
282 | rv = ismt_recvb(sc, addr, op, flags); | | 282 | rv = ismt_recvb(sc, addr, op, flags); |
283 | if (rv == -1) | | 283 | if (rv == -1) |
284 | return -1; | | 284 | return -1; |
285 | *p = (uint8_t)rv; | | 285 | *p = (uint8_t)rv; |
286 | return 0; | | 286 | return 0; |
287 | } | | 287 | } |
288 | | | 288 | |
289 | if ((I2C_OP_READ_P(op)) && (cmdlen == 1) && (buflen == 1)) { | | 289 | if ((I2C_OP_READ_P(op)) && (cmdlen == 1) && (buflen == 1)) { |
290 | rv = ismt_readb(sc, addr, op, *(const uint8_t*)cmd, flags); | | 290 | rv = ismt_readb(sc, addr, op, *(const uint8_t*)cmd, flags); |
291 | if (rv == -1) | | 291 | if (rv == -1) |
292 | return -1; | | 292 | return -1; |
293 | *p = (uint8_t)rv; | | 293 | *p = (uint8_t)rv; |
294 | return 0; | | 294 | return 0; |
295 | } | | 295 | } |
296 | | | 296 | |
297 | if ((I2C_OP_READ_P(op)) && (cmdlen == 1) && (buflen == 2)) { | | 297 | if ((I2C_OP_READ_P(op)) && (cmdlen == 1) && (buflen == 2)) { |
298 | rv = ismt_readw(sc, addr, op, *(const uint8_t*)cmd, flags); | | 298 | rv = ismt_readw(sc, addr, op, *(const uint8_t*)cmd, flags); |
299 | if (rv == -1) | | 299 | if (rv == -1) |
300 | return -1; | | 300 | return -1; |
301 | *(uint16_t *)p = (uint16_t)rv; | | 301 | *(uint16_t *)p = (uint16_t)rv; |
302 | return 0; | | 302 | return 0; |
303 | } | | 303 | } |
304 | | | 304 | |
305 | if ((I2C_OP_WRITE_P(op)) && (cmdlen == 0) && (buflen == 1)) | | 305 | if ((I2C_OP_WRITE_P(op)) && (cmdlen == 0) && (buflen == 1)) |
306 | return ismt_sendb(sc, addr, op, *(uint8_t*)buf, flags); | | 306 | return ismt_sendb(sc, addr, op, *(uint8_t*)buf, flags); |
307 | | | 307 | |
308 | if ((I2C_OP_WRITE_P(op)) && (cmdlen == 1) && (buflen == 1)) | | 308 | if ((I2C_OP_WRITE_P(op)) && (cmdlen == 1) && (buflen == 1)) |
309 | return ismt_writeb(sc, addr, op, *(const uint8_t*)cmd, | | 309 | return ismt_writeb(sc, addr, op, *(const uint8_t*)cmd, |
310 | *(uint8_t*)buf, flags); | | 310 | *(uint8_t*)buf, flags); |
311 | | | 311 | |
312 | if ((I2C_OP_WRITE_P(op)) && (cmdlen == 1) && (buflen == 2)) | | 312 | if ((I2C_OP_WRITE_P(op)) && (cmdlen == 1) && (buflen == 2)) |
313 | return ismt_writew(sc, addr, op, | | 313 | return ismt_writew(sc, addr, op, |
314 | *(const uint8_t*)cmd, *((uint16_t *)buf), flags); | | 314 | *(const uint8_t*)cmd, *((uint16_t *)buf), flags); |
315 | | | 315 | |
316 | return -1; | | 316 | return -1; |
317 | } | | 317 | } |
318 | | | 318 | |
319 | static struct ismt_desc * | | 319 | static struct ismt_desc * |
320 | ismt_alloc_desc(struct ismt_softc *sc) | | 320 | ismt_alloc_desc(struct ismt_softc *sc) |
321 | { | | 321 | { |
322 | struct ismt_desc *desc; | | 322 | struct ismt_desc *desc; |
323 | | | 323 | |
324 | desc = &sc->desc[sc->head++]; | | 324 | desc = &sc->desc[sc->head++]; |
325 | if (sc->head == ISMT_DESC_ENTRIES) | | 325 | if (sc->head == ISMT_DESC_ENTRIES) |
326 | sc->head = 0; | | 326 | sc->head = 0; |
327 | | | 327 | |
328 | memset(desc, 0, sizeof(*desc)); | | 328 | memset(desc, 0, sizeof(*desc)); |
329 | | | 329 | |
330 | return (desc); | | 330 | return (desc); |
331 | } | | 331 | } |
332 | | | 332 | |
333 | static int | | 333 | static int |
334 | ismt_submit(struct ismt_softc *sc, struct ismt_desc *desc, i2c_addr_t slave, | | 334 | ismt_submit(struct ismt_softc *sc, struct ismt_desc *desc, i2c_addr_t slave, |
335 | uint8_t is_read, int flags) | | 335 | uint8_t is_read, int flags) |
336 | { | | 336 | { |
337 | uint32_t err, fmhp, val; | | 337 | uint32_t err, fmhp, val; |
338 | int timeout, i; | | 338 | int timeout, i; |
339 | | | 339 | |
340 | if (sc->using_msi == 0) | | 340 | if (sc->using_msi == 0) |
341 | flags |= I2C_F_POLL; | | 341 | flags |= I2C_F_POLL; |
342 | desc->control |= ISMT_DESC_FAIR; | | 342 | desc->control |= ISMT_DESC_FAIR; |
343 | if ((flags & I2C_F_POLL) == 0) | | 343 | if ((flags & I2C_F_POLL) == 0) |
344 | desc->control |= ISMT_DESC_INT; | | 344 | desc->control |= ISMT_DESC_INT; |
345 | | | 345 | |
346 | desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(slave, is_read); | | 346 | desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(slave, is_read); |
347 | desc->dptr_low = ISMT_LOW(sc->dma_buffer_dma_map->dm_segs[0].ds_addr); | | 347 | desc->dptr_low = ISMT_LOW(sc->dma_buffer_dma_map->dm_segs[0].ds_addr); |
348 | desc->dptr_high = ISMT_HIGH(sc->dma_buffer_dma_map->dm_segs[0].ds_addr); | | 348 | desc->dptr_high = ISMT_HIGH(sc->dma_buffer_dma_map->dm_segs[0].ds_addr); |
349 | | | 349 | |
350 | bus_dmamap_sync(sc->desc_dma_tag, sc->desc_dma_map, | | 350 | bus_dmamap_sync(sc->desc_dma_tag, sc->desc_dma_map, |
351 | desc - &sc->desc[0], sizeof(struct ismt_desc), | | 351 | desc - &sc->desc[0], sizeof(struct ismt_desc), |
352 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | | 352 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
353 | | | 353 | |
354 | fmhp = sc->head << 16; | | 354 | fmhp = sc->head << 16; |
355 | val = bus_space_read_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MCTRL); | | 355 | val = bus_space_read_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MCTRL); |
356 | val &= ~ISMT_MCTRL_FMHP; | | 356 | val &= ~ISMT_MCTRL_FMHP; |
357 | val |= fmhp; | | 357 | val |= fmhp; |
358 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MCTRL, val); | | 358 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MCTRL, val); |
359 | | | 359 | |
360 | /* set the start bit */ | | 360 | /* set the start bit */ |
361 | val = bus_space_read_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MCTRL); | | 361 | val = bus_space_read_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MCTRL); |
362 | val |= ISMT_MCTRL_SS; | | 362 | val |= ISMT_MCTRL_SS; |
363 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MCTRL, val); | | 363 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MCTRL, val); |
364 | | | 364 | |
365 | i = 0; | | 365 | i = 0; |
366 | if ((flags & I2C_F_POLL) == 0) { | | 366 | if ((flags & I2C_F_POLL) == 0) { |
367 | timeout = ISMT_INTR_TIMEOUT; | | 367 | timeout = ISMT_INTR_TIMEOUT; |
368 | if (timeout == 0) | | 368 | if (timeout == 0) |
369 | timeout = 1; | | 369 | timeout = 1; |
370 | err = tsleep(sc, PWAIT, "ismt_wait", timeout); | | 370 | err = tsleep(sc, PWAIT, "ismt_wait", timeout); |
371 | if (err != 0) { | | 371 | if (err != 0) { |
372 | ISMT_DEBUG(sc->pcidev, "%s timeout\n", __func__); | | 372 | ISMT_DEBUG(sc->pcidev, "%s timeout\n", __func__); |
373 | return -1; | | 373 | return -1; |
374 | } | | 374 | } |
375 | } else { | | 375 | } else { |
376 | /* Polling */ | | 376 | /* Polling */ |
377 | for (i = 0; i < ISMT_POLL_COUNT; i++) { | | 377 | for (i = 0; i < ISMT_POLL_COUNT; i++) { |
378 | val = bus_space_read_4(sc->mmio_tag, sc->mmio_handle, | | 378 | val = bus_space_read_4(sc->mmio_tag, sc->mmio_handle, |
379 | ISMT_MSTR_MSTS); | | 379 | ISMT_MSTR_MSTS); |
380 | if ((val & (ISMT_MSTS_MIS | ISMT_MSTS_MEIS)) != 0) { | | 380 | if ((val & (ISMT_MSTS_MIS | ISMT_MSTS_MEIS)) != 0) { |
381 | ismt_intr(sc); | | 381 | ismt_intr(sc); |
382 | err = 0; | | 382 | err = 0; |
383 | break; | | 383 | break; |
384 | } | | 384 | } |
385 | delay(ISMT_POLL_DELAY); | | 385 | delay(ISMT_POLL_DELAY); |
386 | } | | 386 | } |
387 | if (i >= ISMT_POLL_COUNT) { | | 387 | if (i >= ISMT_POLL_COUNT) { |
388 | ISMT_DEBUG(sc->pcidev, "%s polling timeout. " | | 388 | ISMT_DEBUG(sc->pcidev, "%s polling timeout. " |
389 | "MSTS = %08x\n", __func__, val); | | 389 | "MSTS = %08x\n", __func__, val); |
390 | return -1; | | 390 | return -1; |
391 | } | | 391 | } |
392 | } | | 392 | } |
393 | | | 393 | |
394 | bus_dmamap_sync(sc->desc_dma_tag, sc->desc_dma_map, | | 394 | bus_dmamap_sync(sc->desc_dma_tag, sc->desc_dma_map, |
395 | desc - &sc->desc[0], sizeof(struct ismt_desc), | | 395 | desc - &sc->desc[0], sizeof(struct ismt_desc), |
396 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); | | 396 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
397 | ISMT_DEBUG(sc->pcidev, "%s status=0x%02x\n", __func__, desc->status); | | 397 | ISMT_DEBUG(sc->pcidev, "%s status=0x%02x\n", __func__, desc->status); |
398 | | | 398 | |
399 | if (desc->status & ISMT_DESC_SCS) | | 399 | if (desc->status & ISMT_DESC_SCS) |
400 | return 0; | | 400 | return 0; |
401 | | | 401 | |
402 | if (desc->status & ISMT_DESC_NAK) | | 402 | if (desc->status & ISMT_DESC_NAK) |
403 | return -1; | | 403 | return -1; |
404 | | | 404 | |
405 | if (desc->status & ISMT_DESC_CRC) | | 405 | if (desc->status & ISMT_DESC_CRC) |
406 | return -1; | | 406 | return -1; |
407 | | | 407 | |
408 | if (desc->status & ISMT_DESC_COL) | | 408 | if (desc->status & ISMT_DESC_COL) |
409 | return -1; | | 409 | return -1; |
410 | | | 410 | |
411 | if (desc->status & ISMT_DESC_LPR) | | 411 | if (desc->status & ISMT_DESC_LPR) |
412 | return -1; | | 412 | return -1; |
413 | | | 413 | |
414 | if (desc->status & (ISMT_DESC_DLTO | ISMT_DESC_CLTO)) | | 414 | if (desc->status & (ISMT_DESC_DLTO | ISMT_DESC_CLTO)) |
415 | return -1; | | 415 | return -1; |
416 | | | 416 | |
417 | return -1; | | 417 | return -1; |
418 | } | | 418 | } |
419 | | | 419 | |
420 | static int | | 420 | static int |
421 | ismt_quick(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, int flags) | | 421 | ismt_quick(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, int flags) |
422 | { | | 422 | { |
423 | struct ismt_desc *desc; | | 423 | struct ismt_desc *desc; |
424 | int is_read; | | 424 | int is_read; |
425 | | | 425 | |
426 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); | | 426 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); |
427 | | | 427 | |
428 | desc = ismt_alloc_desc(sc); | | 428 | desc = ismt_alloc_desc(sc); |
429 | is_read = I2C_OP_READ_P(op); | | 429 | is_read = I2C_OP_READ_P(op); |
430 | return (ismt_submit(sc, desc, slave, is_read, flags)); | | 430 | return (ismt_submit(sc, desc, slave, is_read, flags)); |
431 | } | | 431 | } |
432 | | | 432 | |
433 | static int | | 433 | static int |
434 | ismt_sendb(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, char byte, | | 434 | ismt_sendb(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, char byte, |
435 | int flags) | | 435 | int flags) |
436 | { | | 436 | { |
437 | struct ismt_desc *desc; | | 437 | struct ismt_desc *desc; |
438 | | | 438 | |
439 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); | | 439 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); |
440 | | | 440 | |
441 | desc = ismt_alloc_desc(sc); | | 441 | desc = ismt_alloc_desc(sc); |
442 | desc->control = ISMT_DESC_CWRL; | | 442 | desc->control = ISMT_DESC_CWRL; |
443 | desc->wr_len_cmd = byte; | | 443 | desc->wr_len_cmd = byte; |
444 | | | 444 | |
445 | return (ismt_submit(sc, desc, slave, 0, flags)); | | 445 | return (ismt_submit(sc, desc, slave, 0, flags)); |
446 | } | | 446 | } |
447 | | | 447 | |
448 | static int | | 448 | static int |
449 | ismt_recvb(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, int flags) | | 449 | ismt_recvb(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, int flags) |
450 | { | | 450 | { |
451 | struct ismt_desc *desc; | | 451 | struct ismt_desc *desc; |
452 | int err; | | 452 | int err; |
453 | | | 453 | |
454 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); | | 454 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); |
455 | | | 455 | |
456 | desc = ismt_alloc_desc(sc); | | 456 | desc = ismt_alloc_desc(sc); |
457 | desc->rd_len = 1; | | 457 | desc->rd_len = 1; |
458 | | | 458 | |
459 | err = ismt_submit(sc, desc, slave, 1, flags); | | 459 | err = ismt_submit(sc, desc, slave, 1, flags); |
460 | | | 460 | |
461 | if (err != 0) | | 461 | if (err != 0) |
462 | return (err); | | 462 | return (err); |
463 | | | 463 | |
464 | return sc->dma_buffer[0]; | | 464 | return sc->dma_buffer[0]; |
465 | } | | 465 | } |
466 | | | 466 | |
467 | static int | | 467 | static int |
468 | ismt_writeb(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, uint8_t cmd, | | 468 | ismt_writeb(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, uint8_t cmd, |
469 | char byte, int flags) | | 469 | char byte, int flags) |
470 | { | | 470 | { |
471 | struct ismt_desc *desc; | | 471 | struct ismt_desc *desc; |
472 | | | 472 | |
473 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); | | 473 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); |
474 | | | 474 | |
475 | desc = ismt_alloc_desc(sc); | | 475 | desc = ismt_alloc_desc(sc); |
476 | desc->wr_len_cmd = 2; | | 476 | desc->wr_len_cmd = 2; |
477 | sc->dma_buffer[0] = cmd; | | 477 | sc->dma_buffer[0] = cmd; |
478 | sc->dma_buffer[1] = byte; | | 478 | sc->dma_buffer[1] = byte; |
479 | | | 479 | |
480 | return (ismt_submit(sc, desc, slave, 0, flags)); | | 480 | return (ismt_submit(sc, desc, slave, 0, flags)); |
481 | } | | 481 | } |
482 | | | 482 | |
483 | static int | | 483 | static int |
484 | ismt_writew(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, uint8_t cmd, | | 484 | ismt_writew(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, uint8_t cmd, |
485 | uint16_t word, int flags) | | 485 | uint16_t word, int flags) |
486 | { | | 486 | { |
487 | struct ismt_desc *desc; | | 487 | struct ismt_desc *desc; |
488 | | | 488 | |
489 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); | | 489 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); |
490 | | | 490 | |
491 | desc = ismt_alloc_desc(sc); | | 491 | desc = ismt_alloc_desc(sc); |
492 | desc->wr_len_cmd = 3; | | 492 | desc->wr_len_cmd = 3; |
493 | sc->dma_buffer[0] = cmd; | | 493 | sc->dma_buffer[0] = cmd; |
494 | sc->dma_buffer[1] = word & 0xFF; | | 494 | sc->dma_buffer[1] = word & 0xFF; |
495 | sc->dma_buffer[2] = word >> 8; | | 495 | sc->dma_buffer[2] = word >> 8; |
496 | | | 496 | |
497 | return (ismt_submit(sc, desc, slave, 0, flags)); | | 497 | return (ismt_submit(sc, desc, slave, 0, flags)); |
498 | } | | 498 | } |
499 | | | 499 | |
500 | static int | | 500 | static int |
501 | ismt_readb(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, char cmd, | | 501 | ismt_readb(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, char cmd, |
502 | int flags) | | 502 | int flags) |
503 | { | | 503 | { |
504 | struct ismt_desc *desc; | | 504 | struct ismt_desc *desc; |
505 | int err; | | 505 | int err; |
506 | | | 506 | |
507 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); | | 507 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); |
508 | | | 508 | |
509 | desc = ismt_alloc_desc(sc); | | 509 | desc = ismt_alloc_desc(sc); |
510 | desc->control = ISMT_DESC_CWRL; | | 510 | desc->control = ISMT_DESC_CWRL; |
511 | desc->wr_len_cmd = cmd; | | 511 | desc->wr_len_cmd = cmd; |
512 | desc->rd_len = 1; | | 512 | desc->rd_len = 1; |
513 | | | 513 | |
514 | err = ismt_submit(sc, desc, slave, 1, flags); | | 514 | err = ismt_submit(sc, desc, slave, 1, flags); |
515 | | | 515 | |
516 | if (err != 0) | | 516 | if (err != 0) |
517 | return (err); | | 517 | return (err); |
518 | | | 518 | |
519 | return sc->dma_buffer[0]; | | 519 | return sc->dma_buffer[0]; |
520 | } | | 520 | } |
521 | | | 521 | |
522 | static int | | 522 | static int |
523 | ismt_readw(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, char cmd, | | 523 | ismt_readw(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, char cmd, |
524 | int flags) | | 524 | int flags) |
525 | { | | 525 | { |
526 | struct ismt_desc *desc; | | 526 | struct ismt_desc *desc; |
527 | uint16_t word; | | 527 | uint16_t word; |
528 | int err; | | 528 | int err; |
529 | | | 529 | |
530 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); | | 530 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); |
531 | | | 531 | |
532 | desc = ismt_alloc_desc(sc); | | 532 | desc = ismt_alloc_desc(sc); |
533 | desc->control = ISMT_DESC_CWRL; | | 533 | desc->control = ISMT_DESC_CWRL; |
534 | desc->wr_len_cmd = cmd; | | 534 | desc->wr_len_cmd = cmd; |
535 | desc->rd_len = 2; | | 535 | desc->rd_len = 2; |
536 | | | 536 | |
537 | err = ismt_submit(sc, desc, slave, 1, flags); | | 537 | err = ismt_submit(sc, desc, slave, 1, flags); |
538 | | | 538 | |
539 | if (err != 0) | | 539 | if (err != 0) |
540 | return (err); | | 540 | return (err); |
541 | | | 541 | |
542 | word = sc->dma_buffer[0] | (sc->dma_buffer[1] << 8); | | 542 | word = sc->dma_buffer[0] | (sc->dma_buffer[1] << 8); |
543 | | | 543 | |
544 | return word; | | 544 | return word; |
545 | } | | 545 | } |
546 | | | 546 | |
547 | #if 0 | | 547 | #if 0 |
548 | static int | | 548 | static int |
549 | ismt_pcall(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, char cmd, | | 549 | ismt_pcall(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, char cmd, |
550 | uint16_t sdata, uint16_t *rdata, int flags) | | 550 | uint16_t sdata, uint16_t *rdata, int flags) |
551 | { | | 551 | { |
552 | struct ismt_desc *desc; | | 552 | struct ismt_desc *desc; |
553 | int err; | | 553 | int err; |
554 | | | 554 | |
555 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); | | 555 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); |
556 | | | 556 | |
557 | desc = ismt_alloc_desc(sc); | | 557 | desc = ismt_alloc_desc(sc); |
558 | desc->wr_len_cmd = 3; | | 558 | desc->wr_len_cmd = 3; |
559 | desc->rd_len = 2; | | 559 | desc->rd_len = 2; |
560 | sc->dma_buffer[0] = cmd; | | 560 | sc->dma_buffer[0] = cmd; |
561 | sc->dma_buffer[1] = sdata & 0xff; | | 561 | sc->dma_buffer[1] = sdata & 0xff; |
562 | sc->dma_buffer[2] = sdata >> 8; | | 562 | sc->dma_buffer[2] = sdata >> 8; |
563 | | | 563 | |
564 | err = ismt_submit(sc, desc, slave, 0, flags); | | 564 | err = ismt_submit(sc, desc, slave, 0, flags); |
565 | | | 565 | |
566 | if (err != 0) | | 566 | if (err != 0) |
567 | return (err); | | 567 | return (err); |
568 | | | 568 | |
569 | *rdata = sc->dma_buffer[0] | (sc->dma_buffer[1] << 8); | | 569 | *rdata = sc->dma_buffer[0] | (sc->dma_buffer[1] << 8); |
570 | | | 570 | |
571 | return (err); | | 571 | return (err); |
572 | } | | 572 | } |
573 | | | 573 | |
574 | static int | | 574 | static int |
575 | ismt_bwrite(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, char cmd, | | 575 | ismt_bwrite(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, char cmd, |
576 | u_char count, char *buf, int flags) | | 576 | u_char count, char *buf, int flags) |
577 | { | | 577 | { |
578 | struct ismt_desc *desc; | | 578 | struct ismt_desc *desc; |
579 | | | 579 | |
580 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); | | 580 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); |
581 | | | 581 | |
582 | if (count == 0 || count > ISMT_MAX_BLOCK_SIZE) | | 582 | if (count == 0 || count > ISMT_MAX_BLOCK_SIZE) |
583 | return -1; | | 583 | return -1; |
584 | | | 584 | |
585 | desc = ismt_alloc_desc(sc); | | 585 | desc = ismt_alloc_desc(sc); |
586 | desc->control = ISMT_DESC_I2C; | | 586 | desc->control = ISMT_DESC_I2C; |
587 | desc->wr_len_cmd = count + 1; | | 587 | desc->wr_len_cmd = count + 1; |
588 | sc->dma_buffer[0] = cmd; | | 588 | sc->dma_buffer[0] = cmd; |
589 | memcpy(&sc->dma_buffer[1], buf, count); | | 589 | memcpy(&sc->dma_buffer[1], buf, count); |
590 | | | 590 | |
591 | return (ismt_submit(sc, desc, slave, 0, flags)); | | 591 | return (ismt_submit(sc, desc, slave, 0, flags)); |
592 | } | | 592 | } |
593 | | | 593 | |
594 | static int | | 594 | static int |
595 | ismt_bread(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, char cmd, | | 595 | ismt_bread(struct ismt_softc *sc, i2c_addr_t slave, i2c_op_t op, char cmd, |
596 | u_char *count, char *buf, int flags) | | 596 | u_char *count, char *buf, int flags) |
597 | { | | 597 | { |
598 | struct ismt_desc *desc; | | 598 | struct ismt_desc *desc; |
599 | int err; | | 599 | int err; |
600 | | | 600 | |
601 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); | | 601 | ISMT_DEBUG(sc->pcidev, "%s\n", __func__); |
602 | | | 602 | |
603 | if (*count == 0 || *count > ISMT_MAX_BLOCK_SIZE) | | 603 | if (*count == 0 || *count > ISMT_MAX_BLOCK_SIZE) |
604 | return -1; | | 604 | return -1; |
605 | | | 605 | |
606 | desc = ismt_alloc_desc(sc); | | 606 | desc = ismt_alloc_desc(sc); |
607 | desc->control = ISMT_DESC_I2C | ISMT_DESC_CWRL; | | 607 | desc->control = ISMT_DESC_I2C | ISMT_DESC_CWRL; |
608 | desc->wr_len_cmd = cmd; | | 608 | desc->wr_len_cmd = cmd; |
609 | desc->rd_len = *count; | | 609 | desc->rd_len = *count; |
610 | | | 610 | |
611 | err = ismt_submit(sc, desc, slave, 0, flags); | | 611 | err = ismt_submit(sc, desc, slave, 0, flags); |
612 | | | 612 | |
613 | if (err != 0) | | 613 | if (err != 0) |
614 | return (err); | | 614 | return (err); |
615 | | | 615 | |
616 | memcpy(buf, sc->dma_buffer, desc->rxbytes); | | 616 | memcpy(buf, sc->dma_buffer, desc->rxbytes); |
617 | *count = desc->rxbytes; | | 617 | *count = desc->rxbytes; |
618 | | | 618 | |
619 | return (err); | | 619 | return (err); |
620 | } | | 620 | } |
621 | #endif | | 621 | #endif |
622 | | | 622 | |
623 | static int | | 623 | static int |
624 | ismt_detach(device_t self, int flags) | | 624 | ismt_detach(device_t self, int flags) |
625 | { | | 625 | { |
626 | struct ismt_softc *sc; | | 626 | struct ismt_softc *sc; |
627 | int rv = 0; | | 627 | int rv = 0; |
628 | | | 628 | |
629 | ISMT_DEBUG(self, "%s\n", __func__); | | 629 | ISMT_DEBUG(self, "%s\n", __func__); |
630 | sc = device_private(self); | | 630 | sc = device_private(self); |
631 | if (sc->smbdev != NULL) { | | 631 | if (sc->smbdev != NULL) { |
632 | rv = config_detach(sc->smbdev, flags); | | 632 | rv = config_detach(sc->smbdev, flags); |
633 | if (rv != 0) | | 633 | if (rv != 0) |
634 | return rv; | | 634 | return rv; |
635 | } | | 635 | } |
636 | if (sc->sc_ih != NULL) { | | 636 | if (sc->sc_ih != NULL) { |
637 | pci_intr_disestablish(sc->sc_pc, sc->sc_ih); | | 637 | pci_intr_disestablish(sc->sc_pc, sc->sc_ih); |
638 | sc->sc_ih = NULL; | | 638 | sc->sc_ih = NULL; |
639 | } | | 639 | } |
640 | if (sc->sc_pihp != NULL) { | | 640 | if (sc->sc_pihp != NULL) { |
641 | pci_intr_release(sc->sc_pc, sc->sc_pihp, 1); | | 641 | pci_intr_release(sc->sc_pc, sc->sc_pihp, 1); |
642 | sc->sc_pihp = NULL; | | 642 | sc->sc_pihp = NULL; |
643 | } | | 643 | } |
644 | | | 644 | |
645 | bus_dmamap_unload(sc->desc_dma_tag, sc->desc_dma_map); | | 645 | bus_dmamap_unload(sc->desc_dma_tag, sc->desc_dma_map); |
646 | bus_dmamap_unload(sc->dma_buffer_dma_tag, sc->dma_buffer_dma_map); | | 646 | bus_dmamap_unload(sc->dma_buffer_dma_tag, sc->dma_buffer_dma_map); |
647 | | | 647 | |
648 | bus_dmamem_free(sc->desc_dma_tag, &sc->desc_dma_seg, sc->desc_rseg); | | 648 | bus_dmamem_free(sc->desc_dma_tag, &sc->desc_dma_seg, sc->desc_rseg); |
649 | bus_dmamem_free(sc->dma_buffer_dma_tag, &sc->dma_buffer_dma_seg, | | 649 | bus_dmamem_free(sc->dma_buffer_dma_tag, &sc->dma_buffer_dma_seg, |
650 | sc->dma_buffer_rseg); | | 650 | sc->dma_buffer_rseg); |
651 | | | 651 | |
652 | if (sc->mmio_size) | | 652 | if (sc->mmio_size) |
653 | bus_space_unmap(sc->mmio_tag, sc->mmio_handle, sc->mmio_size); | | 653 | bus_space_unmap(sc->mmio_tag, sc->mmio_handle, sc->mmio_size); |
654 | | | 654 | |
655 | iic_tag_fini(&sc->sc_i2c_tag); | | 655 | iic_tag_fini(&sc->sc_i2c_tag); |
656 | return rv; | | 656 | return rv; |
657 | } | | 657 | } |
658 | | | 658 | |
659 | static void | | 659 | static void |
660 | ismt_attach(device_t parent, device_t self, void *aux) | | 660 | ismt_attach(device_t parent, device_t self, void *aux) |
661 | { | | 661 | { |
662 | struct ismt_softc *sc = device_private(self); | | 662 | struct ismt_softc *sc = device_private(self); |
663 | struct pci_attach_args *pa = aux; | | 663 | struct pci_attach_args *pa = aux; |
664 | const char *intrstr = NULL; | | 664 | const char *intrstr = NULL; |
665 | char intrbuf[PCI_INTRSTR_LEN]; | | 665 | char intrbuf[PCI_INTRSTR_LEN]; |
666 | pcireg_t reg; | | 666 | pcireg_t reg; |
667 | int val; | | 667 | int val; |
668 | | | 668 | |
669 | sc->pcidev = self; | | 669 | sc->pcidev = self; |
670 | sc->sc_pc = pa->pa_pc; | | 670 | sc->sc_pc = pa->pa_pc; |
671 | sc->sc_pcitag = pa->pa_tag; | | 671 | sc->sc_pcitag = pa->pa_tag; |
672 | | | 672 | |
673 | /* Enable busmastering */ | | 673 | /* Enable busmastering */ |
674 | reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG); | | 674 | reg = pci_conf_read(sc->sc_pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG); |
675 | reg |= PCI_COMMAND_MASTER_ENABLE; | | 675 | reg |= PCI_COMMAND_MASTER_ENABLE; |
676 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg); | | 676 | pci_conf_write(sc->sc_pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, reg); |
677 | | | 677 | |
678 | pci_aprint_devinfo(pa, NULL); | | 678 | pci_aprint_devinfo(pa, NULL); |
679 | | | 679 | |
680 | /* Map mem space */ | | 680 | /* Map mem space */ |
681 | if (pci_mapreg_map(pa, PCI_BAR0, PCI_MAPREG_TYPE_MEM, 0, | | 681 | if (pci_mapreg_map(pa, PCI_BAR0, PCI_MAPREG_TYPE_MEM, 0, |
682 | &sc->mmio_tag, &sc->mmio_handle, NULL, &sc->mmio_size)) { | | 682 | &sc->mmio_tag, &sc->mmio_handle, NULL, &sc->mmio_size)) { |
683 | aprint_error_dev(self, "can't map mem space\n"); | | 683 | aprint_error_dev(self, "can't map mem space\n"); |
684 | goto fail; | | 684 | goto fail; |
685 | } | | 685 | } |
686 | | | 686 | |
687 | if (pci_dma64_available(pa)) { | | 687 | if (pci_dma64_available(pa)) { |
688 | sc->desc_dma_tag = pa->pa_dmat64; | | 688 | sc->desc_dma_tag = pa->pa_dmat64; |
689 | sc->dma_buffer_dma_tag = pa->pa_dmat64; | | 689 | sc->dma_buffer_dma_tag = pa->pa_dmat64; |
690 | } else { | | 690 | } else { |
691 | sc->desc_dma_tag = pa->pa_dmat; | | 691 | sc->desc_dma_tag = pa->pa_dmat; |
692 | sc->dma_buffer_dma_tag = pa->pa_dmat; | | 692 | sc->dma_buffer_dma_tag = pa->pa_dmat; |
693 | } | | 693 | } |
694 | bus_dmamem_alloc(sc->desc_dma_tag, DESC_SIZE, PAGE_SIZE, 0, | | 694 | bus_dmamem_alloc(sc->desc_dma_tag, DESC_SIZE, PAGE_SIZE, 0, |
695 | &sc->desc_dma_seg, ISMT_DESC_ENTRIES, &sc->desc_rseg, | | 695 | &sc->desc_dma_seg, ISMT_DESC_ENTRIES, &sc->desc_rseg, |
696 | BUS_DMA_WAITOK); | | 696 | BUS_DMA_WAITOK); |
697 | bus_dmamem_alloc(sc->dma_buffer_dma_tag, DMA_BUFFER_SIZE, PAGE_SIZE, 0, | | 697 | bus_dmamem_alloc(sc->dma_buffer_dma_tag, DMA_BUFFER_SIZE, PAGE_SIZE, 0, |
698 | &sc->dma_buffer_dma_seg, 1, &sc->dma_buffer_rseg, BUS_DMA_WAITOK); | | 698 | &sc->dma_buffer_dma_seg, 1, &sc->dma_buffer_rseg, BUS_DMA_WAITOK); |
699 | | | 699 | |
700 | bus_dmamem_map(sc->desc_dma_tag, &sc->desc_dma_seg, | | 700 | bus_dmamem_map(sc->desc_dma_tag, &sc->desc_dma_seg, |
701 | sc->desc_rseg, DESC_SIZE, (void **)&sc->desc, BUS_DMA_COHERENT); | | 701 | sc->desc_rseg, DESC_SIZE, (void **)&sc->desc, BUS_DMA_COHERENT); |
702 | bus_dmamem_map(sc->dma_buffer_dma_tag, &sc->dma_buffer_dma_seg, | | 702 | bus_dmamem_map(sc->dma_buffer_dma_tag, &sc->dma_buffer_dma_seg, |
703 | sc->dma_buffer_rseg, DMA_BUFFER_SIZE, (void **)&sc->dma_buffer, | | 703 | sc->dma_buffer_rseg, DMA_BUFFER_SIZE, (void **)&sc->dma_buffer, |
704 | BUS_DMA_COHERENT); | | 704 | BUS_DMA_COHERENT); |
705 | | | 705 | |
706 | bus_dmamap_create(sc->desc_dma_tag, DESC_SIZE, 1, | | 706 | bus_dmamap_create(sc->desc_dma_tag, DESC_SIZE, 1, |
707 | DESC_SIZE, 0, 0, &sc->desc_dma_map); | | 707 | DESC_SIZE, 0, 0, &sc->desc_dma_map); |
708 | bus_dmamap_create(sc->dma_buffer_dma_tag, DMA_BUFFER_SIZE, 1, | | 708 | bus_dmamap_create(sc->dma_buffer_dma_tag, DMA_BUFFER_SIZE, 1, |
709 | DMA_BUFFER_SIZE, 0, 0, &sc->dma_buffer_dma_map); | | 709 | DMA_BUFFER_SIZE, 0, 0, &sc->dma_buffer_dma_map); |
710 | | | 710 | |
711 | bus_dmamap_load(sc->desc_dma_tag, | | 711 | bus_dmamap_load(sc->desc_dma_tag, |
712 | sc->desc_dma_map, sc->desc, DESC_SIZE, NULL, 0); | | 712 | sc->desc_dma_map, sc->desc, DESC_SIZE, NULL, 0); |
713 | bus_dmamap_load(sc->dma_buffer_dma_tag, | | 713 | bus_dmamap_load(sc->dma_buffer_dma_tag, |
714 | sc->dma_buffer_dma_map, sc->dma_buffer, DMA_BUFFER_SIZE, | | 714 | sc->dma_buffer_dma_map, sc->dma_buffer, DMA_BUFFER_SIZE, |
715 | NULL, 0); | | 715 | NULL, 0); |
716 | | | 716 | |
717 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MDBA, | | 717 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MDBA, |
718 | ISMT_LOW(sc->desc_dma_map->dm_segs[0].ds_addr)); | | 718 | ISMT_LOW(sc->desc_dma_map->dm_segs[0].ds_addr)); |
719 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MDBA + 4, | | 719 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MDBA + 4, |
720 | ISMT_HIGH(sc->desc_dma_map->dm_segs[0].ds_addr)); | | 720 | ISMT_HIGH(sc->desc_dma_map->dm_segs[0].ds_addr)); |
721 | | | 721 | |
722 | /* initialize the Master Control Register (MCTRL) */ | | 722 | /* initialize the Master Control Register (MCTRL) */ |
723 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MCTRL, | | 723 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MCTRL, |
724 | ISMT_MCTRL_MEIE); | | 724 | ISMT_MCTRL_MEIE); |
725 | | | 725 | |
726 | /* initialize the Master Status Register (MSTS) */ | | 726 | /* initialize the Master Status Register (MSTS) */ |
727 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MSTS, 0); | | 727 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MSTS, 0); |
728 | | | 728 | |
729 | /* initialize the Master Descriptor Size (MDS) */ | | 729 | /* initialize the Master Descriptor Size (MDS) */ |
730 | val = bus_space_read_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MDS); | | 730 | val = bus_space_read_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MDS); |
731 | val &= ~ISMT_MDS_MASK; | | 731 | val &= ~ISMT_MDS_MASK; |
732 | val |= (ISMT_DESC_ENTRIES - 1); | | 732 | val |= (ISMT_DESC_ENTRIES - 1); |
733 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MDS, val); | | 733 | bus_space_write_4(sc->mmio_tag, sc->mmio_handle, ISMT_MSTR_MDS, val); |
734 | | | 734 | |
735 | if (pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0)) { | | 735 | if (pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0)) { |
736 | aprint_error_dev(self, "couldn't map interrupt\n"); | | 736 | aprint_error_dev(self, "couldn't map interrupt\n"); |
737 | return; | | 737 | return; |
738 | } | | 738 | } |
739 | intrstr = pci_intr_string(pa->pa_pc, sc->sc_pihp[0], intrbuf, | | 739 | intrstr = pci_intr_string(pa->pa_pc, sc->sc_pihp[0], intrbuf, |
740 | sizeof(intrbuf)); | | 740 | sizeof(intrbuf)); |
741 | sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, sc->sc_pihp[0], | | 741 | sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, sc->sc_pihp[0], |
742 | IPL_BIO, ismt_intr, sc, device_xname(self)); | | 742 | IPL_BIO, ismt_intr, sc, device_xname(self)); |
743 | if (sc->sc_ih == NULL) { | | 743 | if (sc->sc_ih == NULL) { |
744 | aprint_error_dev(sc->pcidev, "unable to establish %s\n", | | 744 | aprint_error_dev(sc->pcidev, "unable to establish %s\n", |
745 | (pci_intr_type(pa->pa_pc, sc->sc_pihp[0]) | | 745 | (pci_intr_type(pa->pa_pc, sc->sc_pihp[0]) |
746 | == PCI_INTR_TYPE_MSI) ? "MSI" : "INTx"); | | 746 | == PCI_INTR_TYPE_MSI) ? "MSI" : "INTx"); |
747 | /* Polling */ | | 747 | /* Polling */ |
748 | } | | 748 | } |
749 | | | 749 | |
750 | if (pci_intr_type(pa->pa_pc, sc->sc_pihp[0]) == PCI_INTR_TYPE_MSI) | | 750 | if (pci_intr_type(pa->pa_pc, sc->sc_pihp[0]) == PCI_INTR_TYPE_MSI) |
751 | sc->using_msi = 1; | | 751 | sc->using_msi = 1; |
752 | | | 752 | |
753 | aprint_normal_dev(sc->pcidev, "interrupting at %s\n", intrstr); | | 753 | aprint_normal_dev(sc->pcidev, "interrupting at %s\n", intrstr); |
754 | | | 754 | |
755 | sc->smbdev = NULL; | | 755 | sc->smbdev = NULL; |
756 | if (!pmf_device_register(self, NULL, NULL)) | | 756 | if (!pmf_device_register(self, NULL, NULL)) |
757 | aprint_error_dev(self, "couldn't establish power handler\n"); | | 757 | aprint_error_dev(self, "couldn't establish power handler\n"); |
758 | | | 758 | |
759 | config_interrupts(self, ismt_config_interrupts); | | 759 | config_interrupts(self, ismt_config_interrupts); |
760 | return; | | 760 | return; |
761 | | | 761 | |
762 | fail: | | 762 | fail: |
763 | ismt_detach(sc->pcidev, 0); | | 763 | ismt_detach(sc->pcidev, 0); |
764 | | | 764 | |
765 | return; | | 765 | return; |
766 | } | | 766 | } |
767 | | | 767 | |
768 | static int | | 768 | static int |
769 | ismt_match(device_t parent, cfdata_t match, void *aux) | | 769 | ismt_match(device_t parent, cfdata_t match, void *aux) |
770 | { | | 770 | { |
771 | struct pci_attach_args *pa = aux; | | 771 | struct pci_attach_args *pa = aux; |
772 | | | 772 | |
773 | if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL) | | 773 | if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_INTEL) |
774 | return 0; | | 774 | return 0; |
775 | | | 775 | |
776 | switch (PCI_PRODUCT(pa->pa_id)) { | | 776 | switch (PCI_PRODUCT(pa->pa_id)) { |
777 | case PCI_PRODUCT_INTEL_S1200_SMBUS_0: | | 777 | case PCI_PRODUCT_INTEL_S1200_SMBUS_0: |
778 | case PCI_PRODUCT_INTEL_S1200_SMBUS_1: | | 778 | case PCI_PRODUCT_INTEL_S1200_SMBUS_1: |
779 | case PCI_PRODUCT_INTEL_C2000_SMBUS: | | 779 | case PCI_PRODUCT_INTEL_C2000_SMBUS: |
780 | case PCI_PRODUCT_INTEL_C3K_SMBUS: | | 780 | case PCI_PRODUCT_INTEL_C3K_SMBUS: |
781 | break; | | 781 | break; |
782 | default: | | 782 | default: |
783 | return 0; | | 783 | return 0; |
784 | } | | 784 | } |
785 | | | 785 | |
786 | return 1; | | 786 | return 1; |
787 | } | | 787 | } |
788 | | | 788 | |
789 | static int | | 789 | static int |
790 | ismt_rescan(device_t self, const char *ifattr, const int *locators) | | 790 | ismt_rescan(device_t self, const char *ifattr, const int *locators) |
791 | { | | 791 | { |
792 | struct ismt_softc *sc = device_private(self); | | 792 | struct ismt_softc *sc = device_private(self); |
793 | struct i2cbus_attach_args iba; | | 793 | struct i2cbus_attach_args iba; |
794 | | | 794 | |
795 | if (sc->smbdev != NULL) | | 795 | if (sc->smbdev != NULL) |
796 | return 0; | | 796 | return 0; |
797 | | | 797 | |
798 | /* Attach I2C bus */ | | 798 | /* Attach I2C bus */ |
799 | iic_tag_init(&sc->sc_i2c_tag); | | 799 | iic_tag_init(&sc->sc_i2c_tag); |
800 | sc->sc_i2c_tag.ic_cookie = sc; | | 800 | sc->sc_i2c_tag.ic_cookie = sc; |
801 | sc->sc_i2c_tag.ic_exec = ismt_i2c_exec; | | 801 | sc->sc_i2c_tag.ic_exec = ismt_i2c_exec; |
802 | | | 802 | |
803 | memset(&iba, 0, sizeof(iba)); | | 803 | memset(&iba, 0, sizeof(iba)); |
804 | iba.iba_tag = &sc->sc_i2c_tag; | | 804 | iba.iba_tag = &sc->sc_i2c_tag; |
805 | sc->smbdev = config_found(self, &iba, iicbus_print, CFARG_EOL); | | 805 | sc->smbdev = config_found(self, &iba, iicbus_print, CFARG_EOL); |
806 | | | 806 | |
807 | return 0; | | 807 | return 0; |
808 | } | | 808 | } |
809 | | | 809 | |
810 | static void | | 810 | static void |
811 | ismt_config_interrupts(device_t self) | | 811 | ismt_config_interrupts(device_t self) |
812 | { | | 812 | { |
813 | int flags = 0; | | | |
814 | | | 813 | |
815 | ismt_rescan(self, NULL, NULL); | | 814 | ismt_rescan(self, NULL, NULL); |
816 | } | | 815 | } |
817 | | | 816 | |
818 | static void | | 817 | static void |
819 | ismt_chdet(device_t self, device_t child) | | 818 | ismt_chdet(device_t self, device_t child) |
820 | { | | 819 | { |
821 | struct ismt_softc *sc = device_private(self); | | 820 | struct ismt_softc *sc = device_private(self); |
822 | | | 821 | |
823 | if (sc->smbdev == child) | | 822 | if (sc->smbdev == child) |
824 | sc->smbdev = NULL; | | 823 | sc->smbdev = NULL; |
825 | | | 824 | |
826 | } | | 825 | } |
827 | | | 826 | |
828 | MODULE(MODULE_CLASS_DRIVER, ismt, "pci"); | | 827 | MODULE(MODULE_CLASS_DRIVER, ismt, "pci"); |
829 | | | 828 | |
830 | #ifdef _MODULE | | 829 | #ifdef _MODULE |
831 | #include "ioconf.c" | | 830 | #include "ioconf.c" |
832 | #endif | | 831 | #endif |
833 | | | 832 | |
834 | static int | | 833 | static int |
835 | ismt_modcmd(modcmd_t cmd, void *opaque) | | 834 | ismt_modcmd(modcmd_t cmd, void *opaque) |
836 | { | | 835 | { |
837 | int error = 0; | | 836 | int error = 0; |
838 | | | 837 | |
839 | switch (cmd) { | | 838 | switch (cmd) { |
840 | case MODULE_CMD_INIT: | | 839 | case MODULE_CMD_INIT: |
841 | #ifdef _MODULE | | 840 | #ifdef _MODULE |
842 | error = config_init_component(cfdriver_ioconf_ismt, | | 841 | error = config_init_component(cfdriver_ioconf_ismt, |
843 | cfattach_ioconf_ismt, cfdata_ioconf_ismt); | | 842 | cfattach_ioconf_ismt, cfdata_ioconf_ismt); |
844 | #endif | | 843 | #endif |
845 | return error; | | 844 | return error; |
846 | case MODULE_CMD_FINI: | | 845 | case MODULE_CMD_FINI: |
847 | #ifdef _MODULE | | 846 | #ifdef _MODULE |
848 | error = config_fini_component(cfdriver_ioconf_ismt, | | 847 | error = config_fini_component(cfdriver_ioconf_ismt, |
849 | cfattach_ioconf_ismt, cfdata_ioconf_ismt); | | 848 | cfattach_ioconf_ismt, cfdata_ioconf_ismt); |
850 | #endif | | 849 | #endif |
851 | return error; | | 850 | return error; |
852 | default: | | 851 | default: |
853 | return ENOTTY; | | 852 | return ENOTTY; |
854 | } | | 853 | } |
855 | } | | 854 | } |