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