1 /*
2   This file is provided under a dual BSD/GPLv2 license.  When using or
3   redistributing this file, you may do so under either license.
4 
5   GPL LICENSE SUMMARY
6   Copyright(c) 2014 Intel Corporation.
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of version 2 of the GNU General Public License as
9   published by the Free Software Foundation.
10 
11   This program is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   General Public License for more details.
15 
16   Contact Information:
17   qat-linux@intel.com
18 
19   BSD LICENSE
20   Copyright(c) 2014 Intel Corporation.
21   Redistribution and use in source and binary forms, with or without
22   modification, are permitted provided that the following conditions
23   are met:
24 
25     * Redistributions of source code must retain the above copyright
26       notice, this list of conditions and the following disclaimer.
27     * Redistributions in binary form must reproduce the above copyright
28       notice, this list of conditions and the following disclaimer in
29       the documentation and/or other materials provided with the
30       distribution.
31     * Neither the name of Intel Corporation nor the names of its
32       contributors may be used to endorse or promote products derived
33       from this software without specific prior written permission.
34 
35   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 */
47 #include <adf_accel_devices.h>
48 #include "adf_dh895xcc_hw_data.h"
49 #include "adf_common_drv.h"
50 #include "adf_drv.h"
51 
52 /* Worker thread to service arbiter mappings based on dev SKUs */
53 static const uint32_t thrd_to_arb_map_sku4[] = {
54 	0x12222AAA, 0x11666666, 0x12222AAA, 0x11666666,
55 	0x12222AAA, 0x11222222, 0x12222AAA, 0x11222222,
56 	0x00000000, 0x00000000, 0x00000000, 0x00000000
57 };
58 
59 static const uint32_t thrd_to_arb_map_sku6[] = {
60 	0x12222AAA, 0x11666666, 0x12222AAA, 0x11666666,
61 	0x12222AAA, 0x11222222, 0x12222AAA, 0x11222222,
62 	0x12222AAA, 0x11222222, 0x12222AAA, 0x11222222
63 };
64 
65 static struct adf_hw_device_class dh895xcc_class = {
66 	.name = ADF_DH895XCC_DEVICE_NAME,
67 	.type = DEV_DH895XCC,
68 	.instances = 0
69 };
70 
get_accel_mask(uint32_t fuse)71 static uint32_t get_accel_mask(uint32_t fuse)
72 {
73 	return (~fuse) >> ADF_DH895XCC_ACCELERATORS_REG_OFFSET &
74 			  ADF_DH895XCC_ACCELERATORS_MASK;
75 }
76 
get_ae_mask(uint32_t fuse)77 static uint32_t get_ae_mask(uint32_t fuse)
78 {
79 	return (~fuse) & ADF_DH895XCC_ACCELENGINES_MASK;
80 }
81 
get_num_accels(struct adf_hw_device_data * self)82 static uint32_t get_num_accels(struct adf_hw_device_data *self)
83 {
84 	uint32_t i, ctr = 0;
85 
86 	if (!self || !self->accel_mask)
87 		return 0;
88 
89 	for (i = 0; i < ADF_DH895XCC_MAX_ACCELERATORS; i++) {
90 		if (self->accel_mask & (1 << i))
91 			ctr++;
92 	}
93 	return ctr;
94 }
95 
get_num_aes(struct adf_hw_device_data * self)96 static uint32_t get_num_aes(struct adf_hw_device_data *self)
97 {
98 	uint32_t i, ctr = 0;
99 
100 	if (!self || !self->ae_mask)
101 		return 0;
102 
103 	for (i = 0; i < ADF_DH895XCC_MAX_ACCELENGINES; i++) {
104 		if (self->ae_mask & (1 << i))
105 			ctr++;
106 	}
107 	return ctr;
108 }
109 
get_misc_bar_id(struct adf_hw_device_data * self)110 static uint32_t get_misc_bar_id(struct adf_hw_device_data *self)
111 {
112 	return ADF_DH895XCC_PMISC_BAR;
113 }
114 
get_etr_bar_id(struct adf_hw_device_data * self)115 static uint32_t get_etr_bar_id(struct adf_hw_device_data *self)
116 {
117 	return ADF_DH895XCC_ETR_BAR;
118 }
119 
get_sku(struct adf_hw_device_data * self)120 static enum dev_sku_info get_sku(struct adf_hw_device_data *self)
121 {
122 	int sku = (self->fuses & ADF_DH895XCC_FUSECTL_SKU_MASK)
123 	    >> ADF_DH895XCC_FUSECTL_SKU_SHIFT;
124 
125 	switch (sku) {
126 	case ADF_DH895XCC_FUSECTL_SKU_1:
127 		return DEV_SKU_1;
128 	case ADF_DH895XCC_FUSECTL_SKU_2:
129 		return DEV_SKU_2;
130 	case ADF_DH895XCC_FUSECTL_SKU_3:
131 		return DEV_SKU_3;
132 	case ADF_DH895XCC_FUSECTL_SKU_4:
133 		return DEV_SKU_4;
134 	default:
135 		return DEV_SKU_UNKNOWN;
136 	}
137 	return DEV_SKU_UNKNOWN;
138 }
139 
adf_get_arbiter_mapping(struct adf_accel_dev * accel_dev,uint32_t const ** arb_map_config)140 void adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev,
141 			     uint32_t const **arb_map_config)
142 {
143 	switch (accel_dev->accel_pci_dev.sku) {
144 	case DEV_SKU_1:
145 		*arb_map_config = thrd_to_arb_map_sku4;
146 		break;
147 
148 	case DEV_SKU_2:
149 	case DEV_SKU_4:
150 		*arb_map_config = thrd_to_arb_map_sku6;
151 		break;
152 	default:
153 		dev_err(&GET_DEV(accel_dev),
154 			"The configuration doesn't match any SKU");
155 		*arb_map_config = NULL;
156 	}
157 }
158 
adf_enable_error_correction(struct adf_accel_dev * accel_dev)159 static void adf_enable_error_correction(struct adf_accel_dev *accel_dev)
160 {
161 	struct adf_hw_device_data *hw_device = accel_dev->hw_device;
162 	struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR];
163 	void __iomem *csr = misc_bar->virt_addr;
164 	unsigned int val, i;
165 
166 	/* Enable Accel Engine error detection & correction */
167 	for (i = 0; i < hw_device->get_num_aes(hw_device); i++) {
168 		val = ADF_CSR_RD(csr, ADF_DH895XCC_AE_CTX_ENABLES(i));
169 		val |= ADF_DH895XCC_ENABLE_AE_ECC_ERR;
170 		ADF_CSR_WR(csr, ADF_DH895XCC_AE_CTX_ENABLES(i), val);
171 		val = ADF_CSR_RD(csr, ADF_DH895XCC_AE_MISC_CONTROL(i));
172 		val |= ADF_DH895XCC_ENABLE_AE_ECC_PARITY_CORR;
173 		ADF_CSR_WR(csr, ADF_DH895XCC_AE_MISC_CONTROL(i), val);
174 	}
175 
176 	/* Enable shared memory error detection & correction */
177 	for (i = 0; i < hw_device->get_num_accels(hw_device); i++) {
178 		val = ADF_CSR_RD(csr, ADF_DH895XCC_UERRSSMSH(i));
179 		val |= ADF_DH895XCC_ERRSSMSH_EN;
180 		ADF_CSR_WR(csr, ADF_DH895XCC_UERRSSMSH(i), val);
181 		val = ADF_CSR_RD(csr, ADF_DH895XCC_CERRSSMSH(i));
182 		val |= ADF_DH895XCC_ERRSSMSH_EN;
183 		ADF_CSR_WR(csr, ADF_DH895XCC_CERRSSMSH(i), val);
184 	}
185 }
186 
adf_enable_ints(struct adf_accel_dev * accel_dev)187 static void adf_enable_ints(struct adf_accel_dev *accel_dev)
188 {
189 	void __iomem *addr;
190 
191 	addr = (&GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR])->virt_addr;
192 
193 	/* Enable bundle and misc interrupts */
194 	ADF_CSR_WR(addr, ADF_DH895XCC_SMIAPF0_MASK_OFFSET,
195 		   ADF_DH895XCC_SMIA0_MASK);
196 	ADF_CSR_WR(addr, ADF_DH895XCC_SMIAPF1_MASK_OFFSET,
197 		   ADF_DH895XCC_SMIA1_MASK);
198 }
199 
adf_init_hw_data_dh895xcc(struct adf_hw_device_data * hw_data)200 void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
201 {
202 	hw_data->dev_class = &dh895xcc_class;
203 	hw_data->instance_id = dh895xcc_class.instances++;
204 	hw_data->num_banks = ADF_DH895XCC_ETR_MAX_BANKS;
205 	hw_data->num_accel = ADF_DH895XCC_MAX_ACCELERATORS;
206 	hw_data->pci_dev_id = ADF_DH895XCC_PCI_DEVICE_ID;
207 	hw_data->num_logical_accel = 1;
208 	hw_data->num_engines = ADF_DH895XCC_MAX_ACCELENGINES;
209 	hw_data->tx_rx_gap = ADF_DH895XCC_RX_RINGS_OFFSET;
210 	hw_data->tx_rings_mask = ADF_DH895XCC_TX_RINGS_MASK;
211 	hw_data->alloc_irq = adf_isr_resource_alloc;
212 	hw_data->free_irq = adf_isr_resource_free;
213 	hw_data->enable_error_correction = adf_enable_error_correction;
214 	hw_data->hw_arb_ring_enable = adf_update_ring_arb_enable;
215 	hw_data->hw_arb_ring_disable = adf_update_ring_arb_enable;
216 	hw_data->get_accel_mask = get_accel_mask;
217 	hw_data->get_ae_mask = get_ae_mask;
218 	hw_data->get_num_accels = get_num_accels;
219 	hw_data->get_num_aes = get_num_aes;
220 	hw_data->get_etr_bar_id = get_etr_bar_id;
221 	hw_data->get_misc_bar_id = get_misc_bar_id;
222 	hw_data->get_sku = get_sku;
223 	hw_data->fw_name = ADF_DH895XCC_FW;
224 	hw_data->init_admin_comms = adf_init_admin_comms;
225 	hw_data->exit_admin_comms = adf_exit_admin_comms;
226 	hw_data->init_arb = adf_init_arb;
227 	hw_data->exit_arb = adf_exit_arb;
228 	hw_data->enable_ints = adf_enable_ints;
229 }
230 
adf_clean_hw_data_dh895xcc(struct adf_hw_device_data * hw_data)231 void adf_clean_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
232 {
233 	hw_data->dev_class->instances--;
234 }
235