1/* SPDX-License-Identifier: BSD-3-Clause */
2/* Copyright(c) 2007-2022 Intel Corporation */
3#include "qat_freebsd.h"
4#include "adf_cfg.h"
5#include <adf_accel_devices.h>
6#include <adf_pfvf_msg.h>
7#include <adf_common_drv.h>
8#include <adf_dev_err.h>
9#include <adf_gen2_hw_data.h>
10#include <adf_gen2_pfvf.h>
11#include "adf_dh895xcc_hw_data.h"
12#include "icp_qat_hw.h"
13#include "adf_heartbeat.h"
14
15/* Worker thread to service arbiter mappings based on dev SKUs */
16static const u32 thrd_to_arb_map_sku4[] =
17    { 0x12222AAA, 0x11666666, 0x12222AAA, 0x11666666, 0x12222AAA, 0x11222222,
18      0x12222AAA, 0x11222222, 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
19
20static const u32 thrd_to_arb_map_sku6[] =
21    { 0x12222AAA, 0x11666666, 0x12222AAA, 0x11666666, 0x12222AAA, 0x11222222,
22      0x12222AAA, 0x11222222, 0x12222AAA, 0x11222222, 0x12222AAA, 0x11222222 };
23
24static const u32 thrd_to_arb_map_sku3[] =
25    { 0x00000888, 0x00000000, 0x00000888, 0x00000000, 0x00000888, 0x00000000,
26      0x00000888, 0x00000000, 0x00000888, 0x00000000, 0x00000888, 0x00000000 };
27
28static u32 thrd_to_arb_map_gen[ADF_DH895XCC_MAX_ACCELENGINES] = { 0 };
29
30static struct adf_hw_device_class dh895xcc_class =
31    {.name = ADF_DH895XCC_DEVICE_NAME, .type = DEV_DH895XCC, .instances = 0 };
32
33static u32
34get_accel_mask(struct adf_accel_dev *accel_dev)
35{
36	device_t pdev = accel_dev->accel_pci_dev.pci_dev;
37	u32 fuse;
38
39	fuse = pci_read_config(pdev, ADF_DEVICE_FUSECTL_OFFSET, 4);
40
41	return (~fuse) >> ADF_DH895XCC_ACCELERATORS_REG_OFFSET &
42	    ADF_DH895XCC_ACCELERATORS_MASK;
43}
44
45static u32
46get_ae_mask(struct adf_accel_dev *accel_dev)
47{
48	device_t pdev = accel_dev->accel_pci_dev.pci_dev;
49	u32 fuse;
50
51	fuse = pci_read_config(pdev, ADF_DEVICE_FUSECTL_OFFSET, 4);
52
53	return (~fuse) & ADF_DH895XCC_ACCELENGINES_MASK;
54}
55
56static uint32_t
57get_num_accels(struct adf_hw_device_data *self)
58{
59	uint32_t i, ctr = 0;
60
61	if (!self || !self->accel_mask)
62		return 0;
63
64	for (i = 0; i < ADF_DH895XCC_MAX_ACCELERATORS; i++) {
65		if (self->accel_mask & (1 << i))
66			ctr++;
67	}
68	return ctr;
69}
70
71static uint32_t
72get_num_aes(struct adf_hw_device_data *self)
73{
74	uint32_t i, ctr = 0;
75
76	if (!self || !self->ae_mask)
77		return 0;
78
79	for (i = 0; i < ADF_DH895XCC_MAX_ACCELENGINES; i++) {
80		if (self->ae_mask & (1 << i))
81			ctr++;
82	}
83	return ctr;
84}
85
86static uint32_t
87get_misc_bar_id(struct adf_hw_device_data *self)
88{
89	return ADF_DH895XCC_PMISC_BAR;
90}
91
92static uint32_t
93get_etr_bar_id(struct adf_hw_device_data *self)
94{
95	return ADF_DH895XCC_ETR_BAR;
96}
97
98static uint32_t
99get_sram_bar_id(struct adf_hw_device_data *self)
100{
101	return ADF_DH895XCC_SRAM_BAR;
102}
103
104static enum dev_sku_info
105get_sku(struct adf_hw_device_data *self)
106{
107	int sku = (self->fuses & ADF_DH895XCC_FUSECTL_SKU_MASK) >>
108	    ADF_DH895XCC_FUSECTL_SKU_SHIFT;
109
110	switch (sku) {
111	case ADF_DH895XCC_FUSECTL_SKU_1:
112		return DEV_SKU_1;
113	case ADF_DH895XCC_FUSECTL_SKU_2:
114		return DEV_SKU_2;
115	case ADF_DH895XCC_FUSECTL_SKU_3:
116		return DEV_SKU_3;
117	case ADF_DH895XCC_FUSECTL_SKU_4:
118		return DEV_SKU_4;
119	default:
120		return DEV_SKU_UNKNOWN;
121	}
122	return DEV_SKU_UNKNOWN;
123}
124
125static void
126adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev,
127			u32 const **arb_map_config)
128{
129	switch (accel_dev->accel_pci_dev.sku) {
130	case DEV_SKU_1:
131		adf_cfg_gen_dispatch_arbiter(accel_dev,
132					     thrd_to_arb_map_sku4,
133					     thrd_to_arb_map_gen,
134					     ADF_DH895XCC_MAX_ACCELENGINES);
135		*arb_map_config = thrd_to_arb_map_gen;
136		break;
137
138	case DEV_SKU_2:
139	case DEV_SKU_4:
140		adf_cfg_gen_dispatch_arbiter(accel_dev,
141					     thrd_to_arb_map_sku6,
142					     thrd_to_arb_map_gen,
143					     ADF_DH895XCC_MAX_ACCELENGINES);
144		*arb_map_config = thrd_to_arb_map_gen;
145		break;
146
147	case DEV_SKU_3:
148		adf_cfg_gen_dispatch_arbiter(accel_dev,
149					     thrd_to_arb_map_sku3,
150					     thrd_to_arb_map_gen,
151					     ADF_DH895XCC_MAX_ACCELENGINES);
152		*arb_map_config = thrd_to_arb_map_gen;
153		break;
154
155	default:
156		device_printf(GET_DEV(accel_dev),
157			      "The configuration doesn't match any SKU");
158		*arb_map_config = NULL;
159	}
160}
161
162static void
163get_arb_info(struct arb_info *arb_csrs_info)
164{
165	arb_csrs_info->arbiter_offset = ADF_DH895XCC_ARB_OFFSET;
166	arb_csrs_info->wrk_thd_2_srv_arb_map =
167	    ADF_DH895XCC_ARB_WRK_2_SER_MAP_OFFSET;
168	arb_csrs_info->wrk_cfg_offset = ADF_DH895XCC_ARB_WQCFG_OFFSET;
169}
170
171static void
172get_admin_info(struct admin_info *admin_csrs_info)
173{
174	admin_csrs_info->mailbox_offset = ADF_DH895XCC_MAILBOX_BASE_OFFSET;
175	admin_csrs_info->admin_msg_ur = ADF_DH895XCC_ADMINMSGUR_OFFSET;
176	admin_csrs_info->admin_msg_lr = ADF_DH895XCC_ADMINMSGLR_OFFSET;
177}
178
179static void
180get_errsou_offset(u32 *errsou3, u32 *errsou5)
181{
182	*errsou3 = ADF_DH895XCC_ERRSOU3;
183	*errsou5 = ADF_DH895XCC_ERRSOU5;
184}
185
186static u32
187get_clock_speed(struct adf_hw_device_data *self)
188{
189	/* CPP clock is half high-speed clock */
190	return self->clock_frequency / 2;
191}
192
193static void
194adf_enable_error_correction(struct adf_accel_dev *accel_dev)
195{
196	struct adf_hw_device_data *hw_device = accel_dev->hw_device;
197	struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR];
198	struct resource *csr = misc_bar->virt_addr;
199	unsigned int val, i;
200	unsigned int mask;
201
202	/* Enable Accel Engine error detection & correction */
203	mask = hw_device->ae_mask;
204	for (i = 0; mask; i++, mask >>= 1) {
205		if (!(mask & 1))
206			continue;
207		val = ADF_CSR_RD(csr, ADF_DH895XCC_AE_CTX_ENABLES(i));
208		val |= ADF_DH895XCC_ENABLE_AE_ECC_ERR;
209		ADF_CSR_WR(csr, ADF_DH895XCC_AE_CTX_ENABLES(i), val);
210		val = ADF_CSR_RD(csr, ADF_DH895XCC_AE_MISC_CONTROL(i));
211		val |= ADF_DH895XCC_ENABLE_AE_ECC_PARITY_CORR;
212		ADF_CSR_WR(csr, ADF_DH895XCC_AE_MISC_CONTROL(i), val);
213	}
214
215	/* Enable shared memory error detection & correction */
216	mask = hw_device->accel_mask;
217	for (i = 0; mask; i++, mask >>= 1) {
218		if (!(mask & 1))
219			continue;
220		val = ADF_CSR_RD(csr, ADF_DH895XCC_UERRSSMSH(i));
221		val |= ADF_DH895XCC_ERRSSMSH_EN;
222		ADF_CSR_WR(csr, ADF_DH895XCC_UERRSSMSH(i), val);
223		val = ADF_CSR_RD(csr, ADF_DH895XCC_CERRSSMSH(i));
224		val |= ADF_DH895XCC_ERRSSMSH_EN;
225		ADF_CSR_WR(csr, ADF_DH895XCC_CERRSSMSH(i), val);
226	}
227}
228
229static void
230adf_enable_ints(struct adf_accel_dev *accel_dev)
231{
232	struct resource *addr;
233
234	addr = (&GET_BARS(accel_dev)[ADF_DH895XCC_PMISC_BAR])->virt_addr;
235
236	/* Enable bundle and misc interrupts */
237	ADF_CSR_WR(addr,
238		   ADF_DH895XCC_SMIAPF0_MASK_OFFSET,
239		   accel_dev->u1.pf.vf_info ?
240		       0 :
241		       (1ULL << GET_MAX_BANKS(accel_dev)) - 1);
242	ADF_CSR_WR(addr,
243		   ADF_DH895XCC_SMIAPF1_MASK_OFFSET,
244		   ADF_DH895XCC_SMIA1_MASK);
245}
246
247static u32
248get_ae_clock(struct adf_hw_device_data *self)
249{
250	/*
251	 * Clock update interval is <16> ticks for dh895xcc.
252	 */
253	return self->clock_frequency / 16;
254}
255
256static int
257get_storage_enabled(struct adf_accel_dev *accel_dev, u32 *storage_enabled)
258{
259	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
260	char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
261
262	strlcpy(key, ADF_STORAGE_FIRMWARE_ENABLED, sizeof(key));
263	if (!adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val)) {
264		if (kstrtouint(val, 0, storage_enabled))
265			return -EFAULT;
266	}
267	return 0;
268}
269
270static u32
271dh895xcc_get_hw_cap(struct adf_accel_dev *accel_dev)
272{
273	device_t pdev = accel_dev->accel_pci_dev.pci_dev;
274	u32 legfuses;
275	u32 capabilities;
276
277	/* Read accelerator capabilities mask */
278	legfuses = pci_read_config(pdev, ADF_DEVICE_LEGFUSE_OFFSET, 4);
279	capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC +
280	    ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC +
281	    ICP_ACCEL_CAPABILITIES_CIPHER +
282	    ICP_ACCEL_CAPABILITIES_AUTHENTICATION +
283	    ICP_ACCEL_CAPABILITIES_COMPRESSION + ICP_ACCEL_CAPABILITIES_RAND +
284	    ICP_ACCEL_CAPABILITIES_HKDF + ICP_ACCEL_CAPABILITIES_ECEDMONT +
285	    ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN;
286
287	if (legfuses & ICP_ACCEL_MASK_CIPHER_SLICE)
288		capabilities &= ~(ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC |
289				  ICP_ACCEL_CAPABILITIES_CIPHER |
290				  ICP_ACCEL_CAPABILITIES_HKDF |
291				  ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN);
292	if (legfuses & ICP_ACCEL_MASK_AUTH_SLICE)
293		capabilities &= ~ICP_ACCEL_CAPABILITIES_AUTHENTICATION;
294	if (legfuses & ICP_ACCEL_MASK_PKE_SLICE)
295		capabilities &= ~(ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC |
296				  ICP_ACCEL_CAPABILITIES_ECEDMONT);
297	if (legfuses & ICP_ACCEL_MASK_COMPRESS_SLICE)
298		capabilities &= ~ICP_ACCEL_CAPABILITIES_COMPRESSION;
299
300	return capabilities;
301}
302
303static const char *
304get_obj_name(struct adf_accel_dev *accel_dev,
305	     enum adf_accel_unit_services service)
306{
307	return ADF_DH895XCC_AE_FW_NAME_CUSTOM1;
308}
309
310static u32
311get_objs_num(struct adf_accel_dev *accel_dev)
312{
313	return 1;
314}
315
316static u32
317get_obj_cfg_ae_mask(struct adf_accel_dev *accel_dev,
318		    enum adf_accel_unit_services services)
319{
320	return accel_dev->hw_device->ae_mask;
321}
322
323void
324adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
325{
326	hw_data->dev_class = &dh895xcc_class;
327	hw_data->instance_id = dh895xcc_class.instances++;
328	hw_data->num_banks = ADF_DH895XCC_ETR_MAX_BANKS;
329	hw_data->num_rings_per_bank = ADF_ETR_MAX_RINGS_PER_BANK;
330	hw_data->num_accel = ADF_DH895XCC_MAX_ACCELERATORS;
331	hw_data->num_logical_accel = 1;
332	hw_data->num_engines = ADF_DH895XCC_MAX_ACCELENGINES;
333	hw_data->tx_rx_gap = ADF_DH895XCC_RX_RINGS_OFFSET;
334	hw_data->tx_rings_mask = ADF_DH895XCC_TX_RINGS_MASK;
335	hw_data->alloc_irq = adf_isr_resource_alloc;
336	hw_data->free_irq = adf_isr_resource_free;
337	hw_data->enable_error_correction = adf_enable_error_correction;
338	hw_data->print_err_registers = adf_print_err_registers;
339	hw_data->get_accel_mask = get_accel_mask;
340	hw_data->get_ae_mask = get_ae_mask;
341	hw_data->get_num_accels = get_num_accels;
342	hw_data->get_num_aes = get_num_aes;
343	hw_data->get_etr_bar_id = get_etr_bar_id;
344	hw_data->get_misc_bar_id = get_misc_bar_id;
345	hw_data->get_arb_info = get_arb_info;
346	hw_data->get_admin_info = get_admin_info;
347	hw_data->get_errsou_offset = get_errsou_offset;
348	hw_data->get_clock_speed = get_clock_speed;
349	hw_data->get_sram_bar_id = get_sram_bar_id;
350	hw_data->get_sku = get_sku;
351	hw_data->heartbeat_ctr_num = ADF_NUM_HB_CNT_PER_AE;
352	hw_data->fw_name = ADF_DH895XCC_FW;
353	hw_data->fw_mmp_name = ADF_DH895XCC_MMP;
354	hw_data->init_admin_comms = adf_init_admin_comms;
355	hw_data->exit_admin_comms = adf_exit_admin_comms;
356	hw_data->disable_iov = adf_disable_sriov;
357	hw_data->send_admin_init = adf_send_admin_init;
358	hw_data->init_arb = adf_init_gen2_arb;
359	hw_data->exit_arb = adf_exit_arb;
360	hw_data->get_arb_mapping = adf_get_arbiter_mapping;
361	hw_data->enable_ints = adf_enable_ints;
362	hw_data->reset_device = adf_reset_sbr;
363	hw_data->restore_device = adf_dev_restore;
364	hw_data->get_accel_cap = dh895xcc_get_hw_cap;
365	hw_data->get_heartbeat_status = adf_get_heartbeat_status;
366	hw_data->get_ae_clock = get_ae_clock;
367	hw_data->get_objs_num = get_objs_num;
368	hw_data->get_obj_name = get_obj_name;
369	hw_data->get_obj_cfg_ae_mask = get_obj_cfg_ae_mask;
370	hw_data->clock_frequency = ADF_DH895XCC_AE_FREQ;
371	hw_data->extended_dc_capabilities = 0;
372	hw_data->get_storage_enabled = get_storage_enabled;
373	hw_data->query_storage_cap = 1;
374	hw_data->get_heartbeat_status = adf_get_heartbeat_status;
375	hw_data->get_ae_clock = get_ae_clock;
376	hw_data->storage_enable = 0;
377	hw_data->get_fw_image_type = adf_cfg_get_fw_image_type;
378	hw_data->config_device = adf_config_device;
379	hw_data->get_ring_to_svc_map = adf_cfg_get_services_enabled;
380	hw_data->set_asym_rings_mask = adf_cfg_set_asym_rings_mask;
381	hw_data->ring_to_svc_map = ADF_DEFAULT_RING_TO_SRV_MAP;
382	hw_data->pre_reset = adf_dev_pre_reset;
383	hw_data->post_reset = adf_dev_post_reset;
384
385	adf_gen2_init_hw_csr_info(&hw_data->csr_info);
386	adf_gen2_init_pf_pfvf_ops(&hw_data->csr_info.pfvf_ops);
387}
388
389void
390adf_clean_hw_data_dh895xcc(struct adf_hw_device_data *hw_data)
391{
392	hw_data->dev_class->instances--;
393}
394