1d5c65159SKalle Valo // SPDX-License-Identifier: BSD-3-Clause-Clear 2d5c65159SKalle Valo /* 3d5c65159SKalle Valo * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. 4d5c65159SKalle Valo */ 5d5c65159SKalle Valo 6d5c65159SKalle Valo #include <linux/module.h> 7d5c65159SKalle Valo #include <linux/platform_device.h> 8d5c65159SKalle Valo #include <linux/of_device.h> 9d5c65159SKalle Valo #include <linux/of.h> 10d5c65159SKalle Valo #include <linux/dma-mapping.h> 11d5c65159SKalle Valo #include "ahb.h" 12d5c65159SKalle Valo #include "debug.h" 13d5c65159SKalle Valo #include <linux/remoteproc.h> 14d5c65159SKalle Valo 15d5c65159SKalle Valo static const struct of_device_id ath11k_ahb_of_match[] = { 16d5c65159SKalle Valo /* TODO: Should we change the compatible string to something similar 17d5c65159SKalle Valo * to one that ath10k uses? 18d5c65159SKalle Valo */ 19d5c65159SKalle Valo { .compatible = "qcom,ipq8074-wifi", 20d5c65159SKalle Valo .data = (void *)ATH11K_HW_IPQ8074, 21d5c65159SKalle Valo }, 22d5c65159SKalle Valo { } 23d5c65159SKalle Valo }; 24d5c65159SKalle Valo 25d5c65159SKalle Valo MODULE_DEVICE_TABLE(of, ath11k_ahb_of_match); 26d5c65159SKalle Valo 27d5c65159SKalle Valo /* Target firmware's Copy Engine configuration. */ 28d5c65159SKalle Valo static const struct ce_pipe_config target_ce_config_wlan[] = { 29d5c65159SKalle Valo /* CE0: host->target HTC control and raw streams */ 30d5c65159SKalle Valo { 31d5c65159SKalle Valo .pipenum = __cpu_to_le32(0), 32d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), 33d5c65159SKalle Valo .nentries = __cpu_to_le32(32), 34d5c65159SKalle Valo .nbytes_max = __cpu_to_le32(2048), 35d5c65159SKalle Valo .flags = __cpu_to_le32(CE_ATTR_FLAGS), 36d5c65159SKalle Valo .reserved = __cpu_to_le32(0), 37d5c65159SKalle Valo }, 38d5c65159SKalle Valo 39d5c65159SKalle Valo /* CE1: target->host HTT + HTC control */ 40d5c65159SKalle Valo { 41d5c65159SKalle Valo .pipenum = __cpu_to_le32(1), 42d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), 43d5c65159SKalle Valo .nentries = __cpu_to_le32(32), 44d5c65159SKalle Valo .nbytes_max = __cpu_to_le32(2048), 45d5c65159SKalle Valo .flags = __cpu_to_le32(CE_ATTR_FLAGS), 46d5c65159SKalle Valo .reserved = __cpu_to_le32(0), 47d5c65159SKalle Valo }, 48d5c65159SKalle Valo 49d5c65159SKalle Valo /* CE2: target->host WMI */ 50d5c65159SKalle Valo { 51d5c65159SKalle Valo .pipenum = __cpu_to_le32(2), 52d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), 53d5c65159SKalle Valo .nentries = __cpu_to_le32(32), 54d5c65159SKalle Valo .nbytes_max = __cpu_to_le32(2048), 55d5c65159SKalle Valo .flags = __cpu_to_le32(CE_ATTR_FLAGS), 56d5c65159SKalle Valo .reserved = __cpu_to_le32(0), 57d5c65159SKalle Valo }, 58d5c65159SKalle Valo 59d5c65159SKalle Valo /* CE3: host->target WMI */ 60d5c65159SKalle Valo { 61d5c65159SKalle Valo .pipenum = __cpu_to_le32(3), 62d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), 63d5c65159SKalle Valo .nentries = __cpu_to_le32(32), 64d5c65159SKalle Valo .nbytes_max = __cpu_to_le32(2048), 65d5c65159SKalle Valo .flags = __cpu_to_le32(CE_ATTR_FLAGS), 66d5c65159SKalle Valo .reserved = __cpu_to_le32(0), 67d5c65159SKalle Valo }, 68d5c65159SKalle Valo 69d5c65159SKalle Valo /* CE4: host->target HTT */ 70d5c65159SKalle Valo { 71d5c65159SKalle Valo .pipenum = __cpu_to_le32(4), 72d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), 73d5c65159SKalle Valo .nentries = __cpu_to_le32(256), 74d5c65159SKalle Valo .nbytes_max = __cpu_to_le32(256), 75d5c65159SKalle Valo .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR), 76d5c65159SKalle Valo .reserved = __cpu_to_le32(0), 77d5c65159SKalle Valo }, 78d5c65159SKalle Valo 79d5c65159SKalle Valo /* CE5: target->host Pktlog */ 80d5c65159SKalle Valo { 81d5c65159SKalle Valo .pipenum = __cpu_to_le32(5), 82d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), 83d5c65159SKalle Valo .nentries = __cpu_to_le32(32), 84d5c65159SKalle Valo .nbytes_max = __cpu_to_le32(2048), 85d5c65159SKalle Valo .flags = __cpu_to_le32(0), 86d5c65159SKalle Valo .reserved = __cpu_to_le32(0), 87d5c65159SKalle Valo }, 88d5c65159SKalle Valo 89d5c65159SKalle Valo /* CE6: Reserved for target autonomous hif_memcpy */ 90d5c65159SKalle Valo { 91d5c65159SKalle Valo .pipenum = __cpu_to_le32(6), 92d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_INOUT), 93d5c65159SKalle Valo .nentries = __cpu_to_le32(32), 94d5c65159SKalle Valo .nbytes_max = __cpu_to_le32(65535), 95d5c65159SKalle Valo .flags = __cpu_to_le32(CE_ATTR_FLAGS), 96d5c65159SKalle Valo .reserved = __cpu_to_le32(0), 97d5c65159SKalle Valo }, 98d5c65159SKalle Valo 99d5c65159SKalle Valo /* CE7 used only by Host */ 100d5c65159SKalle Valo { 101d5c65159SKalle Valo .pipenum = __cpu_to_le32(7), 102d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), 103d5c65159SKalle Valo .nentries = __cpu_to_le32(32), 104d5c65159SKalle Valo .nbytes_max = __cpu_to_le32(2048), 105d5c65159SKalle Valo .flags = __cpu_to_le32(CE_ATTR_FLAGS), 106d5c65159SKalle Valo .reserved = __cpu_to_le32(0), 107d5c65159SKalle Valo }, 108d5c65159SKalle Valo 109d5c65159SKalle Valo /* CE8 target->host used only by IPA */ 110d5c65159SKalle Valo { 111d5c65159SKalle Valo .pipenum = __cpu_to_le32(8), 112d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_INOUT), 113d5c65159SKalle Valo .nentries = __cpu_to_le32(32), 114d5c65159SKalle Valo .nbytes_max = __cpu_to_le32(65535), 115d5c65159SKalle Valo .flags = __cpu_to_le32(CE_ATTR_FLAGS), 116d5c65159SKalle Valo .reserved = __cpu_to_le32(0), 117d5c65159SKalle Valo }, 118d5c65159SKalle Valo 119d5c65159SKalle Valo /* CE9 host->target HTT */ 120d5c65159SKalle Valo { 121d5c65159SKalle Valo .pipenum = __cpu_to_le32(9), 122d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), 123d5c65159SKalle Valo .nentries = __cpu_to_le32(32), 124d5c65159SKalle Valo .nbytes_max = __cpu_to_le32(2048), 125d5c65159SKalle Valo .flags = __cpu_to_le32(CE_ATTR_FLAGS), 126d5c65159SKalle Valo .reserved = __cpu_to_le32(0), 127d5c65159SKalle Valo }, 128d5c65159SKalle Valo 129d5c65159SKalle Valo /* CE10 target->host HTT */ 130d5c65159SKalle Valo { 131d5c65159SKalle Valo .pipenum = __cpu_to_le32(10), 132d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H), 133d5c65159SKalle Valo .nentries = __cpu_to_le32(0), 134d5c65159SKalle Valo .nbytes_max = __cpu_to_le32(0), 135d5c65159SKalle Valo .flags = __cpu_to_le32(CE_ATTR_FLAGS), 136d5c65159SKalle Valo .reserved = __cpu_to_le32(0), 137d5c65159SKalle Valo }, 138d5c65159SKalle Valo 139d5c65159SKalle Valo /* CE11 Not used */ 140d5c65159SKalle Valo { 141d5c65159SKalle Valo .pipenum = __cpu_to_le32(0), 142d5c65159SKalle Valo .pipedir = __cpu_to_le32(0), 143d5c65159SKalle Valo .nentries = __cpu_to_le32(0), 144d5c65159SKalle Valo .nbytes_max = __cpu_to_le32(0), 145d5c65159SKalle Valo .flags = __cpu_to_le32(CE_ATTR_FLAGS), 146d5c65159SKalle Valo .reserved = __cpu_to_le32(0), 147d5c65159SKalle Valo }, 148d5c65159SKalle Valo }; 149d5c65159SKalle Valo 150d5c65159SKalle Valo /* Map from service/endpoint to Copy Engine. 151d5c65159SKalle Valo * This table is derived from the CE_PCI TABLE, above. 152d5c65159SKalle Valo * It is passed to the Target at startup for use by firmware. 153d5c65159SKalle Valo */ 154d5c65159SKalle Valo static const struct service_to_pipe target_service_to_ce_map_wlan[] = { 155d5c65159SKalle Valo { 156d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO), 157d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 158d5c65159SKalle Valo .pipenum = __cpu_to_le32(3), 159d5c65159SKalle Valo }, 160d5c65159SKalle Valo { 161d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO), 162d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 163d5c65159SKalle Valo .pipenum = __cpu_to_le32(2), 164d5c65159SKalle Valo }, 165d5c65159SKalle Valo { 166d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK), 167d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 168d5c65159SKalle Valo .pipenum = __cpu_to_le32(3), 169d5c65159SKalle Valo }, 170d5c65159SKalle Valo { 171d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK), 172d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 173d5c65159SKalle Valo .pipenum = __cpu_to_le32(2), 174d5c65159SKalle Valo }, 175d5c65159SKalle Valo { 176d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE), 177d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 178d5c65159SKalle Valo .pipenum = __cpu_to_le32(3), 179d5c65159SKalle Valo }, 180d5c65159SKalle Valo { 181d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE), 182d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 183d5c65159SKalle Valo .pipenum = __cpu_to_le32(2), 184d5c65159SKalle Valo }, 185d5c65159SKalle Valo { 186d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI), 187d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 188d5c65159SKalle Valo .pipenum = __cpu_to_le32(3), 189d5c65159SKalle Valo }, 190d5c65159SKalle Valo { 191d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI), 192d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 193d5c65159SKalle Valo .pipenum = __cpu_to_le32(2), 194d5c65159SKalle Valo }, 195d5c65159SKalle Valo { 196d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL), 197d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 198d5c65159SKalle Valo .pipenum = __cpu_to_le32(3), 199d5c65159SKalle Valo }, 200d5c65159SKalle Valo { 201d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL), 202d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 203d5c65159SKalle Valo .pipenum = __cpu_to_le32(2), 204d5c65159SKalle Valo }, 205d5c65159SKalle Valo { 206d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1), 207d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 208d5c65159SKalle Valo .pipenum = __cpu_to_le32(7), 209d5c65159SKalle Valo }, 210d5c65159SKalle Valo { 211d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1), 212d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 213d5c65159SKalle Valo .pipenum = __cpu_to_le32(2), 214d5c65159SKalle Valo }, 215d5c65159SKalle Valo { 216d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2), 217d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 218d5c65159SKalle Valo .pipenum = __cpu_to_le32(9), 219d5c65159SKalle Valo }, 220d5c65159SKalle Valo { 221d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2), 222d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 223d5c65159SKalle Valo .pipenum = __cpu_to_le32(2), 224d5c65159SKalle Valo }, 225d5c65159SKalle Valo { 226d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL), 227d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 228d5c65159SKalle Valo .pipenum = __cpu_to_le32(0), 229d5c65159SKalle Valo }, 230d5c65159SKalle Valo { 231d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL), 232d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 233d5c65159SKalle Valo .pipenum = __cpu_to_le32(1), 234d5c65159SKalle Valo }, 235d5c65159SKalle Valo { /* not used */ 236d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS), 237d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 238d5c65159SKalle Valo .pipenum = __cpu_to_le32(0), 239d5c65159SKalle Valo }, 240d5c65159SKalle Valo { /* not used */ 241d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS), 242d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 243d5c65159SKalle Valo .pipenum = __cpu_to_le32(1), 244d5c65159SKalle Valo }, 245d5c65159SKalle Valo { 246d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG), 247d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */ 248d5c65159SKalle Valo .pipenum = __cpu_to_le32(4), 249d5c65159SKalle Valo }, 250d5c65159SKalle Valo { 251d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG), 252d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 253d5c65159SKalle Valo .pipenum = __cpu_to_le32(1), 254d5c65159SKalle Valo }, 255d5c65159SKalle Valo { 256d5c65159SKalle Valo .service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_PKT_LOG), 257d5c65159SKalle Valo .pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */ 258d5c65159SKalle Valo .pipenum = __cpu_to_le32(5), 259d5c65159SKalle Valo }, 260d5c65159SKalle Valo 261d5c65159SKalle Valo /* (Additions here) */ 262d5c65159SKalle Valo 263d5c65159SKalle Valo { /* terminator entry */ } 264d5c65159SKalle Valo }; 265d5c65159SKalle Valo 266d5c65159SKalle Valo #define ATH11K_IRQ_CE0_OFFSET 4 267d5c65159SKalle Valo 268d5c65159SKalle Valo static const char *irq_name[ATH11K_IRQ_NUM_MAX] = { 269d5c65159SKalle Valo "misc-pulse1", 270d5c65159SKalle Valo "misc-latch", 271d5c65159SKalle Valo "sw-exception", 272d5c65159SKalle Valo "watchdog", 273d5c65159SKalle Valo "ce0", 274d5c65159SKalle Valo "ce1", 275d5c65159SKalle Valo "ce2", 276d5c65159SKalle Valo "ce3", 277d5c65159SKalle Valo "ce4", 278d5c65159SKalle Valo "ce5", 279d5c65159SKalle Valo "ce6", 280d5c65159SKalle Valo "ce7", 281d5c65159SKalle Valo "ce8", 282d5c65159SKalle Valo "ce9", 283d5c65159SKalle Valo "ce10", 284d5c65159SKalle Valo "ce11", 285d5c65159SKalle Valo "host2wbm-desc-feed", 286d5c65159SKalle Valo "host2reo-re-injection", 287d5c65159SKalle Valo "host2reo-command", 288d5c65159SKalle Valo "host2rxdma-monitor-ring3", 289d5c65159SKalle Valo "host2rxdma-monitor-ring2", 290d5c65159SKalle Valo "host2rxdma-monitor-ring1", 291d5c65159SKalle Valo "reo2ost-exception", 292d5c65159SKalle Valo "wbm2host-rx-release", 293d5c65159SKalle Valo "reo2host-status", 294d5c65159SKalle Valo "reo2host-destination-ring4", 295d5c65159SKalle Valo "reo2host-destination-ring3", 296d5c65159SKalle Valo "reo2host-destination-ring2", 297d5c65159SKalle Valo "reo2host-destination-ring1", 298d5c65159SKalle Valo "rxdma2host-monitor-destination-mac3", 299d5c65159SKalle Valo "rxdma2host-monitor-destination-mac2", 300d5c65159SKalle Valo "rxdma2host-monitor-destination-mac1", 301d5c65159SKalle Valo "ppdu-end-interrupts-mac3", 302d5c65159SKalle Valo "ppdu-end-interrupts-mac2", 303d5c65159SKalle Valo "ppdu-end-interrupts-mac1", 304d5c65159SKalle Valo "rxdma2host-monitor-status-ring-mac3", 305d5c65159SKalle Valo "rxdma2host-monitor-status-ring-mac2", 306d5c65159SKalle Valo "rxdma2host-monitor-status-ring-mac1", 307d5c65159SKalle Valo "host2rxdma-host-buf-ring-mac3", 308d5c65159SKalle Valo "host2rxdma-host-buf-ring-mac2", 309d5c65159SKalle Valo "host2rxdma-host-buf-ring-mac1", 310d5c65159SKalle Valo "rxdma2host-destination-ring-mac3", 311d5c65159SKalle Valo "rxdma2host-destination-ring-mac2", 312d5c65159SKalle Valo "rxdma2host-destination-ring-mac1", 313d5c65159SKalle Valo "host2tcl-input-ring4", 314d5c65159SKalle Valo "host2tcl-input-ring3", 315d5c65159SKalle Valo "host2tcl-input-ring2", 316d5c65159SKalle Valo "host2tcl-input-ring1", 317d5c65159SKalle Valo "wbm2host-tx-completions-ring3", 318d5c65159SKalle Valo "wbm2host-tx-completions-ring2", 319d5c65159SKalle Valo "wbm2host-tx-completions-ring1", 320d5c65159SKalle Valo "tcl2host-status-ring", 321d5c65159SKalle Valo }; 322d5c65159SKalle Valo 323d5c65159SKalle Valo #define ATH11K_TX_RING_MASK_0 0x1 324d5c65159SKalle Valo #define ATH11K_TX_RING_MASK_1 0x2 325d5c65159SKalle Valo #define ATH11K_TX_RING_MASK_2 0x4 326d5c65159SKalle Valo 327d5c65159SKalle Valo #define ATH11K_RX_RING_MASK_0 0x1 328d5c65159SKalle Valo #define ATH11K_RX_RING_MASK_1 0x2 329d5c65159SKalle Valo #define ATH11K_RX_RING_MASK_2 0x4 330d5c65159SKalle Valo #define ATH11K_RX_RING_MASK_3 0x8 331d5c65159SKalle Valo 332d5c65159SKalle Valo #define ATH11K_RX_ERR_RING_MASK_0 0x1 333d5c65159SKalle Valo 334d5c65159SKalle Valo #define ATH11K_RX_WBM_REL_RING_MASK_0 0x1 335d5c65159SKalle Valo 336d5c65159SKalle Valo #define ATH11K_REO_STATUS_RING_MASK_0 0x1 337d5c65159SKalle Valo 338d5c65159SKalle Valo #define ATH11K_RXDMA2HOST_RING_MASK_0 0x1 339d5c65159SKalle Valo #define ATH11K_RXDMA2HOST_RING_MASK_1 0x2 340d5c65159SKalle Valo #define ATH11K_RXDMA2HOST_RING_MASK_2 0x4 341d5c65159SKalle Valo 342d5c65159SKalle Valo #define ATH11K_HOST2RXDMA_RING_MASK_0 0x1 343d5c65159SKalle Valo #define ATH11K_HOST2RXDMA_RING_MASK_1 0x2 344d5c65159SKalle Valo #define ATH11K_HOST2RXDMA_RING_MASK_2 0x4 345d5c65159SKalle Valo 346d5c65159SKalle Valo #define ATH11K_RX_MON_STATUS_RING_MASK_0 0x1 347d5c65159SKalle Valo #define ATH11K_RX_MON_STATUS_RING_MASK_1 0x2 348d5c65159SKalle Valo #define ATH11K_RX_MON_STATUS_RING_MASK_2 0x4 349d5c65159SKalle Valo 350d5c65159SKalle Valo const u8 ath11k_tx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { 351d5c65159SKalle Valo ATH11K_TX_RING_MASK_0, 352d5c65159SKalle Valo ATH11K_TX_RING_MASK_1, 353d5c65159SKalle Valo ATH11K_TX_RING_MASK_2, 354d5c65159SKalle Valo }; 355d5c65159SKalle Valo 356d5c65159SKalle Valo const u8 rx_mon_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { 357d5c65159SKalle Valo 0, 0, 0, 0, 358d5c65159SKalle Valo ATH11K_RX_MON_STATUS_RING_MASK_0, 359d5c65159SKalle Valo ATH11K_RX_MON_STATUS_RING_MASK_1, 360d5c65159SKalle Valo ATH11K_RX_MON_STATUS_RING_MASK_2, 361d5c65159SKalle Valo }; 362d5c65159SKalle Valo 363d5c65159SKalle Valo const u8 ath11k_rx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { 364d5c65159SKalle Valo 0, 0, 0, 0, 0, 0, 0, 365d5c65159SKalle Valo ATH11K_RX_RING_MASK_0, 366d5c65159SKalle Valo ATH11K_RX_RING_MASK_1, 367d5c65159SKalle Valo ATH11K_RX_RING_MASK_2, 368d5c65159SKalle Valo ATH11K_RX_RING_MASK_3, 369d5c65159SKalle Valo }; 370d5c65159SKalle Valo 371d5c65159SKalle Valo const u8 ath11k_rx_err_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { 372d5c65159SKalle Valo ATH11K_RX_ERR_RING_MASK_0, 373d5c65159SKalle Valo }; 374d5c65159SKalle Valo 375d5c65159SKalle Valo const u8 ath11k_rx_wbm_rel_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { 376d5c65159SKalle Valo ATH11K_RX_WBM_REL_RING_MASK_0, 377d5c65159SKalle Valo }; 378d5c65159SKalle Valo 379d5c65159SKalle Valo const u8 ath11k_reo_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { 380d5c65159SKalle Valo ATH11K_REO_STATUS_RING_MASK_0, 381d5c65159SKalle Valo }; 382d5c65159SKalle Valo 383d5c65159SKalle Valo const u8 ath11k_rxdma2host_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { 384d5c65159SKalle Valo ATH11K_RXDMA2HOST_RING_MASK_0, 385d5c65159SKalle Valo ATH11K_RXDMA2HOST_RING_MASK_1, 386d5c65159SKalle Valo ATH11K_RXDMA2HOST_RING_MASK_2, 387d5c65159SKalle Valo }; 388d5c65159SKalle Valo 389d5c65159SKalle Valo const u8 ath11k_host2rxdma_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { 390d5c65159SKalle Valo ATH11K_HOST2RXDMA_RING_MASK_0, 391d5c65159SKalle Valo ATH11K_HOST2RXDMA_RING_MASK_1, 392d5c65159SKalle Valo ATH11K_HOST2RXDMA_RING_MASK_2, 393d5c65159SKalle Valo }; 394d5c65159SKalle Valo 395d5c65159SKalle Valo /* enum ext_irq_num - irq numbers that can be used by external modules 396d5c65159SKalle Valo * like datapath 397d5c65159SKalle Valo */ 398d5c65159SKalle Valo enum ext_irq_num { 399d5c65159SKalle Valo host2wbm_desc_feed = 16, 400d5c65159SKalle Valo host2reo_re_injection, 401d5c65159SKalle Valo host2reo_command, 402d5c65159SKalle Valo host2rxdma_monitor_ring3, 403d5c65159SKalle Valo host2rxdma_monitor_ring2, 404d5c65159SKalle Valo host2rxdma_monitor_ring1, 405d5c65159SKalle Valo reo2host_exception, 406d5c65159SKalle Valo wbm2host_rx_release, 407d5c65159SKalle Valo reo2host_status, 408d5c65159SKalle Valo reo2host_destination_ring4, 409d5c65159SKalle Valo reo2host_destination_ring3, 410d5c65159SKalle Valo reo2host_destination_ring2, 411d5c65159SKalle Valo reo2host_destination_ring1, 412d5c65159SKalle Valo rxdma2host_monitor_destination_mac3, 413d5c65159SKalle Valo rxdma2host_monitor_destination_mac2, 414d5c65159SKalle Valo rxdma2host_monitor_destination_mac1, 415d5c65159SKalle Valo ppdu_end_interrupts_mac3, 416d5c65159SKalle Valo ppdu_end_interrupts_mac2, 417d5c65159SKalle Valo ppdu_end_interrupts_mac1, 418d5c65159SKalle Valo rxdma2host_monitor_status_ring_mac3, 419d5c65159SKalle Valo rxdma2host_monitor_status_ring_mac2, 420d5c65159SKalle Valo rxdma2host_monitor_status_ring_mac1, 421d5c65159SKalle Valo host2rxdma_host_buf_ring_mac3, 422d5c65159SKalle Valo host2rxdma_host_buf_ring_mac2, 423d5c65159SKalle Valo host2rxdma_host_buf_ring_mac1, 424d5c65159SKalle Valo rxdma2host_destination_ring_mac3, 425d5c65159SKalle Valo rxdma2host_destination_ring_mac2, 426d5c65159SKalle Valo rxdma2host_destination_ring_mac1, 427d5c65159SKalle Valo host2tcl_input_ring4, 428d5c65159SKalle Valo host2tcl_input_ring3, 429d5c65159SKalle Valo host2tcl_input_ring2, 430d5c65159SKalle Valo host2tcl_input_ring1, 431d5c65159SKalle Valo wbm2host_tx_completions_ring3, 432d5c65159SKalle Valo wbm2host_tx_completions_ring2, 433d5c65159SKalle Valo wbm2host_tx_completions_ring1, 434d5c65159SKalle Valo tcl2host_status_ring, 435d5c65159SKalle Valo }; 436d5c65159SKalle Valo 437d5c65159SKalle Valo static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab) 438d5c65159SKalle Valo { 439d5c65159SKalle Valo int i; 440d5c65159SKalle Valo 441d5c65159SKalle Valo for (i = 0; i < CE_COUNT; i++) { 442d5c65159SKalle Valo struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i]; 443d5c65159SKalle Valo 444d5c65159SKalle Valo if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) 445d5c65159SKalle Valo continue; 446d5c65159SKalle Valo 447d5c65159SKalle Valo tasklet_kill(&ce_pipe->intr_tq); 448d5c65159SKalle Valo } 449d5c65159SKalle Valo } 450d5c65159SKalle Valo 451d5c65159SKalle Valo static void ath11k_ahb_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp) 452d5c65159SKalle Valo { 453d5c65159SKalle Valo int i; 454d5c65159SKalle Valo 455d5c65159SKalle Valo for (i = 0; i < irq_grp->num_irq; i++) 456d5c65159SKalle Valo disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]); 457d5c65159SKalle Valo } 458d5c65159SKalle Valo 459d5c65159SKalle Valo static void __ath11k_ahb_ext_irq_disable(struct ath11k_base *ab) 460d5c65159SKalle Valo { 461d5c65159SKalle Valo struct sk_buff *skb; 462d5c65159SKalle Valo int i; 463d5c65159SKalle Valo 464d5c65159SKalle Valo for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { 465d5c65159SKalle Valo struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; 466d5c65159SKalle Valo 467d5c65159SKalle Valo ath11k_ahb_ext_grp_disable(irq_grp); 468d5c65159SKalle Valo 469d5c65159SKalle Valo napi_synchronize(&irq_grp->napi); 470d5c65159SKalle Valo napi_disable(&irq_grp->napi); 471d5c65159SKalle Valo 472d5c65159SKalle Valo while ((skb = __skb_dequeue(&irq_grp->pending_q))) 473d5c65159SKalle Valo dev_kfree_skb_any(skb); 474d5c65159SKalle Valo } 475d5c65159SKalle Valo } 476d5c65159SKalle Valo 477d5c65159SKalle Valo static void ath11k_ahb_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp) 478d5c65159SKalle Valo { 479d5c65159SKalle Valo int i; 480d5c65159SKalle Valo 481d5c65159SKalle Valo for (i = 0; i < irq_grp->num_irq; i++) 482d5c65159SKalle Valo enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]); 483d5c65159SKalle Valo } 484d5c65159SKalle Valo 485d5c65159SKalle Valo static void ath11k_ahb_setbit32(struct ath11k_base *ab, u8 bit, u32 offset) 486d5c65159SKalle Valo { 487d5c65159SKalle Valo u32 val; 488d5c65159SKalle Valo 489d5c65159SKalle Valo val = ath11k_ahb_read32(ab, offset); 490d5c65159SKalle Valo ath11k_ahb_write32(ab, offset, val | BIT(bit)); 491d5c65159SKalle Valo } 492d5c65159SKalle Valo 493d5c65159SKalle Valo static void ath11k_ahb_clearbit32(struct ath11k_base *ab, u8 bit, u32 offset) 494d5c65159SKalle Valo { 495d5c65159SKalle Valo u32 val; 496d5c65159SKalle Valo 497d5c65159SKalle Valo val = ath11k_ahb_read32(ab, offset); 498d5c65159SKalle Valo ath11k_ahb_write32(ab, offset, val & ~BIT(bit)); 499d5c65159SKalle Valo } 500d5c65159SKalle Valo 501d5c65159SKalle Valo static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id) 502d5c65159SKalle Valo { 503d5c65159SKalle Valo const struct ce_pipe_config *ce_config; 504d5c65159SKalle Valo 505d5c65159SKalle Valo ce_config = &target_ce_config_wlan[ce_id]; 506d5c65159SKalle Valo if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT) 507d5c65159SKalle Valo ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS); 508d5c65159SKalle Valo 509d5c65159SKalle Valo if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) { 510d5c65159SKalle Valo ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS); 511d5c65159SKalle Valo ath11k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT, 512d5c65159SKalle Valo CE_HOST_IE_3_ADDRESS); 513d5c65159SKalle Valo } 514d5c65159SKalle Valo } 515d5c65159SKalle Valo 516d5c65159SKalle Valo static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id) 517d5c65159SKalle Valo { 518d5c65159SKalle Valo const struct ce_pipe_config *ce_config; 519d5c65159SKalle Valo 520d5c65159SKalle Valo ce_config = &target_ce_config_wlan[ce_id]; 521d5c65159SKalle Valo if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT) 522d5c65159SKalle Valo ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS); 523d5c65159SKalle Valo 524d5c65159SKalle Valo if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) { 525d5c65159SKalle Valo ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS); 526d5c65159SKalle Valo ath11k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT, 527d5c65159SKalle Valo CE_HOST_IE_3_ADDRESS); 528d5c65159SKalle Valo } 529d5c65159SKalle Valo } 530d5c65159SKalle Valo 531d5c65159SKalle Valo static void ath11k_ahb_sync_ce_irqs(struct ath11k_base *ab) 532d5c65159SKalle Valo { 533d5c65159SKalle Valo int i; 534d5c65159SKalle Valo int irq_idx; 535d5c65159SKalle Valo 536d5c65159SKalle Valo for (i = 0; i < CE_COUNT; i++) { 537d5c65159SKalle Valo if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) 538d5c65159SKalle Valo continue; 539d5c65159SKalle Valo 540d5c65159SKalle Valo irq_idx = ATH11K_IRQ_CE0_OFFSET + i; 541d5c65159SKalle Valo synchronize_irq(ab->irq_num[irq_idx]); 542d5c65159SKalle Valo } 543d5c65159SKalle Valo } 544d5c65159SKalle Valo 545d5c65159SKalle Valo static void ath11k_ahb_sync_ext_irqs(struct ath11k_base *ab) 546d5c65159SKalle Valo { 547d5c65159SKalle Valo int i, j; 548d5c65159SKalle Valo int irq_idx; 549d5c65159SKalle Valo 550d5c65159SKalle Valo for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { 551d5c65159SKalle Valo struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; 552d5c65159SKalle Valo 553d5c65159SKalle Valo for (j = 0; j < irq_grp->num_irq; j++) { 554d5c65159SKalle Valo irq_idx = irq_grp->irqs[j]; 555d5c65159SKalle Valo synchronize_irq(ab->irq_num[irq_idx]); 556d5c65159SKalle Valo } 557d5c65159SKalle Valo } 558d5c65159SKalle Valo } 559d5c65159SKalle Valo 560d5c65159SKalle Valo static void ath11k_ahb_ce_irqs_enable(struct ath11k_base *ab) 561d5c65159SKalle Valo { 562d5c65159SKalle Valo int i; 563d5c65159SKalle Valo 564d5c65159SKalle Valo for (i = 0; i < CE_COUNT; i++) { 565d5c65159SKalle Valo if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) 566d5c65159SKalle Valo continue; 567d5c65159SKalle Valo ath11k_ahb_ce_irq_enable(ab, i); 568d5c65159SKalle Valo } 569d5c65159SKalle Valo } 570d5c65159SKalle Valo 571d5c65159SKalle Valo static void ath11k_ahb_ce_irqs_disable(struct ath11k_base *ab) 572d5c65159SKalle Valo { 573d5c65159SKalle Valo int i; 574d5c65159SKalle Valo 575d5c65159SKalle Valo for (i = 0; i < CE_COUNT; i++) { 576d5c65159SKalle Valo if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) 577d5c65159SKalle Valo continue; 578d5c65159SKalle Valo ath11k_ahb_ce_irq_disable(ab, i); 579d5c65159SKalle Valo } 580d5c65159SKalle Valo } 581d5c65159SKalle Valo 582d5c65159SKalle Valo int ath11k_ahb_start(struct ath11k_base *ab) 583d5c65159SKalle Valo { 584d5c65159SKalle Valo ath11k_ahb_ce_irqs_enable(ab); 585d5c65159SKalle Valo ath11k_ce_rx_post_buf(ab); 586d5c65159SKalle Valo 587d5c65159SKalle Valo return 0; 588d5c65159SKalle Valo } 589d5c65159SKalle Valo 590d5c65159SKalle Valo void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab) 591d5c65159SKalle Valo { 592d5c65159SKalle Valo int i; 593d5c65159SKalle Valo 594d5c65159SKalle Valo for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { 595d5c65159SKalle Valo struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; 596d5c65159SKalle Valo 597d5c65159SKalle Valo napi_enable(&irq_grp->napi); 598d5c65159SKalle Valo ath11k_ahb_ext_grp_enable(irq_grp); 599d5c65159SKalle Valo } 600d5c65159SKalle Valo } 601d5c65159SKalle Valo 602d5c65159SKalle Valo void ath11k_ahb_ext_irq_disable(struct ath11k_base *ab) 603d5c65159SKalle Valo { 604d5c65159SKalle Valo __ath11k_ahb_ext_irq_disable(ab); 605d5c65159SKalle Valo ath11k_ahb_sync_ext_irqs(ab); 606d5c65159SKalle Valo } 607d5c65159SKalle Valo 608d5c65159SKalle Valo void ath11k_ahb_stop(struct ath11k_base *ab) 609d5c65159SKalle Valo { 610d5c65159SKalle Valo if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags)) 611d5c65159SKalle Valo ath11k_ahb_ce_irqs_disable(ab); 612d5c65159SKalle Valo ath11k_ahb_sync_ce_irqs(ab); 613d5c65159SKalle Valo ath11k_ahb_kill_tasklets(ab); 614d5c65159SKalle Valo del_timer_sync(&ab->rx_replenish_retry); 615d5c65159SKalle Valo ath11k_ce_cleanup_pipes(ab); 616d5c65159SKalle Valo } 617d5c65159SKalle Valo 618d5c65159SKalle Valo int ath11k_ahb_power_up(struct ath11k_base *ab) 619d5c65159SKalle Valo { 620d5c65159SKalle Valo int ret; 621d5c65159SKalle Valo 622d5c65159SKalle Valo ret = rproc_boot(ab->tgt_rproc); 623d5c65159SKalle Valo if (ret) 624d5c65159SKalle Valo ath11k_err(ab, "failed to boot the remote processor Q6\n"); 625d5c65159SKalle Valo 626d5c65159SKalle Valo return ret; 627d5c65159SKalle Valo } 628d5c65159SKalle Valo 629d5c65159SKalle Valo void ath11k_ahb_power_down(struct ath11k_base *ab) 630d5c65159SKalle Valo { 631d5c65159SKalle Valo rproc_shutdown(ab->tgt_rproc); 632d5c65159SKalle Valo } 633d5c65159SKalle Valo 634d5c65159SKalle Valo static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab) 635d5c65159SKalle Valo { 636d5c65159SKalle Valo struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg; 637d5c65159SKalle Valo 638d6af906dSAnilkumar Kolli cfg->tgt_ce_len = ARRAY_SIZE(target_ce_config_wlan) - 1; 639d6af906dSAnilkumar Kolli cfg->tgt_ce = target_ce_config_wlan; 640d6af906dSAnilkumar Kolli cfg->svc_to_ce_map_len = ARRAY_SIZE(target_service_to_ce_map_wlan); 641d6af906dSAnilkumar Kolli cfg->svc_to_ce_map = target_service_to_ce_map_wlan; 642d5c65159SKalle Valo } 643d5c65159SKalle Valo 644d5c65159SKalle Valo static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab) 645d5c65159SKalle Valo { 646d5c65159SKalle Valo int i, j; 647d5c65159SKalle Valo 648d5c65159SKalle Valo for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { 649d5c65159SKalle Valo struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; 650d5c65159SKalle Valo 651d5c65159SKalle Valo for (j = 0; j < irq_grp->num_irq; j++) 652d5c65159SKalle Valo free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp); 653d5c65159SKalle Valo } 654d5c65159SKalle Valo } 655d5c65159SKalle Valo 656d5c65159SKalle Valo static void ath11k_ahb_free_irq(struct ath11k_base *ab) 657d5c65159SKalle Valo { 658d5c65159SKalle Valo int irq_idx; 659d5c65159SKalle Valo int i; 660d5c65159SKalle Valo 661d5c65159SKalle Valo for (i = 0; i < CE_COUNT; i++) { 662d5c65159SKalle Valo if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) 663d5c65159SKalle Valo continue; 664d5c65159SKalle Valo irq_idx = ATH11K_IRQ_CE0_OFFSET + i; 665d5c65159SKalle Valo free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]); 666d5c65159SKalle Valo } 667d5c65159SKalle Valo 668d5c65159SKalle Valo ath11k_ahb_free_ext_irq(ab); 669d5c65159SKalle Valo } 670d5c65159SKalle Valo 671d5c65159SKalle Valo static void ath11k_ahb_ce_tasklet(unsigned long data) 672d5c65159SKalle Valo { 673d5c65159SKalle Valo struct ath11k_ce_pipe *ce_pipe = (struct ath11k_ce_pipe *)data; 674d5c65159SKalle Valo 675d5c65159SKalle Valo ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num); 676d5c65159SKalle Valo 677d5c65159SKalle Valo ath11k_ahb_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num); 678d5c65159SKalle Valo } 679d5c65159SKalle Valo 680d5c65159SKalle Valo static irqreturn_t ath11k_ahb_ce_interrupt_handler(int irq, void *arg) 681d5c65159SKalle Valo { 682d5c65159SKalle Valo struct ath11k_ce_pipe *ce_pipe = arg; 683d5c65159SKalle Valo 684d5c65159SKalle Valo ath11k_ahb_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num); 685d5c65159SKalle Valo 686d5c65159SKalle Valo tasklet_schedule(&ce_pipe->intr_tq); 687d5c65159SKalle Valo 688d5c65159SKalle Valo return IRQ_HANDLED; 689d5c65159SKalle Valo } 690d5c65159SKalle Valo 691d5c65159SKalle Valo static int ath11k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget) 692d5c65159SKalle Valo { 693d5c65159SKalle Valo struct ath11k_ext_irq_grp *irq_grp = container_of(napi, 694d5c65159SKalle Valo struct ath11k_ext_irq_grp, 695d5c65159SKalle Valo napi); 696d5c65159SKalle Valo struct ath11k_base *ab = irq_grp->ab; 697d5c65159SKalle Valo int work_done; 698d5c65159SKalle Valo 699d5c65159SKalle Valo work_done = ath11k_dp_service_srng(ab, irq_grp, budget); 700d5c65159SKalle Valo if (work_done < budget) { 701d5c65159SKalle Valo napi_complete_done(napi, work_done); 702d5c65159SKalle Valo ath11k_ahb_ext_grp_enable(irq_grp); 703d5c65159SKalle Valo } 704d5c65159SKalle Valo 705d5c65159SKalle Valo if (work_done > budget) 706d5c65159SKalle Valo work_done = budget; 707d5c65159SKalle Valo 708d5c65159SKalle Valo return work_done; 709d5c65159SKalle Valo } 710d5c65159SKalle Valo 711d5c65159SKalle Valo static irqreturn_t ath11k_ahb_ext_interrupt_handler(int irq, void *arg) 712d5c65159SKalle Valo { 713d5c65159SKalle Valo struct ath11k_ext_irq_grp *irq_grp = arg; 714d5c65159SKalle Valo 715d5c65159SKalle Valo ath11k_ahb_ext_grp_disable(irq_grp); 716d5c65159SKalle Valo 717d5c65159SKalle Valo napi_schedule(&irq_grp->napi); 718d5c65159SKalle Valo 719d5c65159SKalle Valo return IRQ_HANDLED; 720d5c65159SKalle Valo } 721d5c65159SKalle Valo 722d5c65159SKalle Valo static int ath11k_ahb_ext_irq_config(struct ath11k_base *ab) 723d5c65159SKalle Valo { 724d5c65159SKalle Valo int i, j; 725d5c65159SKalle Valo int irq; 726d5c65159SKalle Valo int ret; 727d5c65159SKalle Valo 728d5c65159SKalle Valo for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { 729d5c65159SKalle Valo struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; 730d5c65159SKalle Valo u32 num_irq = 0; 731d5c65159SKalle Valo 732d5c65159SKalle Valo irq_grp->ab = ab; 733d5c65159SKalle Valo irq_grp->grp_id = i; 734d5c65159SKalle Valo init_dummy_netdev(&irq_grp->napi_ndev); 735d5c65159SKalle Valo netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, 736d5c65159SKalle Valo ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT); 737d5c65159SKalle Valo __skb_queue_head_init(&irq_grp->pending_q); 738d5c65159SKalle Valo 739d5c65159SKalle Valo for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) { 740d5c65159SKalle Valo if (ath11k_tx_ring_mask[i] & BIT(j)) { 741d5c65159SKalle Valo irq_grp->irqs[num_irq++] = 742d5c65159SKalle Valo wbm2host_tx_completions_ring1 - j; 743d5c65159SKalle Valo } 744d5c65159SKalle Valo 745d5c65159SKalle Valo if (ath11k_rx_ring_mask[i] & BIT(j)) { 746d5c65159SKalle Valo irq_grp->irqs[num_irq++] = 747d5c65159SKalle Valo reo2host_destination_ring1 - j; 748d5c65159SKalle Valo } 749d5c65159SKalle Valo 750d5c65159SKalle Valo if (ath11k_rx_err_ring_mask[i] & BIT(j)) 751d5c65159SKalle Valo irq_grp->irqs[num_irq++] = reo2host_exception; 752d5c65159SKalle Valo 753d5c65159SKalle Valo if (ath11k_rx_wbm_rel_ring_mask[i] & BIT(j)) 754d5c65159SKalle Valo irq_grp->irqs[num_irq++] = wbm2host_rx_release; 755d5c65159SKalle Valo 756d5c65159SKalle Valo if (ath11k_reo_status_ring_mask[i] & BIT(j)) 757d5c65159SKalle Valo irq_grp->irqs[num_irq++] = reo2host_status; 758d5c65159SKalle Valo 759d5c65159SKalle Valo if (j < MAX_RADIOS) { 760d5c65159SKalle Valo if (ath11k_rxdma2host_ring_mask[i] & BIT(j)) { 761d5c65159SKalle Valo irq_grp->irqs[num_irq++] = 762d5c65159SKalle Valo rxdma2host_destination_ring_mac1 763d5c65159SKalle Valo - ath11k_core_get_hw_mac_id(ab, j); 764d5c65159SKalle Valo } 765d5c65159SKalle Valo 766d5c65159SKalle Valo if (ath11k_host2rxdma_ring_mask[i] & BIT(j)) { 767d5c65159SKalle Valo irq_grp->irqs[num_irq++] = 768d5c65159SKalle Valo host2rxdma_host_buf_ring_mac1 769d5c65159SKalle Valo - ath11k_core_get_hw_mac_id(ab, j); 770d5c65159SKalle Valo } 771d5c65159SKalle Valo 772d5c65159SKalle Valo if (rx_mon_status_ring_mask[i] & BIT(j)) { 773d5c65159SKalle Valo irq_grp->irqs[num_irq++] = 774d5c65159SKalle Valo ppdu_end_interrupts_mac1 - 775d5c65159SKalle Valo ath11k_core_get_hw_mac_id(ab, j); 776d5c65159SKalle Valo irq_grp->irqs[num_irq++] = 777d5c65159SKalle Valo rxdma2host_monitor_status_ring_mac1 - 778d5c65159SKalle Valo ath11k_core_get_hw_mac_id(ab, j); 779d5c65159SKalle Valo } 780d5c65159SKalle Valo } 781d5c65159SKalle Valo } 782d5c65159SKalle Valo irq_grp->num_irq = num_irq; 783d5c65159SKalle Valo 784d5c65159SKalle Valo for (j = 0; j < irq_grp->num_irq; j++) { 785d5c65159SKalle Valo int irq_idx = irq_grp->irqs[j]; 786d5c65159SKalle Valo 787d5c65159SKalle Valo irq = platform_get_irq_byname(ab->pdev, 788d5c65159SKalle Valo irq_name[irq_idx]); 789d5c65159SKalle Valo ab->irq_num[irq_idx] = irq; 790d5c65159SKalle Valo irq_set_status_flags(irq, IRQ_NOAUTOEN); 791d5c65159SKalle Valo ret = request_irq(irq, ath11k_ahb_ext_interrupt_handler, 792d5c65159SKalle Valo IRQF_TRIGGER_RISING, 793d5c65159SKalle Valo irq_name[irq_idx], irq_grp); 794d5c65159SKalle Valo if (ret) { 795d5c65159SKalle Valo ath11k_err(ab, "failed request_irq for %d\n", 796d5c65159SKalle Valo irq); 797d5c65159SKalle Valo } 798d5c65159SKalle Valo } 799d5c65159SKalle Valo } 800d5c65159SKalle Valo 801d5c65159SKalle Valo return 0; 802d5c65159SKalle Valo } 803d5c65159SKalle Valo 804d5c65159SKalle Valo static int ath11k_ahb_config_irq(struct ath11k_base *ab) 805d5c65159SKalle Valo { 806d5c65159SKalle Valo int irq, irq_idx, i; 807d5c65159SKalle Valo int ret; 808d5c65159SKalle Valo 809d5c65159SKalle Valo /* Configure CE irqs */ 810d5c65159SKalle Valo for (i = 0; i < CE_COUNT; i++) { 811d5c65159SKalle Valo struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i]; 812d5c65159SKalle Valo 813d5c65159SKalle Valo if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) 814d5c65159SKalle Valo continue; 815d5c65159SKalle Valo 816d5c65159SKalle Valo irq_idx = ATH11K_IRQ_CE0_OFFSET + i; 817d5c65159SKalle Valo 818d5c65159SKalle Valo tasklet_init(&ce_pipe->intr_tq, ath11k_ahb_ce_tasklet, 819d5c65159SKalle Valo (unsigned long)ce_pipe); 820d5c65159SKalle Valo irq = platform_get_irq_byname(ab->pdev, irq_name[irq_idx]); 821d5c65159SKalle Valo ret = request_irq(irq, ath11k_ahb_ce_interrupt_handler, 822d5c65159SKalle Valo IRQF_TRIGGER_RISING, irq_name[irq_idx], 823d5c65159SKalle Valo ce_pipe); 824d5c65159SKalle Valo if (ret) 825d5c65159SKalle Valo return ret; 826d5c65159SKalle Valo 827d5c65159SKalle Valo ab->irq_num[irq_idx] = irq; 828d5c65159SKalle Valo } 829d5c65159SKalle Valo 830d5c65159SKalle Valo /* Configure external interrupts */ 831d5c65159SKalle Valo ret = ath11k_ahb_ext_irq_config(ab); 832d5c65159SKalle Valo 833d5c65159SKalle Valo return ret; 834d5c65159SKalle Valo } 835d5c65159SKalle Valo 836d5c65159SKalle Valo int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id, 837d5c65159SKalle Valo u8 *ul_pipe, u8 *dl_pipe) 838d5c65159SKalle Valo { 839d5c65159SKalle Valo const struct service_to_pipe *entry; 840d5c65159SKalle Valo bool ul_set = false, dl_set = false; 841d5c65159SKalle Valo int i; 842d5c65159SKalle Valo 843d5c65159SKalle Valo for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) { 844d5c65159SKalle Valo entry = &target_service_to_ce_map_wlan[i]; 845d5c65159SKalle Valo 846d5c65159SKalle Valo if (__le32_to_cpu(entry->service_id) != service_id) 847d5c65159SKalle Valo continue; 848d5c65159SKalle Valo 849d5c65159SKalle Valo switch (__le32_to_cpu(entry->pipedir)) { 850d5c65159SKalle Valo case PIPEDIR_NONE: 851d5c65159SKalle Valo break; 852d5c65159SKalle Valo case PIPEDIR_IN: 853d5c65159SKalle Valo WARN_ON(dl_set); 854d5c65159SKalle Valo *dl_pipe = __le32_to_cpu(entry->pipenum); 855d5c65159SKalle Valo dl_set = true; 856d5c65159SKalle Valo break; 857d5c65159SKalle Valo case PIPEDIR_OUT: 858d5c65159SKalle Valo WARN_ON(ul_set); 859d5c65159SKalle Valo *ul_pipe = __le32_to_cpu(entry->pipenum); 860d5c65159SKalle Valo ul_set = true; 861d5c65159SKalle Valo break; 862d5c65159SKalle Valo case PIPEDIR_INOUT: 863d5c65159SKalle Valo WARN_ON(dl_set); 864d5c65159SKalle Valo WARN_ON(ul_set); 865d5c65159SKalle Valo *dl_pipe = __le32_to_cpu(entry->pipenum); 866d5c65159SKalle Valo *ul_pipe = __le32_to_cpu(entry->pipenum); 867d5c65159SKalle Valo dl_set = true; 868d5c65159SKalle Valo ul_set = true; 869d5c65159SKalle Valo break; 870d5c65159SKalle Valo } 871d5c65159SKalle Valo } 872d5c65159SKalle Valo 873d5c65159SKalle Valo if (WARN_ON(!ul_set || !dl_set)) 874d5c65159SKalle Valo return -ENOENT; 875d5c65159SKalle Valo 876d5c65159SKalle Valo return 0; 877d5c65159SKalle Valo } 878d5c65159SKalle Valo 879d5c65159SKalle Valo static int ath11k_ahb_probe(struct platform_device *pdev) 880d5c65159SKalle Valo { 881d5c65159SKalle Valo struct ath11k_base *ab; 882d5c65159SKalle Valo const struct of_device_id *of_id; 883d5c65159SKalle Valo struct resource *mem_res; 884d5c65159SKalle Valo void __iomem *mem; 885d5c65159SKalle Valo int ret; 886d5c65159SKalle Valo 887d5c65159SKalle Valo of_id = of_match_device(ath11k_ahb_of_match, &pdev->dev); 888d5c65159SKalle Valo if (!of_id) { 889d5c65159SKalle Valo dev_err(&pdev->dev, "failed to find matching device tree id\n"); 890d5c65159SKalle Valo return -EINVAL; 891d5c65159SKalle Valo } 892d5c65159SKalle Valo 893d5c65159SKalle Valo mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 894d5c65159SKalle Valo if (!mem_res) { 895d5c65159SKalle Valo dev_err(&pdev->dev, "failed to get IO memory resource\n"); 896d5c65159SKalle Valo return -ENXIO; 897d5c65159SKalle Valo } 898d5c65159SKalle Valo 899d5c65159SKalle Valo mem = devm_ioremap_resource(&pdev->dev, mem_res); 900d5c65159SKalle Valo if (IS_ERR(mem)) { 901d5c65159SKalle Valo dev_err(&pdev->dev, "ioremap error\n"); 902d5c65159SKalle Valo return PTR_ERR(mem); 903d5c65159SKalle Valo } 904d5c65159SKalle Valo 905d5c65159SKalle Valo ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 906d5c65159SKalle Valo if (ret) { 907d5c65159SKalle Valo dev_err(&pdev->dev, "failed to set 32-bit consistent dma\n"); 908d5c65159SKalle Valo return ret; 909d5c65159SKalle Valo } 910d5c65159SKalle Valo 911d5c65159SKalle Valo ab = ath11k_core_alloc(&pdev->dev); 912d5c65159SKalle Valo if (!ab) { 913d5c65159SKalle Valo dev_err(&pdev->dev, "failed to allocate ath11k base\n"); 914d5c65159SKalle Valo return -ENOMEM; 915d5c65159SKalle Valo } 916d5c65159SKalle Valo 917d5c65159SKalle Valo ab->pdev = pdev; 918d5c65159SKalle Valo ab->hw_rev = (enum ath11k_hw_rev)of_id->data; 919d5c65159SKalle Valo ab->mem = mem; 920d5c65159SKalle Valo ab->mem_len = resource_size(mem_res); 921d5c65159SKalle Valo platform_set_drvdata(pdev, ab); 922d5c65159SKalle Valo 923d5c65159SKalle Valo ret = ath11k_hal_srng_init(ab); 924d5c65159SKalle Valo if (ret) 925d5c65159SKalle Valo goto err_core_free; 926d5c65159SKalle Valo 927d5c65159SKalle Valo ret = ath11k_ce_alloc_pipes(ab); 928d5c65159SKalle Valo if (ret) { 929d5c65159SKalle Valo ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret); 930d5c65159SKalle Valo goto err_hal_srng_deinit; 931d5c65159SKalle Valo } 932d5c65159SKalle Valo 933d5c65159SKalle Valo ath11k_ahb_init_qmi_ce_config(ab); 934d5c65159SKalle Valo 935d5c65159SKalle Valo ret = ath11k_ahb_config_irq(ab); 936d5c65159SKalle Valo if (ret) { 937d5c65159SKalle Valo ath11k_err(ab, "failed to configure irq: %d\n", ret); 938d5c65159SKalle Valo goto err_ce_free; 939d5c65159SKalle Valo } 940d5c65159SKalle Valo 941d5c65159SKalle Valo ret = ath11k_core_init(ab); 942d5c65159SKalle Valo if (ret) { 943d5c65159SKalle Valo ath11k_err(ab, "failed to init core: %d\n", ret); 944d5c65159SKalle Valo goto err_ce_free; 945d5c65159SKalle Valo } 946d5c65159SKalle Valo 947d5c65159SKalle Valo return 0; 948d5c65159SKalle Valo 949d5c65159SKalle Valo err_ce_free: 950d5c65159SKalle Valo ath11k_ce_free_pipes(ab); 951d5c65159SKalle Valo 952d5c65159SKalle Valo err_hal_srng_deinit: 953d5c65159SKalle Valo ath11k_hal_srng_deinit(ab); 954d5c65159SKalle Valo 955d5c65159SKalle Valo err_core_free: 956d5c65159SKalle Valo ath11k_core_free(ab); 957d5c65159SKalle Valo platform_set_drvdata(pdev, NULL); 958d5c65159SKalle Valo 959d5c65159SKalle Valo return ret; 960d5c65159SKalle Valo } 961d5c65159SKalle Valo 962d5c65159SKalle Valo static int ath11k_ahb_remove(struct platform_device *pdev) 963d5c65159SKalle Valo { 964d5c65159SKalle Valo struct ath11k_base *ab = platform_get_drvdata(pdev); 965d5c65159SKalle Valo 966d5c65159SKalle Valo reinit_completion(&ab->driver_recovery); 967d5c65159SKalle Valo 968d5c65159SKalle Valo if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags)) 969d5c65159SKalle Valo wait_for_completion_timeout(&ab->driver_recovery, 970d5c65159SKalle Valo ATH11K_AHB_RECOVERY_TIMEOUT); 971d5c65159SKalle Valo 972d5c65159SKalle Valo set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags); 973d5c65159SKalle Valo cancel_work_sync(&ab->restart_work); 974d5c65159SKalle Valo 975d5c65159SKalle Valo ath11k_core_deinit(ab); 976d5c65159SKalle Valo ath11k_ahb_free_irq(ab); 977d5c65159SKalle Valo 978d5c65159SKalle Valo ath11k_hal_srng_deinit(ab); 979d5c65159SKalle Valo ath11k_ce_free_pipes(ab); 980d5c65159SKalle Valo ath11k_core_free(ab); 981d5c65159SKalle Valo platform_set_drvdata(pdev, NULL); 982d5c65159SKalle Valo 983d5c65159SKalle Valo return 0; 984d5c65159SKalle Valo } 985d5c65159SKalle Valo 986d5c65159SKalle Valo static struct platform_driver ath11k_ahb_driver = { 987d5c65159SKalle Valo .driver = { 988d5c65159SKalle Valo .name = "ath11k", 989d5c65159SKalle Valo .of_match_table = ath11k_ahb_of_match, 990d5c65159SKalle Valo }, 991d5c65159SKalle Valo .probe = ath11k_ahb_probe, 992d5c65159SKalle Valo .remove = ath11k_ahb_remove, 993d5c65159SKalle Valo }; 994d5c65159SKalle Valo 995d5c65159SKalle Valo int ath11k_ahb_init(void) 996d5c65159SKalle Valo { 997d5c65159SKalle Valo return platform_driver_register(&ath11k_ahb_driver); 998d5c65159SKalle Valo } 999d5c65159SKalle Valo 1000d5c65159SKalle Valo void ath11k_ahb_exit(void) 1001d5c65159SKalle Valo { 1002d5c65159SKalle Valo platform_driver_unregister(&ath11k_ahb_driver); 1003d5c65159SKalle Valo } 1004