|
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | +/* Copyright (c) 2024 Intel Corporation */ |
| 3 | + |
| 4 | +#include <linux/regmap.h> |
| 5 | + |
| 6 | +#include "intel-thc-dev.h" |
| 7 | + |
| 8 | +static int thc_regmap_read(void *context, unsigned int reg, |
| 9 | + unsigned int *val) |
| 10 | +{ |
| 11 | + struct thc_device *thc_ctx = context; |
| 12 | + void __iomem *base = thc_ctx->mmio_addr; |
| 13 | + |
| 14 | + *val = ioread32(base + reg); |
| 15 | + return 0; |
| 16 | +} |
| 17 | + |
| 18 | +static int thc_regmap_write(void *context, unsigned int reg, |
| 19 | + unsigned int val) |
| 20 | +{ |
| 21 | + struct thc_device *thc_ctx = context; |
| 22 | + void __iomem *base = thc_ctx->mmio_addr; |
| 23 | + |
| 24 | + iowrite32(val, base + reg); |
| 25 | + return 0; |
| 26 | +} |
| 27 | + |
| 28 | +static const struct regmap_range thc_rw_ranges[] = { |
| 29 | + regmap_reg_range(0x10, 0x14), |
| 30 | + regmap_reg_range(0x1000, 0x1320), |
| 31 | +}; |
| 32 | + |
| 33 | +static const struct regmap_access_table thc_rw_table = { |
| 34 | + .yes_ranges = thc_rw_ranges, |
| 35 | + .n_yes_ranges = ARRAY_SIZE(thc_rw_ranges), |
| 36 | +}; |
| 37 | + |
| 38 | +static const struct regmap_config thc_regmap_cfg = { |
| 39 | + .name = "thc_regmap_common", |
| 40 | + .reg_bits = 32, |
| 41 | + .val_bits = 32, |
| 42 | + .reg_stride = 4, |
| 43 | + .max_register = 0x1320, |
| 44 | + .reg_read = thc_regmap_read, |
| 45 | + .reg_write = thc_regmap_write, |
| 46 | + .cache_type = REGCACHE_NONE, |
| 47 | + .fast_io = true, |
| 48 | + .rd_table = &thc_rw_table, |
| 49 | + .wr_table = &thc_rw_table, |
| 50 | + .volatile_table = &thc_rw_table, |
| 51 | +}; |
| 52 | + |
| 53 | +/** |
| 54 | + * thc_clear_state - Clear THC hardware state |
| 55 | + * |
| 56 | + * @dev: The pointer of THC device structure |
| 57 | + */ |
| 58 | +static void thc_clear_state(const struct thc_device *dev) |
| 59 | +{ |
| 60 | + u32 val; |
| 61 | + |
| 62 | + /* Clear interrupt cause register */ |
| 63 | + val = THC_M_PRT_ERR_CAUSE_INVLD_DEV_ENTRY | |
| 64 | + THC_M_PRT_ERR_CAUSE_FRAME_BABBLE_ERR | |
| 65 | + THC_M_PRT_ERR_CAUSE_BUF_OVRRUN_ERR | |
| 66 | + THC_M_PRT_ERR_CAUSE_PRD_ENTRY_ERR; |
| 67 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_ERR_CAUSE_OFFSET, val, val); |
| 68 | + |
| 69 | + /* Clear interrupt error state */ |
| 70 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_1_OFFSET, |
| 71 | + THC_M_PRT_READ_DMA_CNTRL_IE_STALL, |
| 72 | + THC_M_PRT_READ_DMA_CNTRL_IE_STALL); |
| 73 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_2_OFFSET, |
| 74 | + THC_M_PRT_READ_DMA_CNTRL_IE_STALL, |
| 75 | + THC_M_PRT_READ_DMA_CNTRL_IE_STALL); |
| 76 | + |
| 77 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, |
| 78 | + THC_M_PRT_INT_STATUS_TXN_ERR_INT_STS, |
| 79 | + THC_M_PRT_INT_STATUS_TXN_ERR_INT_STS); |
| 80 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_INT_STATUS_OFFSET, |
| 81 | + THC_M_PRT_INT_STATUS_FATAL_ERR_INT_STS, |
| 82 | + THC_M_PRT_INT_STATUS_FATAL_ERR_INT_STS); |
| 83 | + |
| 84 | + val = THC_M_PRT_INT_EN_TXN_ERR_INT_EN | |
| 85 | + THC_M_PRT_INT_EN_FATAL_ERR_INT_EN | |
| 86 | + THC_M_PRT_INT_EN_BUF_OVRRUN_ERR_INT_EN; |
| 87 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_INT_EN_OFFSET, val, val); |
| 88 | + |
| 89 | + val = THC_M_PRT_SW_SEQ_STS_THC_SS_ERR | |
| 90 | + THC_M_PRT_SW_SEQ_STS_TSSDONE; |
| 91 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_SW_SEQ_STS_OFFSET, val, val); |
| 92 | + |
| 93 | + /* Clear RxDMA state */ |
| 94 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_1_OFFSET, |
| 95 | + THC_M_PRT_READ_DMA_CNTRL_IE_EOF, 0); |
| 96 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_2_OFFSET, |
| 97 | + THC_M_PRT_READ_DMA_CNTRL_IE_EOF, 0); |
| 98 | + |
| 99 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_INT_STS_1_OFFSET, |
| 100 | + THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS, |
| 101 | + THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS); |
| 102 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_INT_STS_2_OFFSET, |
| 103 | + THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS, |
| 104 | + THC_M_PRT_READ_DMA_INT_STS_EOF_INT_STS); |
| 105 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_INT_STS_1_OFFSET, |
| 106 | + THC_M_PRT_READ_DMA_INT_STS_NONDMA_INT_STS, |
| 107 | + THC_M_PRT_READ_DMA_INT_STS_NONDMA_INT_STS); |
| 108 | + |
| 109 | + /* Clear TxDMA state */ |
| 110 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_WRITE_DMA_CNTRL_OFFSET, |
| 111 | + THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC_DMACPL, |
| 112 | + THC_M_PRT_WRITE_DMA_CNTRL_THC_WRDMA_IE_IOC_DMACPL); |
| 113 | + |
| 114 | + val = THC_M_PRT_WRITE_INT_STS_THC_WRDMA_ERROR_STS | |
| 115 | + THC_M_PRT_WRITE_INT_STS_THC_WRDMA_IOC_STS | |
| 116 | + THC_M_PRT_WRITE_INT_STS_THC_WRDMA_CMPL_STATUS; |
| 117 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_WRITE_INT_STS_OFFSET, val, val); |
| 118 | + |
| 119 | + /* Reset all DMAs count */ |
| 120 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_DB_CNT_1_OFFSET, |
| 121 | + THC_M_PRT_DB_CNT_1_THC_M_PRT_DB_CNT_RST, |
| 122 | + THC_M_PRT_DB_CNT_1_THC_M_PRT_DB_CNT_RST); |
| 123 | + |
| 124 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_DEVINT_CNT_OFFSET, |
| 125 | + THC_M_PRT_DEVINT_CNT_THC_M_PRT_DEVINT_CNT_RST, |
| 126 | + THC_M_PRT_DEVINT_CNT_THC_M_PRT_DEVINT_CNT_RST); |
| 127 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_READ_DMA_CNTRL_1_OFFSET, |
| 128 | + THC_M_PRT_READ_DMA_CNTRL_TPCPR, |
| 129 | + THC_M_PRT_READ_DMA_CNTRL_TPCPR); |
| 130 | + |
| 131 | + /* Reset THC hardware sequence state */ |
| 132 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_FRAME_DROP_CNT_1_OFFSET, |
| 133 | + THC_M_PRT_FRAME_DROP_CNT_1_RFDC, |
| 134 | + THC_M_PRT_FRAME_DROP_CNT_1_RFDC); |
| 135 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_FRAME_DROP_CNT_2_OFFSET, |
| 136 | + THC_M_PRT_FRAME_DROP_CNT_2_RFDC, |
| 137 | + THC_M_PRT_FRAME_DROP_CNT_2_RFDC); |
| 138 | + |
| 139 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_FRM_CNT_1_OFFSET, |
| 140 | + THC_M_PRT_FRM_CNT_1_THC_M_PRT_FRM_CNT_RST, |
| 141 | + THC_M_PRT_FRM_CNT_1_THC_M_PRT_FRM_CNT_RST); |
| 142 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_FRM_CNT_2_OFFSET, |
| 143 | + THC_M_PRT_FRM_CNT_2_THC_M_PRT_FRM_CNT_RST, |
| 144 | + THC_M_PRT_FRM_CNT_2_THC_M_PRT_FRM_CNT_RST); |
| 145 | + |
| 146 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_RXDMA_PKT_CNT_1_OFFSET, |
| 147 | + THC_M_PRT_RXDMA_PKT_CNT_1_THC_M_PRT_RXDMA_PKT_CNT_RST, |
| 148 | + THC_M_PRT_RXDMA_PKT_CNT_1_THC_M_PRT_RXDMA_PKT_CNT_RST); |
| 149 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_RXDMA_PKT_CNT_2_OFFSET, |
| 150 | + THC_M_PRT_RXDMA_PKT_CNT_2_THC_M_PRT_RXDMA_PKT_CNT_RST, |
| 151 | + THC_M_PRT_RXDMA_PKT_CNT_2_THC_M_PRT_RXDMA_PKT_CNT_RST); |
| 152 | + |
| 153 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_SWINT_CNT_1_OFFSET, |
| 154 | + THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT_RST, |
| 155 | + THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT_RST); |
| 156 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_SWINT_CNT_1_OFFSET, |
| 157 | + THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT_RST, |
| 158 | + THC_M_PRT_SWINT_CNT_1_THC_M_PRT_SWINT_CNT_RST); |
| 159 | + |
| 160 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_TX_FRM_CNT_OFFSET, |
| 161 | + THC_M_PRT_TX_FRM_CNT_THC_M_PRT_TX_FRM_CNT_RST, |
| 162 | + THC_M_PRT_TX_FRM_CNT_THC_M_PRT_TX_FRM_CNT_RST); |
| 163 | + |
| 164 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_TXDMA_PKT_CNT_OFFSET, |
| 165 | + THC_M_PRT_TXDMA_PKT_CNT_THC_M_PRT_TXDMA_PKT_CNT_RST, |
| 166 | + THC_M_PRT_TXDMA_PKT_CNT_THC_M_PRT_TXDMA_PKT_CNT_RST); |
| 167 | + |
| 168 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_UFRM_CNT_1_OFFSET, |
| 169 | + THC_M_PRT_UFRM_CNT_1_THC_M_PRT_UFRM_CNT_RST, |
| 170 | + THC_M_PRT_UFRM_CNT_1_THC_M_PRT_UFRM_CNT_RST); |
| 171 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_UFRM_CNT_2_OFFSET, |
| 172 | + THC_M_PRT_UFRM_CNT_2_THC_M_PRT_UFRM_CNT_RST, |
| 173 | + THC_M_PRT_UFRM_CNT_2_THC_M_PRT_UFRM_CNT_RST); |
| 174 | + |
| 175 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_PRD_EMPTY_CNT_1_OFFSET, |
| 176 | + THC_M_PRT_PRD_EMPTY_CNT_1_RPTEC, |
| 177 | + THC_M_PRT_PRD_EMPTY_CNT_1_RPTEC); |
| 178 | + regmap_write_bits(dev->thc_regmap, THC_M_PRT_PRD_EMPTY_CNT_2_OFFSET, |
| 179 | + THC_M_PRT_PRD_EMPTY_CNT_2_RPTEC, |
| 180 | + THC_M_PRT_PRD_EMPTY_CNT_2_RPTEC); |
| 181 | +} |
| 182 | + |
| 183 | +/** |
| 184 | + * thc_dev_init - Allocate and initialize the THC device structure |
| 185 | + * |
| 186 | + * @device: The pointer of device structure |
| 187 | + * @mem_addr: The pointer of MMIO memory address |
| 188 | + * |
| 189 | + * Return: The thc_device pointer on success, NULL on failed. |
| 190 | + */ |
| 191 | +struct thc_device *thc_dev_init(struct device *device, void __iomem *mem_addr) |
| 192 | +{ |
| 193 | + struct thc_device *thc_dev; |
| 194 | + int ret; |
| 195 | + |
| 196 | + thc_dev = devm_kzalloc(device, sizeof(*thc_dev), GFP_KERNEL); |
| 197 | + if (!thc_dev) |
| 198 | + return ERR_PTR(-ENOMEM); |
| 199 | + |
| 200 | + thc_dev->dev = device; |
| 201 | + thc_dev->mmio_addr = mem_addr; |
| 202 | + thc_dev->thc_regmap = devm_regmap_init(device, NULL, thc_dev, &thc_regmap_cfg); |
| 203 | + if (IS_ERR(thc_dev->thc_regmap)) { |
| 204 | + ret = PTR_ERR(thc_dev->thc_regmap); |
| 205 | + dev_err_once(device, "Failed to init thc_regmap: %d\n", ret); |
| 206 | + return ERR_PTR(ret); |
| 207 | + } |
| 208 | + |
| 209 | + thc_clear_state(thc_dev); |
| 210 | + |
| 211 | + return thc_dev; |
| 212 | +} |
| 213 | +EXPORT_SYMBOL_NS_GPL(thc_dev_init, "INTEL_THC"); |
| 214 | + |
| 215 | +MODULE_AUTHOR( "Xinpeng Sun <[email protected]>"); |
| 216 | +MODULE_AUTHOR( "Even Xu <[email protected]>"); |
| 217 | + |
| 218 | +MODULE_DESCRIPTION("Intel(R) Intel THC Hardware Driver"); |
| 219 | +MODULE_LICENSE("GPL"); |
0 commit comments