1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. 3 4 #include <linux/bitfield.h> 5 #include <linux/device.h> 6 #include <linux/io.h> 7 8 #include "hinic3_common.h" 9 #include "hinic3_csr.h" 10 #include "hinic3_hwdev.h" 11 #include "hinic3_hwif.h" 12 13 /* config BAR4/5 4MB, DB & DWQE both 2MB */ 14 #define HINIC3_DB_DWQE_SIZE 0x00400000 15 16 /* db/dwqe page size: 4K */ 17 #define HINIC3_DB_PAGE_SIZE 0x00001000 18 #define HINIC3_DWQE_OFFSET 0x00000800 19 #define HINIC3_DB_MAX_AREAS (HINIC3_DB_DWQE_SIZE / HINIC3_DB_PAGE_SIZE) 20 21 #define HINIC3_GET_REG_ADDR(reg) ((reg) & (HINIC3_REGS_FLAG_MASK)) 22 23 static void __iomem *hinic3_reg_addr(struct hinic3_hwif *hwif, u32 reg) 24 { 25 return hwif->cfg_regs_base + HINIC3_GET_REG_ADDR(reg); 26 } 27 28 u32 hinic3_hwif_read_reg(struct hinic3_hwif *hwif, u32 reg) 29 { 30 void __iomem *addr = hinic3_reg_addr(hwif, reg); 31 32 return ioread32be(addr); 33 } 34 35 void hinic3_hwif_write_reg(struct hinic3_hwif *hwif, u32 reg, u32 val) 36 { 37 void __iomem *addr = hinic3_reg_addr(hwif, reg); 38 39 iowrite32be(val, addr); 40 } 41 42 static int get_db_idx(struct hinic3_hwif *hwif, u32 *idx) 43 { 44 struct hinic3_db_area *db_area = &hwif->db_area; 45 u32 pg_idx; 46 47 spin_lock(&db_area->idx_lock); 48 pg_idx = find_first_zero_bit(db_area->db_bitmap_array, 49 db_area->db_max_areas); 50 if (pg_idx == db_area->db_max_areas) { 51 spin_unlock(&db_area->idx_lock); 52 return -ENOMEM; 53 } 54 set_bit(pg_idx, db_area->db_bitmap_array); 55 spin_unlock(&db_area->idx_lock); 56 57 *idx = pg_idx; 58 59 return 0; 60 } 61 62 static void free_db_idx(struct hinic3_hwif *hwif, u32 idx) 63 { 64 struct hinic3_db_area *db_area = &hwif->db_area; 65 66 spin_lock(&db_area->idx_lock); 67 clear_bit(idx, db_area->db_bitmap_array); 68 spin_unlock(&db_area->idx_lock); 69 } 70 71 void hinic3_free_db_addr(struct hinic3_hwdev *hwdev, const u8 __iomem *db_base) 72 { 73 struct hinic3_hwif *hwif; 74 uintptr_t distance; 75 u32 idx; 76 77 hwif = hwdev->hwif; 78 distance = db_base - hwif->db_base; 79 idx = distance / HINIC3_DB_PAGE_SIZE; 80 81 free_db_idx(hwif, idx); 82 } 83 84 int hinic3_alloc_db_addr(struct hinic3_hwdev *hwdev, void __iomem **db_base, 85 void __iomem **dwqe_base) 86 { 87 struct hinic3_hwif *hwif; 88 u8 __iomem *addr; 89 u32 idx; 90 int err; 91 92 hwif = hwdev->hwif; 93 94 err = get_db_idx(hwif, &idx); 95 if (err) 96 return err; 97 98 addr = hwif->db_base + idx * HINIC3_DB_PAGE_SIZE; 99 *db_base = addr; 100 101 if (dwqe_base) 102 *dwqe_base = addr + HINIC3_DWQE_OFFSET; 103 104 return 0; 105 } 106 107 void hinic3_set_msix_state(struct hinic3_hwdev *hwdev, u16 msix_idx, 108 enum hinic3_msix_state flag) 109 { 110 struct hinic3_hwif *hwif; 111 u8 int_msk = 1; 112 u32 mask_bits; 113 u32 addr; 114 115 hwif = hwdev->hwif; 116 117 if (flag) 118 mask_bits = HINIC3_MSI_CLR_INDIR_SET(int_msk, INT_MSK_SET); 119 else 120 mask_bits = HINIC3_MSI_CLR_INDIR_SET(int_msk, INT_MSK_CLR); 121 mask_bits = mask_bits | 122 HINIC3_MSI_CLR_INDIR_SET(msix_idx, SIMPLE_INDIR_IDX); 123 124 addr = HINIC3_CSR_FUNC_MSI_CLR_WR_ADDR; 125 hinic3_hwif_write_reg(hwif, addr, mask_bits); 126 } 127 128 void hinic3_msix_intr_clear_resend_bit(struct hinic3_hwdev *hwdev, u16 msix_idx, 129 u8 clear_resend_en) 130 { 131 struct hinic3_hwif *hwif; 132 u32 msix_ctrl, addr; 133 134 hwif = hwdev->hwif; 135 136 msix_ctrl = HINIC3_MSI_CLR_INDIR_SET(msix_idx, SIMPLE_INDIR_IDX) | 137 HINIC3_MSI_CLR_INDIR_SET(clear_resend_en, RESEND_TIMER_CLR); 138 139 addr = HINIC3_CSR_FUNC_MSI_CLR_WR_ADDR; 140 hinic3_hwif_write_reg(hwif, addr, msix_ctrl); 141 } 142 143 void hinic3_set_msix_auto_mask_state(struct hinic3_hwdev *hwdev, u16 msix_idx, 144 enum hinic3_msix_auto_mask flag) 145 { 146 struct hinic3_hwif *hwif; 147 u32 mask_bits; 148 u32 addr; 149 150 hwif = hwdev->hwif; 151 152 if (flag) 153 mask_bits = HINIC3_MSI_CLR_INDIR_SET(1, AUTO_MSK_SET); 154 else 155 mask_bits = HINIC3_MSI_CLR_INDIR_SET(1, AUTO_MSK_CLR); 156 157 mask_bits = mask_bits | 158 HINIC3_MSI_CLR_INDIR_SET(msix_idx, SIMPLE_INDIR_IDX); 159 160 addr = HINIC3_CSR_FUNC_MSI_CLR_WR_ADDR; 161 hinic3_hwif_write_reg(hwif, addr, mask_bits); 162 } 163 164 u16 hinic3_global_func_id(struct hinic3_hwdev *hwdev) 165 { 166 return hwdev->hwif->attr.func_global_idx; 167 } 168