linux/drivers/net/wireless/ath/ath11k/mhi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause-Clear
   2/* Copyright (c) 2020 The Linux Foundation. All rights reserved. */
   3
   4#include <linux/msi.h>
   5#include <linux/pci.h>
   6
   7#include "core.h"
   8#include "debug.h"
   9#include "mhi.h"
  10#include "pci.h"
  11
  12#define MHI_TIMEOUT_DEFAULT_MS  90000
  13
  14static struct mhi_channel_config ath11k_mhi_channels_qca6390[] = {
  15        {
  16                .num = 0,
  17                .name = "LOOPBACK",
  18                .num_elements = 32,
  19                .event_ring = 0,
  20                .dir = DMA_TO_DEVICE,
  21                .ee_mask = 0x4,
  22                .pollcfg = 0,
  23                .doorbell = MHI_DB_BRST_DISABLE,
  24                .lpm_notify = false,
  25                .offload_channel = false,
  26                .doorbell_mode_switch = false,
  27                .auto_queue = false,
  28        },
  29        {
  30                .num = 1,
  31                .name = "LOOPBACK",
  32                .num_elements = 32,
  33                .event_ring = 0,
  34                .dir = DMA_FROM_DEVICE,
  35                .ee_mask = 0x4,
  36                .pollcfg = 0,
  37                .doorbell = MHI_DB_BRST_DISABLE,
  38                .lpm_notify = false,
  39                .offload_channel = false,
  40                .doorbell_mode_switch = false,
  41                .auto_queue = false,
  42        },
  43        {
  44                .num = 20,
  45                .name = "IPCR",
  46                .num_elements = 64,
  47                .event_ring = 1,
  48                .dir = DMA_TO_DEVICE,
  49                .ee_mask = 0x4,
  50                .pollcfg = 0,
  51                .doorbell = MHI_DB_BRST_DISABLE,
  52                .lpm_notify = false,
  53                .offload_channel = false,
  54                .doorbell_mode_switch = false,
  55                .auto_queue = false,
  56        },
  57        {
  58                .num = 21,
  59                .name = "IPCR",
  60                .num_elements = 64,
  61                .event_ring = 1,
  62                .dir = DMA_FROM_DEVICE,
  63                .ee_mask = 0x4,
  64                .pollcfg = 0,
  65                .doorbell = MHI_DB_BRST_DISABLE,
  66                .lpm_notify = false,
  67                .offload_channel = false,
  68                .doorbell_mode_switch = false,
  69                .auto_queue = true,
  70        },
  71};
  72
  73static struct mhi_event_config ath11k_mhi_events_qca6390[] = {
  74        {
  75                .num_elements = 32,
  76                .irq_moderation_ms = 0,
  77                .irq = 1,
  78                .mode = MHI_DB_BRST_DISABLE,
  79                .data_type = MHI_ER_CTRL,
  80                .hardware_event = false,
  81                .client_managed = false,
  82                .offload_channel = false,
  83        },
  84        {
  85                .num_elements = 256,
  86                .irq_moderation_ms = 1,
  87                .irq = 2,
  88                .mode = MHI_DB_BRST_DISABLE,
  89                .priority = 1,
  90                .hardware_event = false,
  91                .client_managed = false,
  92                .offload_channel = false,
  93        },
  94};
  95
  96static struct mhi_controller_config ath11k_mhi_config_qca6390 = {
  97        .max_channels = 128,
  98        .timeout_ms = 2000,
  99        .use_bounce_buf = false,
 100        .buf_len = 0,
 101        .num_channels = ARRAY_SIZE(ath11k_mhi_channels_qca6390),
 102        .ch_cfg = ath11k_mhi_channels_qca6390,
 103        .num_events = ARRAY_SIZE(ath11k_mhi_events_qca6390),
 104        .event_cfg = ath11k_mhi_events_qca6390,
 105};
 106
 107static struct mhi_channel_config ath11k_mhi_channels_qcn9074[] = {
 108        {
 109                .num = 0,
 110                .name = "LOOPBACK",
 111                .num_elements = 32,
 112                .event_ring = 1,
 113                .dir = DMA_TO_DEVICE,
 114                .ee_mask = 0x14,
 115                .pollcfg = 0,
 116                .doorbell = MHI_DB_BRST_DISABLE,
 117                .lpm_notify = false,
 118                .offload_channel = false,
 119                .doorbell_mode_switch = false,
 120                .auto_queue = false,
 121        },
 122        {
 123                .num = 1,
 124                .name = "LOOPBACK",
 125                .num_elements = 32,
 126                .event_ring = 1,
 127                .dir = DMA_FROM_DEVICE,
 128                .ee_mask = 0x14,
 129                .pollcfg = 0,
 130                .doorbell = MHI_DB_BRST_DISABLE,
 131                .lpm_notify = false,
 132                .offload_channel = false,
 133                .doorbell_mode_switch = false,
 134                .auto_queue = false,
 135        },
 136        {
 137                .num = 20,
 138                .name = "IPCR",
 139                .num_elements = 32,
 140                .event_ring = 1,
 141                .dir = DMA_TO_DEVICE,
 142                .ee_mask = 0x14,
 143                .pollcfg = 0,
 144                .doorbell = MHI_DB_BRST_DISABLE,
 145                .lpm_notify = false,
 146                .offload_channel = false,
 147                .doorbell_mode_switch = false,
 148                .auto_queue = false,
 149        },
 150        {
 151                .num = 21,
 152                .name = "IPCR",
 153                .num_elements = 32,
 154                .event_ring = 1,
 155                .dir = DMA_FROM_DEVICE,
 156                .ee_mask = 0x14,
 157                .pollcfg = 0,
 158                .doorbell = MHI_DB_BRST_DISABLE,
 159                .lpm_notify = false,
 160                .offload_channel = false,
 161                .doorbell_mode_switch = false,
 162                .auto_queue = true,
 163        },
 164};
 165
 166static struct mhi_event_config ath11k_mhi_events_qcn9074[] = {
 167        {
 168                .num_elements = 32,
 169                .irq_moderation_ms = 0,
 170                .irq = 1,
 171                .data_type = MHI_ER_CTRL,
 172                .mode = MHI_DB_BRST_DISABLE,
 173                .hardware_event = false,
 174                .client_managed = false,
 175                .offload_channel = false,
 176        },
 177        {
 178                .num_elements = 256,
 179                .irq_moderation_ms = 1,
 180                .irq = 2,
 181                .mode = MHI_DB_BRST_DISABLE,
 182                .priority = 1,
 183                .hardware_event = false,
 184                .client_managed = false,
 185                .offload_channel = false,
 186        },
 187};
 188
 189static struct mhi_controller_config ath11k_mhi_config_qcn9074 = {
 190        .max_channels = 30,
 191        .timeout_ms = 10000,
 192        .use_bounce_buf = false,
 193        .buf_len = 0,
 194        .num_channels = ARRAY_SIZE(ath11k_mhi_channels_qcn9074),
 195        .ch_cfg = ath11k_mhi_channels_qcn9074,
 196        .num_events = ARRAY_SIZE(ath11k_mhi_events_qcn9074),
 197        .event_cfg = ath11k_mhi_events_qcn9074,
 198};
 199
 200void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab)
 201{
 202        u32 val;
 203
 204        val = ath11k_pci_read32(ab, MHISTATUS);
 205
 206        ath11k_dbg(ab, ATH11K_DBG_PCI, "MHISTATUS 0x%x\n", val);
 207
 208        /* Observed on QCA6390 that after SOC_GLOBAL_RESET, MHISTATUS
 209         * has SYSERR bit set and thus need to set MHICTRL_RESET
 210         * to clear SYSERR.
 211         */
 212        ath11k_pci_write32(ab, MHICTRL, MHICTRL_RESET_MASK);
 213
 214        mdelay(10);
 215}
 216
 217static void ath11k_mhi_reset_txvecdb(struct ath11k_base *ab)
 218{
 219        ath11k_pci_write32(ab, PCIE_TXVECDB, 0);
 220}
 221
 222static void ath11k_mhi_reset_txvecstatus(struct ath11k_base *ab)
 223{
 224        ath11k_pci_write32(ab, PCIE_TXVECSTATUS, 0);
 225}
 226
 227static void ath11k_mhi_reset_rxvecdb(struct ath11k_base *ab)
 228{
 229        ath11k_pci_write32(ab, PCIE_RXVECDB, 0);
 230}
 231
 232static void ath11k_mhi_reset_rxvecstatus(struct ath11k_base *ab)
 233{
 234        ath11k_pci_write32(ab, PCIE_RXVECSTATUS, 0);
 235}
 236
 237void ath11k_mhi_clear_vector(struct ath11k_base *ab)
 238{
 239        ath11k_mhi_reset_txvecdb(ab);
 240        ath11k_mhi_reset_txvecstatus(ab);
 241        ath11k_mhi_reset_rxvecdb(ab);
 242        ath11k_mhi_reset_rxvecstatus(ab);
 243}
 244
 245static int ath11k_mhi_get_msi(struct ath11k_pci *ab_pci)
 246{
 247        struct ath11k_base *ab = ab_pci->ab;
 248        u32 user_base_data, base_vector;
 249        int ret, num_vectors, i;
 250        int *irq;
 251
 252        ret = ath11k_pci_get_user_msi_assignment(ab_pci,
 253                                                 "MHI", &num_vectors,
 254                                                 &user_base_data, &base_vector);
 255        if (ret)
 256                return ret;
 257
 258        ath11k_dbg(ab, ATH11K_DBG_PCI, "Number of assigned MSI for MHI is %d, base vector is %d\n",
 259                   num_vectors, base_vector);
 260
 261        irq = kcalloc(num_vectors, sizeof(int), GFP_KERNEL);
 262        if (!irq)
 263                return -ENOMEM;
 264
 265        for (i = 0; i < num_vectors; i++)
 266                irq[i] = ath11k_pci_get_msi_irq(ab->dev,
 267                                                base_vector + i);
 268
 269        ab_pci->mhi_ctrl->irq = irq;
 270        ab_pci->mhi_ctrl->nr_irqs = num_vectors;
 271
 272        return 0;
 273}
 274
 275static int ath11k_mhi_op_runtime_get(struct mhi_controller *mhi_cntrl)
 276{
 277        return 0;
 278}
 279
 280static void ath11k_mhi_op_runtime_put(struct mhi_controller *mhi_cntrl)
 281{
 282}
 283
 284static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
 285                                    enum mhi_callback cb)
 286{
 287        struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev);
 288
 289        switch (cb) {
 290        case MHI_CB_SYS_ERROR:
 291                ath11k_warn(ab, "firmware crashed: MHI_CB_SYS_ERROR\n");
 292                break;
 293        default:
 294                break;
 295        }
 296}
 297
 298static int ath11k_mhi_op_read_reg(struct mhi_controller *mhi_cntrl,
 299                                  void __iomem *addr,
 300                                  u32 *out)
 301{
 302        *out = readl(addr);
 303
 304        return 0;
 305}
 306
 307static void ath11k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl,
 308                                    void __iomem *addr,
 309                                    u32 val)
 310{
 311        writel(val, addr);
 312}
 313
 314int ath11k_mhi_register(struct ath11k_pci *ab_pci)
 315{
 316        struct ath11k_base *ab = ab_pci->ab;
 317        struct mhi_controller *mhi_ctrl;
 318        struct mhi_controller_config *ath11k_mhi_config;
 319        int ret;
 320
 321        mhi_ctrl = mhi_alloc_controller();
 322        if (!mhi_ctrl)
 323                return -ENOMEM;
 324
 325        ath11k_core_create_firmware_path(ab, ATH11K_AMSS_FILE,
 326                                         ab_pci->amss_path,
 327                                         sizeof(ab_pci->amss_path));
 328
 329        ab_pci->mhi_ctrl = mhi_ctrl;
 330        mhi_ctrl->cntrl_dev = ab->dev;
 331        mhi_ctrl->fw_image = ab_pci->amss_path;
 332        mhi_ctrl->regs = ab->mem;
 333        mhi_ctrl->reg_len = ab->mem_len;
 334
 335        ret = ath11k_mhi_get_msi(ab_pci);
 336        if (ret) {
 337                ath11k_err(ab, "failed to get msi for mhi\n");
 338                mhi_free_controller(mhi_ctrl);
 339                return ret;
 340        }
 341
 342        mhi_ctrl->iova_start = 0;
 343        mhi_ctrl->iova_stop = 0xffffffff;
 344        mhi_ctrl->sbl_size = SZ_512K;
 345        mhi_ctrl->seg_len = SZ_512K;
 346        mhi_ctrl->fbc_download = true;
 347        mhi_ctrl->runtime_get = ath11k_mhi_op_runtime_get;
 348        mhi_ctrl->runtime_put = ath11k_mhi_op_runtime_put;
 349        mhi_ctrl->status_cb = ath11k_mhi_op_status_cb;
 350        mhi_ctrl->read_reg = ath11k_mhi_op_read_reg;
 351        mhi_ctrl->write_reg = ath11k_mhi_op_write_reg;
 352
 353        switch (ab->hw_rev) {
 354        case ATH11K_HW_QCN9074_HW10:
 355                ath11k_mhi_config = &ath11k_mhi_config_qcn9074;
 356                break;
 357        case ATH11K_HW_QCA6390_HW20:
 358        case ATH11K_HW_WCN6855_HW20:
 359                ath11k_mhi_config = &ath11k_mhi_config_qca6390;
 360                break;
 361        default:
 362                ath11k_err(ab, "failed assign mhi_config for unknown hw rev %d\n",
 363                           ab->hw_rev);
 364                mhi_free_controller(mhi_ctrl);
 365                return -EINVAL;
 366        }
 367
 368        ret = mhi_register_controller(mhi_ctrl, ath11k_mhi_config);
 369        if (ret) {
 370                ath11k_err(ab, "failed to register to mhi bus, err = %d\n", ret);
 371                mhi_free_controller(mhi_ctrl);
 372                return ret;
 373        }
 374
 375        return 0;
 376}
 377
 378void ath11k_mhi_unregister(struct ath11k_pci *ab_pci)
 379{
 380        struct mhi_controller *mhi_ctrl = ab_pci->mhi_ctrl;
 381
 382        mhi_unregister_controller(mhi_ctrl);
 383        kfree(mhi_ctrl->irq);
 384        mhi_free_controller(mhi_ctrl);
 385}
 386
 387static char *ath11k_mhi_state_to_str(enum ath11k_mhi_state mhi_state)
 388{
 389        switch (mhi_state) {
 390        case ATH11K_MHI_INIT:
 391                return "INIT";
 392        case ATH11K_MHI_DEINIT:
 393                return "DEINIT";
 394        case ATH11K_MHI_POWER_ON:
 395                return "POWER_ON";
 396        case ATH11K_MHI_POWER_OFF:
 397                return "POWER_OFF";
 398        case ATH11K_MHI_FORCE_POWER_OFF:
 399                return "FORCE_POWER_OFF";
 400        case ATH11K_MHI_SUSPEND:
 401                return "SUSPEND";
 402        case ATH11K_MHI_RESUME:
 403                return "RESUME";
 404        case ATH11K_MHI_TRIGGER_RDDM:
 405                return "TRIGGER_RDDM";
 406        case ATH11K_MHI_RDDM_DONE:
 407                return "RDDM_DONE";
 408        default:
 409                return "UNKNOWN";
 410        }
 411};
 412
 413static void ath11k_mhi_set_state_bit(struct ath11k_pci *ab_pci,
 414                                     enum ath11k_mhi_state mhi_state)
 415{
 416        struct ath11k_base *ab = ab_pci->ab;
 417
 418        switch (mhi_state) {
 419        case ATH11K_MHI_INIT:
 420                set_bit(ATH11K_MHI_INIT, &ab_pci->mhi_state);
 421                break;
 422        case ATH11K_MHI_DEINIT:
 423                clear_bit(ATH11K_MHI_INIT, &ab_pci->mhi_state);
 424                break;
 425        case ATH11K_MHI_POWER_ON:
 426                set_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state);
 427                break;
 428        case ATH11K_MHI_POWER_OFF:
 429        case ATH11K_MHI_FORCE_POWER_OFF:
 430                clear_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state);
 431                clear_bit(ATH11K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state);
 432                clear_bit(ATH11K_MHI_RDDM_DONE, &ab_pci->mhi_state);
 433                break;
 434        case ATH11K_MHI_SUSPEND:
 435                set_bit(ATH11K_MHI_SUSPEND, &ab_pci->mhi_state);
 436                break;
 437        case ATH11K_MHI_RESUME:
 438                clear_bit(ATH11K_MHI_SUSPEND, &ab_pci->mhi_state);
 439                break;
 440        case ATH11K_MHI_TRIGGER_RDDM:
 441                set_bit(ATH11K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state);
 442                break;
 443        case ATH11K_MHI_RDDM_DONE:
 444                set_bit(ATH11K_MHI_RDDM_DONE, &ab_pci->mhi_state);
 445                break;
 446        default:
 447                ath11k_err(ab, "unhandled mhi state (%d)\n", mhi_state);
 448        }
 449}
 450
 451static int ath11k_mhi_check_state_bit(struct ath11k_pci *ab_pci,
 452                                      enum ath11k_mhi_state mhi_state)
 453{
 454        struct ath11k_base *ab = ab_pci->ab;
 455
 456        switch (mhi_state) {
 457        case ATH11K_MHI_INIT:
 458                if (!test_bit(ATH11K_MHI_INIT, &ab_pci->mhi_state))
 459                        return 0;
 460                break;
 461        case ATH11K_MHI_DEINIT:
 462        case ATH11K_MHI_POWER_ON:
 463                if (test_bit(ATH11K_MHI_INIT, &ab_pci->mhi_state) &&
 464                    !test_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state))
 465                        return 0;
 466                break;
 467        case ATH11K_MHI_FORCE_POWER_OFF:
 468                if (test_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state))
 469                        return 0;
 470                break;
 471        case ATH11K_MHI_POWER_OFF:
 472        case ATH11K_MHI_SUSPEND:
 473                if (test_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state) &&
 474                    !test_bit(ATH11K_MHI_SUSPEND, &ab_pci->mhi_state))
 475                        return 0;
 476                break;
 477        case ATH11K_MHI_RESUME:
 478                if (test_bit(ATH11K_MHI_SUSPEND, &ab_pci->mhi_state))
 479                        return 0;
 480                break;
 481        case ATH11K_MHI_TRIGGER_RDDM:
 482                if (test_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state) &&
 483                    !test_bit(ATH11K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state))
 484                        return 0;
 485                break;
 486        case ATH11K_MHI_RDDM_DONE:
 487                return 0;
 488        default:
 489                ath11k_err(ab, "unhandled mhi state: %s(%d)\n",
 490                           ath11k_mhi_state_to_str(mhi_state), mhi_state);
 491        }
 492
 493        ath11k_err(ab, "failed to set mhi state %s(%d) in current mhi state (0x%lx)\n",
 494                   ath11k_mhi_state_to_str(mhi_state), mhi_state,
 495                   ab_pci->mhi_state);
 496
 497        return -EINVAL;
 498}
 499
 500static int ath11k_mhi_set_state(struct ath11k_pci *ab_pci,
 501                                enum ath11k_mhi_state mhi_state)
 502{
 503        struct ath11k_base *ab = ab_pci->ab;
 504        int ret;
 505
 506        ret = ath11k_mhi_check_state_bit(ab_pci, mhi_state);
 507        if (ret)
 508                goto out;
 509
 510        ath11k_dbg(ab, ATH11K_DBG_PCI, "setting mhi state: %s(%d)\n",
 511                   ath11k_mhi_state_to_str(mhi_state), mhi_state);
 512
 513        switch (mhi_state) {
 514        case ATH11K_MHI_INIT:
 515                ret = mhi_prepare_for_power_up(ab_pci->mhi_ctrl);
 516                break;
 517        case ATH11K_MHI_DEINIT:
 518                mhi_unprepare_after_power_down(ab_pci->mhi_ctrl);
 519                ret = 0;
 520                break;
 521        case ATH11K_MHI_POWER_ON:
 522                ret = mhi_async_power_up(ab_pci->mhi_ctrl);
 523                break;
 524        case ATH11K_MHI_POWER_OFF:
 525                mhi_power_down(ab_pci->mhi_ctrl, true);
 526                ret = 0;
 527                break;
 528        case ATH11K_MHI_FORCE_POWER_OFF:
 529                mhi_power_down(ab_pci->mhi_ctrl, false);
 530                ret = 0;
 531                break;
 532        case ATH11K_MHI_SUSPEND:
 533                ret = mhi_pm_suspend(ab_pci->mhi_ctrl);
 534                break;
 535        case ATH11K_MHI_RESUME:
 536                ret = mhi_pm_resume(ab_pci->mhi_ctrl);
 537                break;
 538        case ATH11K_MHI_TRIGGER_RDDM:
 539                ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl);
 540                break;
 541        case ATH11K_MHI_RDDM_DONE:
 542                break;
 543        default:
 544                ath11k_err(ab, "unhandled MHI state (%d)\n", mhi_state);
 545                ret = -EINVAL;
 546        }
 547
 548        if (ret)
 549                goto out;
 550
 551        ath11k_mhi_set_state_bit(ab_pci, mhi_state);
 552
 553        return 0;
 554
 555out:
 556        ath11k_err(ab, "failed to set mhi state: %s(%d)\n",
 557                   ath11k_mhi_state_to_str(mhi_state), mhi_state);
 558        return ret;
 559}
 560
 561int ath11k_mhi_start(struct ath11k_pci *ab_pci)
 562{
 563        int ret;
 564
 565        ab_pci->mhi_ctrl->timeout_ms = MHI_TIMEOUT_DEFAULT_MS;
 566
 567        ret = ath11k_mhi_set_state(ab_pci, ATH11K_MHI_INIT);
 568        if (ret)
 569                goto out;
 570
 571        ret = ath11k_mhi_set_state(ab_pci, ATH11K_MHI_POWER_ON);
 572        if (ret)
 573                goto out;
 574
 575        return 0;
 576
 577out:
 578        return ret;
 579}
 580
 581void ath11k_mhi_stop(struct ath11k_pci *ab_pci)
 582{
 583        ath11k_mhi_set_state(ab_pci, ATH11K_MHI_POWER_OFF);
 584        ath11k_mhi_set_state(ab_pci, ATH11K_MHI_DEINIT);
 585}
 586
 587void ath11k_mhi_suspend(struct ath11k_pci *ab_pci)
 588{
 589        ath11k_mhi_set_state(ab_pci, ATH11K_MHI_SUSPEND);
 590}
 591
 592void ath11k_mhi_resume(struct ath11k_pci *ab_pci)
 593{
 594        ath11k_mhi_set_state(ab_pci, ATH11K_MHI_RESUME);
 595}
 596