162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <linux/delay.h> 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "nitrox_dev.h" 562306a36Sopenharmony_ci#include "nitrox_csr.h" 662306a36Sopenharmony_ci#include "nitrox_hal.h" 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#define PLL_REF_CLK 50 962306a36Sopenharmony_ci#define MAX_CSR_RETRIES 10 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/** 1262306a36Sopenharmony_ci * emu_enable_cores - Enable EMU cluster cores. 1362306a36Sopenharmony_ci * @ndev: NITROX device 1462306a36Sopenharmony_ci */ 1562306a36Sopenharmony_cistatic void emu_enable_cores(struct nitrox_device *ndev) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci union emu_se_enable emu_se; 1862306a36Sopenharmony_ci union emu_ae_enable emu_ae; 1962306a36Sopenharmony_ci int i; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci /* AE cores 20 per cluster */ 2262306a36Sopenharmony_ci emu_ae.value = 0; 2362306a36Sopenharmony_ci emu_ae.s.enable = 0xfffff; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci /* SE cores 16 per cluster */ 2662306a36Sopenharmony_ci emu_se.value = 0; 2762306a36Sopenharmony_ci emu_se.s.enable = 0xffff; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci /* enable per cluster cores */ 3062306a36Sopenharmony_ci for (i = 0; i < NR_CLUSTERS; i++) { 3162306a36Sopenharmony_ci nitrox_write_csr(ndev, EMU_AE_ENABLEX(i), emu_ae.value); 3262306a36Sopenharmony_ci nitrox_write_csr(ndev, EMU_SE_ENABLEX(i), emu_se.value); 3362306a36Sopenharmony_ci } 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/** 3762306a36Sopenharmony_ci * nitrox_config_emu_unit - configure EMU unit. 3862306a36Sopenharmony_ci * @ndev: NITROX device 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_civoid nitrox_config_emu_unit(struct nitrox_device *ndev) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci union emu_wd_int_ena_w1s emu_wd_int; 4362306a36Sopenharmony_ci union emu_ge_int_ena_w1s emu_ge_int; 4462306a36Sopenharmony_ci u64 offset; 4562306a36Sopenharmony_ci int i; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci /* enable cores */ 4862306a36Sopenharmony_ci emu_enable_cores(ndev); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci /* enable general error and watch dog interrupts */ 5162306a36Sopenharmony_ci emu_ge_int.value = 0; 5262306a36Sopenharmony_ci emu_ge_int.s.se_ge = 0xffff; 5362306a36Sopenharmony_ci emu_ge_int.s.ae_ge = 0xfffff; 5462306a36Sopenharmony_ci emu_wd_int.value = 0; 5562306a36Sopenharmony_ci emu_wd_int.s.se_wd = 1; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci for (i = 0; i < NR_CLUSTERS; i++) { 5862306a36Sopenharmony_ci offset = EMU_WD_INT_ENA_W1SX(i); 5962306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, emu_wd_int.value); 6062306a36Sopenharmony_ci offset = EMU_GE_INT_ENA_W1SX(i); 6162306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, emu_ge_int.value); 6262306a36Sopenharmony_ci } 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic void reset_pkt_input_ring(struct nitrox_device *ndev, int ring) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci union nps_pkt_in_instr_ctl pkt_in_ctl; 6862306a36Sopenharmony_ci union nps_pkt_in_done_cnts pkt_in_cnts; 6962306a36Sopenharmony_ci int max_retries = MAX_CSR_RETRIES; 7062306a36Sopenharmony_ci u64 offset; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* step 1: disable the ring, clear enable bit */ 7362306a36Sopenharmony_ci offset = NPS_PKT_IN_INSTR_CTLX(ring); 7462306a36Sopenharmony_ci pkt_in_ctl.value = nitrox_read_csr(ndev, offset); 7562306a36Sopenharmony_ci pkt_in_ctl.s.enb = 0; 7662306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, pkt_in_ctl.value); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* step 2: wait to clear [ENB] */ 7962306a36Sopenharmony_ci usleep_range(100, 150); 8062306a36Sopenharmony_ci do { 8162306a36Sopenharmony_ci pkt_in_ctl.value = nitrox_read_csr(ndev, offset); 8262306a36Sopenharmony_ci if (!pkt_in_ctl.s.enb) 8362306a36Sopenharmony_ci break; 8462306a36Sopenharmony_ci udelay(50); 8562306a36Sopenharmony_ci } while (max_retries--); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci /* step 3: clear done counts */ 8862306a36Sopenharmony_ci offset = NPS_PKT_IN_DONE_CNTSX(ring); 8962306a36Sopenharmony_ci pkt_in_cnts.value = nitrox_read_csr(ndev, offset); 9062306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, pkt_in_cnts.value); 9162306a36Sopenharmony_ci usleep_range(50, 100); 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_civoid enable_pkt_input_ring(struct nitrox_device *ndev, int ring) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci union nps_pkt_in_instr_ctl pkt_in_ctl; 9762306a36Sopenharmony_ci int max_retries = MAX_CSR_RETRIES; 9862306a36Sopenharmony_ci u64 offset; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* 64-byte instruction size */ 10162306a36Sopenharmony_ci offset = NPS_PKT_IN_INSTR_CTLX(ring); 10262306a36Sopenharmony_ci pkt_in_ctl.value = nitrox_read_csr(ndev, offset); 10362306a36Sopenharmony_ci pkt_in_ctl.s.is64b = 1; 10462306a36Sopenharmony_ci pkt_in_ctl.s.enb = 1; 10562306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, pkt_in_ctl.value); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci /* wait for set [ENB] */ 10862306a36Sopenharmony_ci do { 10962306a36Sopenharmony_ci pkt_in_ctl.value = nitrox_read_csr(ndev, offset); 11062306a36Sopenharmony_ci if (pkt_in_ctl.s.enb) 11162306a36Sopenharmony_ci break; 11262306a36Sopenharmony_ci udelay(50); 11362306a36Sopenharmony_ci } while (max_retries--); 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci/** 11762306a36Sopenharmony_ci * nitrox_config_pkt_input_rings - configure Packet Input Rings 11862306a36Sopenharmony_ci * @ndev: NITROX device 11962306a36Sopenharmony_ci */ 12062306a36Sopenharmony_civoid nitrox_config_pkt_input_rings(struct nitrox_device *ndev) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci int i; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci for (i = 0; i < ndev->nr_queues; i++) { 12562306a36Sopenharmony_ci struct nitrox_cmdq *cmdq = &ndev->pkt_inq[i]; 12662306a36Sopenharmony_ci union nps_pkt_in_instr_rsize pkt_in_rsize; 12762306a36Sopenharmony_ci union nps_pkt_in_instr_baoff_dbell pkt_in_dbell; 12862306a36Sopenharmony_ci u64 offset; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci reset_pkt_input_ring(ndev, i); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci /** 13362306a36Sopenharmony_ci * step 4: 13462306a36Sopenharmony_ci * configure ring base address 16-byte aligned, 13562306a36Sopenharmony_ci * size and interrupt threshold. 13662306a36Sopenharmony_ci */ 13762306a36Sopenharmony_ci offset = NPS_PKT_IN_INSTR_BADDRX(i); 13862306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, cmdq->dma); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci /* configure ring size */ 14162306a36Sopenharmony_ci offset = NPS_PKT_IN_INSTR_RSIZEX(i); 14262306a36Sopenharmony_ci pkt_in_rsize.value = 0; 14362306a36Sopenharmony_ci pkt_in_rsize.s.rsize = ndev->qlen; 14462306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, pkt_in_rsize.value); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci /* set high threshold for pkt input ring interrupts */ 14762306a36Sopenharmony_ci offset = NPS_PKT_IN_INT_LEVELSX(i); 14862306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, 0xffffffff); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci /* step 5: clear off door bell counts */ 15162306a36Sopenharmony_ci offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(i); 15262306a36Sopenharmony_ci pkt_in_dbell.value = 0; 15362306a36Sopenharmony_ci pkt_in_dbell.s.dbell = 0xffffffff; 15462306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, pkt_in_dbell.value); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* enable the ring */ 15762306a36Sopenharmony_ci enable_pkt_input_ring(ndev, i); 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic void reset_pkt_solicit_port(struct nitrox_device *ndev, int port) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci union nps_pkt_slc_ctl pkt_slc_ctl; 16462306a36Sopenharmony_ci union nps_pkt_slc_cnts pkt_slc_cnts; 16562306a36Sopenharmony_ci int max_retries = MAX_CSR_RETRIES; 16662306a36Sopenharmony_ci u64 offset; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* step 1: disable slc port */ 16962306a36Sopenharmony_ci offset = NPS_PKT_SLC_CTLX(port); 17062306a36Sopenharmony_ci pkt_slc_ctl.value = nitrox_read_csr(ndev, offset); 17162306a36Sopenharmony_ci pkt_slc_ctl.s.enb = 0; 17262306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, pkt_slc_ctl.value); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* step 2 */ 17562306a36Sopenharmony_ci usleep_range(100, 150); 17662306a36Sopenharmony_ci /* wait to clear [ENB] */ 17762306a36Sopenharmony_ci do { 17862306a36Sopenharmony_ci pkt_slc_ctl.value = nitrox_read_csr(ndev, offset); 17962306a36Sopenharmony_ci if (!pkt_slc_ctl.s.enb) 18062306a36Sopenharmony_ci break; 18162306a36Sopenharmony_ci udelay(50); 18262306a36Sopenharmony_ci } while (max_retries--); 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci /* step 3: clear slc counters */ 18562306a36Sopenharmony_ci offset = NPS_PKT_SLC_CNTSX(port); 18662306a36Sopenharmony_ci pkt_slc_cnts.value = nitrox_read_csr(ndev, offset); 18762306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, pkt_slc_cnts.value); 18862306a36Sopenharmony_ci usleep_range(50, 100); 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_civoid enable_pkt_solicit_port(struct nitrox_device *ndev, int port) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci union nps_pkt_slc_ctl pkt_slc_ctl; 19462306a36Sopenharmony_ci int max_retries = MAX_CSR_RETRIES; 19562306a36Sopenharmony_ci u64 offset; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci offset = NPS_PKT_SLC_CTLX(port); 19862306a36Sopenharmony_ci pkt_slc_ctl.value = 0; 19962306a36Sopenharmony_ci pkt_slc_ctl.s.enb = 1; 20062306a36Sopenharmony_ci /* 20162306a36Sopenharmony_ci * 8 trailing 0x00 bytes will be added 20262306a36Sopenharmony_ci * to the end of the outgoing packet. 20362306a36Sopenharmony_ci */ 20462306a36Sopenharmony_ci pkt_slc_ctl.s.z = 1; 20562306a36Sopenharmony_ci /* enable response header */ 20662306a36Sopenharmony_ci pkt_slc_ctl.s.rh = 1; 20762306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, pkt_slc_ctl.value); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci /* wait to set [ENB] */ 21062306a36Sopenharmony_ci do { 21162306a36Sopenharmony_ci pkt_slc_ctl.value = nitrox_read_csr(ndev, offset); 21262306a36Sopenharmony_ci if (pkt_slc_ctl.s.enb) 21362306a36Sopenharmony_ci break; 21462306a36Sopenharmony_ci udelay(50); 21562306a36Sopenharmony_ci } while (max_retries--); 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_cistatic void config_pkt_solicit_port(struct nitrox_device *ndev, int port) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci union nps_pkt_slc_int_levels pkt_slc_int; 22162306a36Sopenharmony_ci u64 offset; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci reset_pkt_solicit_port(ndev, port); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* step 4: configure interrupt levels */ 22662306a36Sopenharmony_ci offset = NPS_PKT_SLC_INT_LEVELSX(port); 22762306a36Sopenharmony_ci pkt_slc_int.value = 0; 22862306a36Sopenharmony_ci /* time interrupt threshold */ 22962306a36Sopenharmony_ci pkt_slc_int.s.timet = 0x3fffff; 23062306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, pkt_slc_int.value); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci /* enable the solicit port */ 23362306a36Sopenharmony_ci enable_pkt_solicit_port(ndev, port); 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_civoid nitrox_config_pkt_solicit_ports(struct nitrox_device *ndev) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci int i; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci for (i = 0; i < ndev->nr_queues; i++) 24162306a36Sopenharmony_ci config_pkt_solicit_port(ndev, i); 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci/** 24562306a36Sopenharmony_ci * enable_nps_core_interrupts - enable NPS core interrutps 24662306a36Sopenharmony_ci * @ndev: NITROX device. 24762306a36Sopenharmony_ci * 24862306a36Sopenharmony_ci * This includes NPS core interrupts. 24962306a36Sopenharmony_ci */ 25062306a36Sopenharmony_cistatic void enable_nps_core_interrupts(struct nitrox_device *ndev) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci union nps_core_int_ena_w1s core_int; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* NPS core interrutps */ 25562306a36Sopenharmony_ci core_int.value = 0; 25662306a36Sopenharmony_ci core_int.s.host_wr_err = 1; 25762306a36Sopenharmony_ci core_int.s.host_wr_timeout = 1; 25862306a36Sopenharmony_ci core_int.s.exec_wr_timeout = 1; 25962306a36Sopenharmony_ci core_int.s.npco_dma_malform = 1; 26062306a36Sopenharmony_ci core_int.s.host_nps_wr_err = 1; 26162306a36Sopenharmony_ci nitrox_write_csr(ndev, NPS_CORE_INT_ENA_W1S, core_int.value); 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_civoid nitrox_config_nps_core_unit(struct nitrox_device *ndev) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci union nps_core_gbl_vfcfg core_gbl_vfcfg; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* endian control information */ 26962306a36Sopenharmony_ci nitrox_write_csr(ndev, NPS_CORE_CONTROL, 1ULL); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* disable ILK interface */ 27262306a36Sopenharmony_ci core_gbl_vfcfg.value = 0; 27362306a36Sopenharmony_ci core_gbl_vfcfg.s.ilk_disable = 1; 27462306a36Sopenharmony_ci core_gbl_vfcfg.s.cfg = __NDEV_MODE_PF; 27562306a36Sopenharmony_ci nitrox_write_csr(ndev, NPS_CORE_GBL_VFCFG, core_gbl_vfcfg.value); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci /* enable nps core interrupts */ 27862306a36Sopenharmony_ci enable_nps_core_interrupts(ndev); 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci/** 28262306a36Sopenharmony_ci * enable_nps_pkt_interrupts - enable NPS packet interrutps 28362306a36Sopenharmony_ci * @ndev: NITROX device. 28462306a36Sopenharmony_ci * 28562306a36Sopenharmony_ci * This includes NPS packet in and slc interrupts. 28662306a36Sopenharmony_ci */ 28762306a36Sopenharmony_cistatic void enable_nps_pkt_interrupts(struct nitrox_device *ndev) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci /* NPS packet in ring interrupts */ 29062306a36Sopenharmony_ci nitrox_write_csr(ndev, NPS_PKT_IN_RERR_LO_ENA_W1S, (~0ULL)); 29162306a36Sopenharmony_ci nitrox_write_csr(ndev, NPS_PKT_IN_RERR_HI_ENA_W1S, (~0ULL)); 29262306a36Sopenharmony_ci nitrox_write_csr(ndev, NPS_PKT_IN_ERR_TYPE_ENA_W1S, (~0ULL)); 29362306a36Sopenharmony_ci /* NPS packet slc port interrupts */ 29462306a36Sopenharmony_ci nitrox_write_csr(ndev, NPS_PKT_SLC_RERR_HI_ENA_W1S, (~0ULL)); 29562306a36Sopenharmony_ci nitrox_write_csr(ndev, NPS_PKT_SLC_RERR_LO_ENA_W1S, (~0ULL)); 29662306a36Sopenharmony_ci nitrox_write_csr(ndev, NPS_PKT_SLC_ERR_TYPE_ENA_W1S, (~0uLL)); 29762306a36Sopenharmony_ci} 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_civoid nitrox_config_nps_pkt_unit(struct nitrox_device *ndev) 30062306a36Sopenharmony_ci{ 30162306a36Sopenharmony_ci /* config input and solicit ports */ 30262306a36Sopenharmony_ci nitrox_config_pkt_input_rings(ndev); 30362306a36Sopenharmony_ci nitrox_config_pkt_solicit_ports(ndev); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci /* enable nps packet interrupts */ 30662306a36Sopenharmony_ci enable_nps_pkt_interrupts(ndev); 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cistatic void reset_aqm_ring(struct nitrox_device *ndev, int ring) 31062306a36Sopenharmony_ci{ 31162306a36Sopenharmony_ci union aqmq_en aqmq_en_reg; 31262306a36Sopenharmony_ci union aqmq_activity_stat activity_stat; 31362306a36Sopenharmony_ci union aqmq_cmp_cnt cmp_cnt; 31462306a36Sopenharmony_ci int max_retries = MAX_CSR_RETRIES; 31562306a36Sopenharmony_ci u64 offset; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci /* step 1: disable the queue */ 31862306a36Sopenharmony_ci offset = AQMQ_ENX(ring); 31962306a36Sopenharmony_ci aqmq_en_reg.value = 0; 32062306a36Sopenharmony_ci aqmq_en_reg.queue_enable = 0; 32162306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, aqmq_en_reg.value); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci /* step 2: wait for AQMQ_ACTIVITY_STATX[QUEUE_ACTIVE] to clear */ 32462306a36Sopenharmony_ci usleep_range(100, 150); 32562306a36Sopenharmony_ci offset = AQMQ_ACTIVITY_STATX(ring); 32662306a36Sopenharmony_ci do { 32762306a36Sopenharmony_ci activity_stat.value = nitrox_read_csr(ndev, offset); 32862306a36Sopenharmony_ci if (!activity_stat.queue_active) 32962306a36Sopenharmony_ci break; 33062306a36Sopenharmony_ci udelay(50); 33162306a36Sopenharmony_ci } while (max_retries--); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci /* step 3: clear commands completed count */ 33462306a36Sopenharmony_ci offset = AQMQ_CMP_CNTX(ring); 33562306a36Sopenharmony_ci cmp_cnt.value = nitrox_read_csr(ndev, offset); 33662306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, cmp_cnt.value); 33762306a36Sopenharmony_ci usleep_range(50, 100); 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_civoid enable_aqm_ring(struct nitrox_device *ndev, int ring) 34162306a36Sopenharmony_ci{ 34262306a36Sopenharmony_ci union aqmq_en aqmq_en_reg; 34362306a36Sopenharmony_ci u64 offset; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci offset = AQMQ_ENX(ring); 34662306a36Sopenharmony_ci aqmq_en_reg.value = 0; 34762306a36Sopenharmony_ci aqmq_en_reg.queue_enable = 1; 34862306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, aqmq_en_reg.value); 34962306a36Sopenharmony_ci usleep_range(50, 100); 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_civoid nitrox_config_aqm_rings(struct nitrox_device *ndev) 35362306a36Sopenharmony_ci{ 35462306a36Sopenharmony_ci int ring; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci for (ring = 0; ring < ndev->nr_queues; ring++) { 35762306a36Sopenharmony_ci struct nitrox_cmdq *cmdq = ndev->aqmq[ring]; 35862306a36Sopenharmony_ci union aqmq_drbl drbl; 35962306a36Sopenharmony_ci union aqmq_qsz qsize; 36062306a36Sopenharmony_ci union aqmq_cmp_thr cmp_thr; 36162306a36Sopenharmony_ci u64 offset; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci /* steps 1 - 3 */ 36462306a36Sopenharmony_ci reset_aqm_ring(ndev, ring); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci /* step 4: clear doorbell count of ring */ 36762306a36Sopenharmony_ci offset = AQMQ_DRBLX(ring); 36862306a36Sopenharmony_ci drbl.value = 0; 36962306a36Sopenharmony_ci drbl.dbell_count = 0xFFFFFFFF; 37062306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, drbl.value); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci /* step 5: configure host ring details */ 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci /* set host address for next command of ring */ 37562306a36Sopenharmony_ci offset = AQMQ_NXT_CMDX(ring); 37662306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, 0ULL); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci /* set host address of ring base */ 37962306a36Sopenharmony_ci offset = AQMQ_BADRX(ring); 38062306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, cmdq->dma); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* set ring size */ 38362306a36Sopenharmony_ci offset = AQMQ_QSZX(ring); 38462306a36Sopenharmony_ci qsize.value = 0; 38562306a36Sopenharmony_ci qsize.host_queue_size = ndev->qlen; 38662306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, qsize.value); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci /* set command completion threshold */ 38962306a36Sopenharmony_ci offset = AQMQ_CMP_THRX(ring); 39062306a36Sopenharmony_ci cmp_thr.value = 0; 39162306a36Sopenharmony_ci cmp_thr.commands_completed_threshold = 1; 39262306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, cmp_thr.value); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci /* step 6: enable the queue */ 39562306a36Sopenharmony_ci enable_aqm_ring(ndev, ring); 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_cistatic void enable_aqm_interrupts(struct nitrox_device *ndev) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci /* clear interrupt enable bits */ 40262306a36Sopenharmony_ci nitrox_write_csr(ndev, AQM_DBELL_OVF_LO_ENA_W1S, (~0ULL)); 40362306a36Sopenharmony_ci nitrox_write_csr(ndev, AQM_DBELL_OVF_HI_ENA_W1S, (~0ULL)); 40462306a36Sopenharmony_ci nitrox_write_csr(ndev, AQM_DMA_RD_ERR_LO_ENA_W1S, (~0ULL)); 40562306a36Sopenharmony_ci nitrox_write_csr(ndev, AQM_DMA_RD_ERR_HI_ENA_W1S, (~0ULL)); 40662306a36Sopenharmony_ci nitrox_write_csr(ndev, AQM_EXEC_NA_LO_ENA_W1S, (~0ULL)); 40762306a36Sopenharmony_ci nitrox_write_csr(ndev, AQM_EXEC_NA_HI_ENA_W1S, (~0ULL)); 40862306a36Sopenharmony_ci nitrox_write_csr(ndev, AQM_EXEC_ERR_LO_ENA_W1S, (~0ULL)); 40962306a36Sopenharmony_ci nitrox_write_csr(ndev, AQM_EXEC_ERR_HI_ENA_W1S, (~0ULL)); 41062306a36Sopenharmony_ci} 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_civoid nitrox_config_aqm_unit(struct nitrox_device *ndev) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci /* config aqm command queues */ 41562306a36Sopenharmony_ci nitrox_config_aqm_rings(ndev); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci /* enable aqm interrupts */ 41862306a36Sopenharmony_ci enable_aqm_interrupts(ndev); 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_civoid nitrox_config_pom_unit(struct nitrox_device *ndev) 42262306a36Sopenharmony_ci{ 42362306a36Sopenharmony_ci union pom_int_ena_w1s pom_int; 42462306a36Sopenharmony_ci int i; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci /* enable pom interrupts */ 42762306a36Sopenharmony_ci pom_int.value = 0; 42862306a36Sopenharmony_ci pom_int.s.illegal_dport = 1; 42962306a36Sopenharmony_ci nitrox_write_csr(ndev, POM_INT_ENA_W1S, pom_int.value); 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci /* enable perf counters */ 43262306a36Sopenharmony_ci for (i = 0; i < ndev->hw.se_cores; i++) 43362306a36Sopenharmony_ci nitrox_write_csr(ndev, POM_PERF_CTL, BIT_ULL(i)); 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci/** 43762306a36Sopenharmony_ci * nitrox_config_rand_unit - enable NITROX random number unit 43862306a36Sopenharmony_ci * @ndev: NITROX device 43962306a36Sopenharmony_ci */ 44062306a36Sopenharmony_civoid nitrox_config_rand_unit(struct nitrox_device *ndev) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci union efl_rnm_ctl_status efl_rnm_ctl; 44362306a36Sopenharmony_ci u64 offset; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci offset = EFL_RNM_CTL_STATUS; 44662306a36Sopenharmony_ci efl_rnm_ctl.value = nitrox_read_csr(ndev, offset); 44762306a36Sopenharmony_ci efl_rnm_ctl.s.ent_en = 1; 44862306a36Sopenharmony_ci efl_rnm_ctl.s.rng_en = 1; 44962306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, efl_rnm_ctl.value); 45062306a36Sopenharmony_ci} 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_civoid nitrox_config_efl_unit(struct nitrox_device *ndev) 45362306a36Sopenharmony_ci{ 45462306a36Sopenharmony_ci int i; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci for (i = 0; i < NR_CLUSTERS; i++) { 45762306a36Sopenharmony_ci union efl_core_int_ena_w1s efl_core_int; 45862306a36Sopenharmony_ci u64 offset; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci /* EFL core interrupts */ 46162306a36Sopenharmony_ci offset = EFL_CORE_INT_ENA_W1SX(i); 46262306a36Sopenharmony_ci efl_core_int.value = 0; 46362306a36Sopenharmony_ci efl_core_int.s.len_ovr = 1; 46462306a36Sopenharmony_ci efl_core_int.s.d_left = 1; 46562306a36Sopenharmony_ci efl_core_int.s.epci_decode_err = 1; 46662306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, efl_core_int.value); 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci offset = EFL_CORE_VF_ERR_INT0_ENA_W1SX(i); 46962306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, (~0ULL)); 47062306a36Sopenharmony_ci offset = EFL_CORE_VF_ERR_INT1_ENA_W1SX(i); 47162306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, (~0ULL)); 47262306a36Sopenharmony_ci } 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_civoid nitrox_config_bmi_unit(struct nitrox_device *ndev) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci union bmi_ctl bmi_ctl; 47862306a36Sopenharmony_ci union bmi_int_ena_w1s bmi_int_ena; 47962306a36Sopenharmony_ci u64 offset; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci /* no threshold limits for PCIe */ 48262306a36Sopenharmony_ci offset = BMI_CTL; 48362306a36Sopenharmony_ci bmi_ctl.value = nitrox_read_csr(ndev, offset); 48462306a36Sopenharmony_ci bmi_ctl.s.max_pkt_len = 0xff; 48562306a36Sopenharmony_ci bmi_ctl.s.nps_free_thrsh = 0xff; 48662306a36Sopenharmony_ci bmi_ctl.s.nps_hdrq_thrsh = 0x7a; 48762306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, bmi_ctl.value); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci /* enable interrupts */ 49062306a36Sopenharmony_ci offset = BMI_INT_ENA_W1S; 49162306a36Sopenharmony_ci bmi_int_ena.value = 0; 49262306a36Sopenharmony_ci bmi_int_ena.s.max_len_err_nps = 1; 49362306a36Sopenharmony_ci bmi_int_ena.s.pkt_rcv_err_nps = 1; 49462306a36Sopenharmony_ci bmi_int_ena.s.fpf_undrrn = 1; 49562306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, bmi_int_ena.value); 49662306a36Sopenharmony_ci} 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_civoid nitrox_config_bmo_unit(struct nitrox_device *ndev) 49962306a36Sopenharmony_ci{ 50062306a36Sopenharmony_ci union bmo_ctl2 bmo_ctl2; 50162306a36Sopenharmony_ci u64 offset; 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci /* no threshold limits for PCIe */ 50462306a36Sopenharmony_ci offset = BMO_CTL2; 50562306a36Sopenharmony_ci bmo_ctl2.value = nitrox_read_csr(ndev, offset); 50662306a36Sopenharmony_ci bmo_ctl2.s.nps_slc_buf_thrsh = 0xff; 50762306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, bmo_ctl2.value); 50862306a36Sopenharmony_ci} 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_civoid invalidate_lbc(struct nitrox_device *ndev) 51162306a36Sopenharmony_ci{ 51262306a36Sopenharmony_ci union lbc_inval_ctl lbc_ctl; 51362306a36Sopenharmony_ci union lbc_inval_status lbc_stat; 51462306a36Sopenharmony_ci int max_retries = MAX_CSR_RETRIES; 51562306a36Sopenharmony_ci u64 offset; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci /* invalidate LBC */ 51862306a36Sopenharmony_ci offset = LBC_INVAL_CTL; 51962306a36Sopenharmony_ci lbc_ctl.value = nitrox_read_csr(ndev, offset); 52062306a36Sopenharmony_ci lbc_ctl.s.cam_inval_start = 1; 52162306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, lbc_ctl.value); 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci offset = LBC_INVAL_STATUS; 52462306a36Sopenharmony_ci do { 52562306a36Sopenharmony_ci lbc_stat.value = nitrox_read_csr(ndev, offset); 52662306a36Sopenharmony_ci if (lbc_stat.s.done) 52762306a36Sopenharmony_ci break; 52862306a36Sopenharmony_ci udelay(50); 52962306a36Sopenharmony_ci } while (max_retries--); 53062306a36Sopenharmony_ci} 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_civoid nitrox_config_lbc_unit(struct nitrox_device *ndev) 53362306a36Sopenharmony_ci{ 53462306a36Sopenharmony_ci union lbc_int_ena_w1s lbc_int_ena; 53562306a36Sopenharmony_ci u64 offset; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci invalidate_lbc(ndev); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci /* enable interrupts */ 54062306a36Sopenharmony_ci offset = LBC_INT_ENA_W1S; 54162306a36Sopenharmony_ci lbc_int_ena.value = 0; 54262306a36Sopenharmony_ci lbc_int_ena.s.dma_rd_err = 1; 54362306a36Sopenharmony_ci lbc_int_ena.s.over_fetch_err = 1; 54462306a36Sopenharmony_ci lbc_int_ena.s.cam_inval_abort = 1; 54562306a36Sopenharmony_ci lbc_int_ena.s.cam_hard_err = 1; 54662306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, lbc_int_ena.value); 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci offset = LBC_PLM_VF1_64_INT_ENA_W1S; 54962306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, (~0ULL)); 55062306a36Sopenharmony_ci offset = LBC_PLM_VF65_128_INT_ENA_W1S; 55162306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, (~0ULL)); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci offset = LBC_ELM_VF1_64_INT_ENA_W1S; 55462306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, (~0ULL)); 55562306a36Sopenharmony_ci offset = LBC_ELM_VF65_128_INT_ENA_W1S; 55662306a36Sopenharmony_ci nitrox_write_csr(ndev, offset, (~0ULL)); 55762306a36Sopenharmony_ci} 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_civoid config_nps_core_vfcfg_mode(struct nitrox_device *ndev, enum vf_mode mode) 56062306a36Sopenharmony_ci{ 56162306a36Sopenharmony_ci union nps_core_gbl_vfcfg vfcfg; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci vfcfg.value = nitrox_read_csr(ndev, NPS_CORE_GBL_VFCFG); 56462306a36Sopenharmony_ci vfcfg.s.cfg = mode & 0x7; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci nitrox_write_csr(ndev, NPS_CORE_GBL_VFCFG, vfcfg.value); 56762306a36Sopenharmony_ci} 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_cistatic const char *get_core_option(u8 se_cores, u8 ae_cores) 57062306a36Sopenharmony_ci{ 57162306a36Sopenharmony_ci const char *option = ""; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci if (ae_cores == AE_MAX_CORES) { 57462306a36Sopenharmony_ci switch (se_cores) { 57562306a36Sopenharmony_ci case SE_MAX_CORES: 57662306a36Sopenharmony_ci option = "60"; 57762306a36Sopenharmony_ci break; 57862306a36Sopenharmony_ci case 40: 57962306a36Sopenharmony_ci option = "60s"; 58062306a36Sopenharmony_ci break; 58162306a36Sopenharmony_ci } 58262306a36Sopenharmony_ci } else if (ae_cores == (AE_MAX_CORES / 2)) { 58362306a36Sopenharmony_ci option = "30"; 58462306a36Sopenharmony_ci } else { 58562306a36Sopenharmony_ci option = "60i"; 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci return option; 58962306a36Sopenharmony_ci} 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_cistatic const char *get_feature_option(u8 zip_cores, int core_freq) 59262306a36Sopenharmony_ci{ 59362306a36Sopenharmony_ci if (zip_cores == 0) 59462306a36Sopenharmony_ci return ""; 59562306a36Sopenharmony_ci else if (zip_cores < ZIP_MAX_CORES) 59662306a36Sopenharmony_ci return "-C15"; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci if (core_freq >= 850) 59962306a36Sopenharmony_ci return "-C45"; 60062306a36Sopenharmony_ci else if (core_freq >= 750) 60162306a36Sopenharmony_ci return "-C35"; 60262306a36Sopenharmony_ci else if (core_freq >= 550) 60362306a36Sopenharmony_ci return "-C25"; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci return ""; 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_civoid nitrox_get_hwinfo(struct nitrox_device *ndev) 60962306a36Sopenharmony_ci{ 61062306a36Sopenharmony_ci union emu_fuse_map emu_fuse; 61162306a36Sopenharmony_ci union rst_boot rst_boot; 61262306a36Sopenharmony_ci union fus_dat1 fus_dat1; 61362306a36Sopenharmony_ci unsigned char name[IFNAMSIZ * 2] = {}; 61462306a36Sopenharmony_ci int i, dead_cores; 61562306a36Sopenharmony_ci u64 offset; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci /* get core frequency */ 61862306a36Sopenharmony_ci offset = RST_BOOT; 61962306a36Sopenharmony_ci rst_boot.value = nitrox_read_csr(ndev, offset); 62062306a36Sopenharmony_ci ndev->hw.freq = (rst_boot.pnr_mul + 3) * PLL_REF_CLK; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci for (i = 0; i < NR_CLUSTERS; i++) { 62362306a36Sopenharmony_ci offset = EMU_FUSE_MAPX(i); 62462306a36Sopenharmony_ci emu_fuse.value = nitrox_read_csr(ndev, offset); 62562306a36Sopenharmony_ci if (emu_fuse.s.valid) { 62662306a36Sopenharmony_ci dead_cores = hweight32(emu_fuse.s.ae_fuse); 62762306a36Sopenharmony_ci ndev->hw.ae_cores += AE_CORES_PER_CLUSTER - dead_cores; 62862306a36Sopenharmony_ci dead_cores = hweight16(emu_fuse.s.se_fuse); 62962306a36Sopenharmony_ci ndev->hw.se_cores += SE_CORES_PER_CLUSTER - dead_cores; 63062306a36Sopenharmony_ci } 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci /* find zip hardware availability */ 63362306a36Sopenharmony_ci offset = FUS_DAT1; 63462306a36Sopenharmony_ci fus_dat1.value = nitrox_read_csr(ndev, offset); 63562306a36Sopenharmony_ci if (!fus_dat1.nozip) { 63662306a36Sopenharmony_ci dead_cores = hweight8(fus_dat1.zip_info); 63762306a36Sopenharmony_ci ndev->hw.zip_cores = ZIP_MAX_CORES - dead_cores; 63862306a36Sopenharmony_ci } 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci /* determine the partname 64162306a36Sopenharmony_ci * CNN55<core option>-<freq><pincount>-<feature option>-<rev> 64262306a36Sopenharmony_ci */ 64362306a36Sopenharmony_ci snprintf(name, sizeof(name), "CNN55%s-%3dBG676%s-1.%u", 64462306a36Sopenharmony_ci get_core_option(ndev->hw.se_cores, ndev->hw.ae_cores), 64562306a36Sopenharmony_ci ndev->hw.freq, 64662306a36Sopenharmony_ci get_feature_option(ndev->hw.zip_cores, ndev->hw.freq), 64762306a36Sopenharmony_ci ndev->hw.revision_id); 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci /* copy partname */ 65062306a36Sopenharmony_ci strncpy(ndev->hw.partname, name, sizeof(ndev->hw.partname)); 65162306a36Sopenharmony_ci} 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_civoid enable_pf2vf_mbox_interrupts(struct nitrox_device *ndev) 65462306a36Sopenharmony_ci{ 65562306a36Sopenharmony_ci u64 value = ~0ULL; 65662306a36Sopenharmony_ci u64 reg_addr; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci /* Mailbox interrupt low enable set register */ 65962306a36Sopenharmony_ci reg_addr = NPS_PKT_MBOX_INT_LO_ENA_W1S; 66062306a36Sopenharmony_ci nitrox_write_csr(ndev, reg_addr, value); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci /* Mailbox interrupt high enable set register */ 66362306a36Sopenharmony_ci reg_addr = NPS_PKT_MBOX_INT_HI_ENA_W1S; 66462306a36Sopenharmony_ci nitrox_write_csr(ndev, reg_addr, value); 66562306a36Sopenharmony_ci} 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_civoid disable_pf2vf_mbox_interrupts(struct nitrox_device *ndev) 66862306a36Sopenharmony_ci{ 66962306a36Sopenharmony_ci u64 value = ~0ULL; 67062306a36Sopenharmony_ci u64 reg_addr; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci /* Mailbox interrupt low enable clear register */ 67362306a36Sopenharmony_ci reg_addr = NPS_PKT_MBOX_INT_LO_ENA_W1C; 67462306a36Sopenharmony_ci nitrox_write_csr(ndev, reg_addr, value); 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci /* Mailbox interrupt high enable clear register */ 67762306a36Sopenharmony_ci reg_addr = NPS_PKT_MBOX_INT_HI_ENA_W1C; 67862306a36Sopenharmony_ci nitrox_write_csr(ndev, reg_addr, value); 67962306a36Sopenharmony_ci} 680