2 * Intel MIC Platform Software Stack (MPSS)
4 * Copyright(c) 2013 Intel Corporation.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
18 * Intel MIC Host driver.
22 #include <linux/pci.h>
24 #include "../common/mic_device.h"
25 #include "mic_device.h"
30 * mic_x100_write_spad - write to the scratchpad register
31 * @mdev: pointer to mic_device instance
32 * @idx: index to the scratchpad register, 0 based
33 * @val: the data value to put into the register
35 * This function allows writing of a 32bit value to the indexed scratchpad
41 mic_x100_write_spad(struct mic_device
*mdev
, unsigned int idx
, u32 val
)
43 dev_dbg(mdev
->sdev
->parent
, "Writing 0x%x to scratch pad index %d\n",
45 mic_mmio_write(&mdev
->mmio
, val
,
46 MIC_X100_SBOX_BASE_ADDRESS
+
47 MIC_X100_SBOX_SPAD0
+ idx
* 4);
51 * mic_x100_read_spad - read from the scratchpad register
52 * @mdev: pointer to mic_device instance
53 * @idx: index to scratchpad register, 0 based
55 * This function allows reading of the 32bit scratchpad register.
57 * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
60 mic_x100_read_spad(struct mic_device
*mdev
, unsigned int idx
)
62 u32 val
= mic_mmio_read(&mdev
->mmio
,
63 MIC_X100_SBOX_BASE_ADDRESS
+
64 MIC_X100_SBOX_SPAD0
+ idx
* 4);
66 dev_dbg(mdev
->sdev
->parent
,
67 "Reading 0x%x from scratch pad index %d\n", val
, idx
);
72 * mic_x100_enable_interrupts - Enable interrupts.
73 * @mdev: pointer to mic_device instance
75 static void mic_x100_enable_interrupts(struct mic_device
*mdev
)
78 struct mic_mw
*mw
= &mdev
->mmio
;
79 u32 sice0
= MIC_X100_SBOX_BASE_ADDRESS
+ MIC_X100_SBOX_SICE0
;
80 u32 siac0
= MIC_X100_SBOX_BASE_ADDRESS
+ MIC_X100_SBOX_SIAC0
;
82 reg
= mic_mmio_read(mw
, sice0
);
83 reg
|= MIC_X100_SBOX_DBR_BITS(0xf) | MIC_X100_SBOX_DMA_BITS(0xff);
84 mic_mmio_write(mw
, reg
, sice0
);
87 * Enable auto-clear when enabling interrupts. Applicable only for
88 * MSI-x. Legacy and MSI mode cannot have auto-clear enabled.
90 if (mdev
->irq_info
.num_vectors
> 1) {
91 reg
= mic_mmio_read(mw
, siac0
);
92 reg
|= MIC_X100_SBOX_DBR_BITS(0xf) |
93 MIC_X100_SBOX_DMA_BITS(0xff);
94 mic_mmio_write(mw
, reg
, siac0
);
99 * mic_x100_disable_interrupts - Disable interrupts.
100 * @mdev: pointer to mic_device instance
102 static void mic_x100_disable_interrupts(struct mic_device
*mdev
)
105 struct mic_mw
*mw
= &mdev
->mmio
;
106 u32 sice0
= MIC_X100_SBOX_BASE_ADDRESS
+ MIC_X100_SBOX_SICE0
;
107 u32 siac0
= MIC_X100_SBOX_BASE_ADDRESS
+ MIC_X100_SBOX_SIAC0
;
108 u32 sicc0
= MIC_X100_SBOX_BASE_ADDRESS
+ MIC_X100_SBOX_SICC0
;
110 reg
= mic_mmio_read(mw
, sice0
);
111 mic_mmio_write(mw
, reg
, sicc0
);
113 if (mdev
->irq_info
.num_vectors
> 1) {
114 reg
= mic_mmio_read(mw
, siac0
);
115 reg
&= ~(MIC_X100_SBOX_DBR_BITS(0xf) |
116 MIC_X100_SBOX_DMA_BITS(0xff));
117 mic_mmio_write(mw
, reg
, siac0
);
122 * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC.
123 * @mdev: pointer to mic_device instance
125 static void mic_x100_send_sbox_intr(struct mic_device
*mdev
,
128 struct mic_mw
*mw
= &mdev
->mmio
;
129 u64 apic_icr_offset
= MIC_X100_SBOX_APICICR0
+ doorbell
* 8;
130 u32 apicicr_low
= mic_mmio_read(mw
,
131 MIC_X100_SBOX_BASE_ADDRESS
+ apic_icr_offset
);
133 /* for MIC we need to make sure we "hit" the send_icr bit (13) */
134 apicicr_low
= (apicicr_low
| (1 << 13));
136 /* Ensure that the interrupt is ordered w.r.t. previous stores. */
138 mic_mmio_write(mw
, apicicr_low
,
139 MIC_X100_SBOX_BASE_ADDRESS
+ apic_icr_offset
);
143 * mic_x100_send_rdmasr_intr - Send an RDMASR interrupt to MIC.
144 * @mdev: pointer to mic_device instance
146 static void mic_x100_send_rdmasr_intr(struct mic_device
*mdev
,
149 int rdmasr_offset
= MIC_X100_SBOX_RDMASR0
+ (doorbell
<< 2);
150 /* Ensure that the interrupt is ordered w.r.t. previous stores. */
152 mic_mmio_write(&mdev
->mmio
, 0,
153 MIC_X100_SBOX_BASE_ADDRESS
+ rdmasr_offset
);
157 * __mic_x100_send_intr - Send interrupt to MIC.
158 * @mdev: pointer to mic_device instance
159 * @doorbell: doorbell number.
161 static void mic_x100_send_intr(struct mic_device
*mdev
, int doorbell
)
164 if (doorbell
< MIC_X100_NUM_SBOX_IRQ
) {
165 mic_x100_send_sbox_intr(mdev
, doorbell
);
167 rdmasr_db
= doorbell
- MIC_X100_NUM_SBOX_IRQ
+
168 MIC_X100_RDMASR_IRQ_BASE
;
169 mic_x100_send_rdmasr_intr(mdev
, rdmasr_db
);
174 * mic_ack_interrupt - Device specific interrupt handling.
175 * @mdev: pointer to mic_device instance
177 * Returns: bitmask of doorbell events triggered.
179 static u32
mic_x100_ack_interrupt(struct mic_device
*mdev
)
182 struct mic_mw
*mw
= &mdev
->mmio
;
183 u32 sicr0
= MIC_X100_SBOX_BASE_ADDRESS
+ MIC_X100_SBOX_SICR0
;
185 /* Clear pending bit array. */
186 if (MIC_A0_STEP
== mdev
->stepping
)
187 mic_mmio_write(mw
, 1, MIC_X100_SBOX_BASE_ADDRESS
+
188 MIC_X100_SBOX_MSIXPBACR
);
190 if (mdev
->irq_info
.num_vectors
<= 1) {
191 reg
= mic_mmio_read(mw
, sicr0
);
196 mic_mmio_write(mw
, reg
, sicr0
);
199 if (mdev
->stepping
>= MIC_B0_STEP
)
200 mdev
->intr_ops
->enable_interrupts(mdev
);
206 * mic_x100_hw_intr_init - Initialize h/w specific interrupt
208 * @mdev: pointer to mic_device instance
210 static void mic_x100_hw_intr_init(struct mic_device
*mdev
)
212 mdev
->intr_info
= (struct mic_intr_info
*) mic_x100_intr_init
;
216 * mic_x100_read_msi_to_src_map - read from the MSI mapping registers
217 * @mdev: pointer to mic_device instance
218 * @idx: index to the mapping register, 0 based
220 * This function allows reading of the 32bit MSI mapping register.
222 * RETURNS: The value in the register.
225 mic_x100_read_msi_to_src_map(struct mic_device
*mdev
, int idx
)
227 return mic_mmio_read(&mdev
->mmio
,
228 MIC_X100_SBOX_BASE_ADDRESS
+
229 MIC_X100_SBOX_MXAR0
+ idx
* 4);
233 * mic_x100_program_msi_to_src_map - program the MSI mapping registers
234 * @mdev: pointer to mic_device instance
235 * @idx: index to the mapping register, 0 based
236 * @offset: The bit offset in the register that needs to be updated.
237 * @set: boolean specifying if the bit in the specified offset needs
238 * to be set or cleared.
243 mic_x100_program_msi_to_src_map(struct mic_device
*mdev
,
244 int idx
, int offset
, bool set
)
247 struct mic_mw
*mw
= &mdev
->mmio
;
248 u32 mxar
= MIC_X100_SBOX_BASE_ADDRESS
+
249 MIC_X100_SBOX_MXAR0
+ idx
* 4;
251 reg
= mic_mmio_read(mw
, mxar
);
253 __set_bit(offset
, ®
);
255 __clear_bit(offset
, ®
);
256 mic_mmio_write(mw
, reg
, mxar
);
260 * mic_x100_smpt_set - Update an SMPT entry with a DMA address.
261 * @mdev: pointer to mic_device instance
266 mic_x100_smpt_set(struct mic_device
*mdev
, dma_addr_t dma_addr
, u8 index
)
268 #define SNOOP_ON (0 << 0)
269 #define SNOOP_OFF (1 << 0)
271 * Sbox Smpt Reg Bits:
272 * Bits 31:2 Host address
276 #define BUILD_SMPT(NO_SNOOP, HOST_ADDR) \
277 (u32)(((HOST_ADDR) << 2) | ((NO_SNOOP) & 0x01))
279 uint32_t smpt_reg_val
= BUILD_SMPT(SNOOP_ON
,
280 dma_addr
>> mdev
->smpt
->info
.page_shift
);
281 mic_mmio_write(&mdev
->mmio
, smpt_reg_val
,
282 MIC_X100_SBOX_BASE_ADDRESS
+
283 MIC_X100_SBOX_SMPT00
+ (4 * index
));
287 * mic_x100_smpt_hw_init - Initialize SMPT X100 specific fields.
288 * @mdev: pointer to mic_device instance
292 static void mic_x100_smpt_hw_init(struct mic_device
*mdev
)
294 struct mic_smpt_hw_info
*info
= &mdev
->smpt
->info
;
297 info
->page_shift
= 34;
298 info
->page_size
= (1ULL << info
->page_shift
);
299 info
->base
= 0x8000000000ULL
;
302 struct mic_smpt_ops mic_x100_smpt_ops
= {
303 .init
= mic_x100_smpt_hw_init
,
304 .set
= mic_x100_smpt_set
,
307 struct mic_hw_ops mic_x100_ops
= {
308 .aper_bar
= MIC_X100_APER_BAR
,
309 .mmio_bar
= MIC_X100_MMIO_BAR
,
310 .read_spad
= mic_x100_read_spad
,
311 .write_spad
= mic_x100_write_spad
,
312 .send_intr
= mic_x100_send_intr
,
313 .ack_interrupt
= mic_x100_ack_interrupt
,
316 struct mic_hw_intr_ops mic_x100_intr_ops
= {
317 .intr_init
= mic_x100_hw_intr_init
,
318 .enable_interrupts
= mic_x100_enable_interrupts
,
319 .disable_interrupts
= mic_x100_disable_interrupts
,
320 .program_msi_to_src_map
= mic_x100_program_msi_to_src_map
,
321 .read_msi_to_src_map
= mic_x100_read_msi_to_src_map
,