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
 334        ret = ath11k_mhi_get_msi(ab_pci);
 335        if (ret) {
 336                ath11k_err(ab, "failed to get msi for mhi\n");
 337                mhi_free_controller(mhi_ctrl);
 338                return ret;
 339        }
 340
 341        mhi_ctrl->iova_start = 0;
 342        mhi_ctrl->iova_stop = 0xffffffff;
 343        mhi_ctrl->sbl_size = SZ_512K;
 344        mhi_ctrl->seg_len = SZ_512K;
 345        mhi_ctrl->fbc_download = true;
 346        mhi_ctrl->runtime_get = ath11k_mhi_op_runtime_get;
 347        mhi_ctrl->runtime_put = ath11k_mhi_op_runtime_put;
 348        mhi_ctrl->status_cb = ath11k_mhi_op_status_cb;
 349        mhi_ctrl->read_reg = ath11k_mhi_op_read_reg;
 350        mhi_ctrl->write_reg = ath11k_mhi_op_write_reg;
 351
 352        switch (ab->hw_rev) {
 353        case ATH11K_HW_QCN9074_HW10:
 354                ath11k_mhi_config = &ath11k_mhi_config_qcn9074;
 355                break;
 356        case ATH11K_HW_QCA6390_HW20:
 357        case ATH11K_HW_WCN6855_HW20:
 358                ath11k_mhi_config = &ath11k_mhi_config_qca6390;
 359                break;
 360        default:
 361                ath11k_err(ab, "failed assign mhi_config for unknown hw rev %d\n",
 362                           ab->hw_rev);
 363                mhi_free_controller(mhi_ctrl);
 364                return -EINVAL;
 365        }
 366
 367        ret = mhi_register_controller(mhi_ctrl, ath11k_mhi_config);
 368        if (ret) {
 369                ath11k_err(ab, "failed to register to mhi bus, err = %d\n", ret);
 370                mhi_free_controller(mhi_ctrl);
 371                return ret;
 372        }
 373
 374        return 0;
 375}
 376
 377void ath11k_mhi_unregister(struct ath11k_pci *ab_pci)
 378{
 379        struct mhi_controller *mhi_ctrl = ab_pci->mhi_ctrl;
 380
 381        mhi_unregister_controller(mhi_ctrl);
 382        kfree(mhi_ctrl->irq);
 383        mhi_free_controller(mhi_ctrl);
 384}
 385
 386static char *ath11k_mhi_state_to_str(enum ath11k_mhi_state mhi_state)
 387{
 388        switch (mhi_state) {
 389        case ATH11K_MHI_INIT:
 390                return "INIT";
 391        case ATH11K_MHI_DEINIT:
 392                return "DEINIT";
 393        case ATH11K_MHI_POWER_ON:
 394                return "POWER_ON";
 395        case ATH11K_MHI_POWER_OFF:
 396                return "POWER_OFF";
 397        case ATH11K_MHI_FORCE_POWER_OFF:
 398                return "FORCE_POWER_OFF";
 399        case ATH11K_MHI_SUSPEND:
 400                return "SUSPEND";
 401        case ATH11K_MHI_RESUME:
 402                return "RESUME";
 403        case ATH11K_MHI_TRIGGER_RDDM:
 404                return "TRIGGER_RDDM";
 405        case ATH11K_MHI_RDDM_DONE:
 406                return "RDDM_DONE";
 407        default:
 408                return "UNKNOWN";
 409        }
 410};
 411
 412static void ath11k_mhi_set_state_bit(struct ath11k_pci *ab_pci,
 413                                     enum ath11k_mhi_state mhi_state)
 414{
 415        struct ath11k_base *ab = ab_pci->ab;
 416
 417        switch (mhi_state) {
 418        case ATH11K_MHI_INIT:
 419                set_bit(ATH11K_MHI_INIT, &ab_pci->mhi_state);
 420                break;
 421        case ATH11K_MHI_DEINIT:
 422                clear_bit(ATH11K_MHI_INIT, &ab_pci->mhi_state);
 423                break;
 424        case ATH11K_MHI_POWER_ON:
 425                set_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state);
 426                break;
 427        case ATH11K_MHI_POWER_OFF:
 428        case ATH11K_MHI_FORCE_POWER_OFF:
 429                clear_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state);
 430                clear_bit(ATH11K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state);
 431                clear_bit(ATH11K_MHI_RDDM_DONE, &ab_pci->mhi_state);
 432                break;
 433        case ATH11K_MHI_SUSPEND:
 434                set_bit(ATH11K_MHI_SUSPEND, &ab_pci->mhi_state);
 435                break;
 436        case ATH11K_MHI_RESUME:
 437                clear_bit(ATH11K_MHI_SUSPEND, &ab_pci->mhi_state);
 438                break;
 439        case ATH11K_MHI_TRIGGER_RDDM:
 440                set_bit(ATH11K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state);
 441                break;
 442        case ATH11K_MHI_RDDM_DONE:
 443                set_bit(ATH11K_MHI_RDDM_DONE, &ab_pci->mhi_state);
 444                break;
 445        default:
 446                ath11k_err(ab, "unhandled mhi state (%d)\n", mhi_state);
 447        }
 448}
 449
 450static int ath11k_mhi_check_state_bit(struct ath11k_pci *ab_pci,
 451                                      enum ath11k_mhi_state mhi_state)
 452{
 453        struct ath11k_base *ab = ab_pci->ab;
 454
 455        switch (mhi_state) {
 456        case ATH11K_MHI_INIT:
 457                if (!test_bit(ATH11K_MHI_INIT, &ab_pci->mhi_state))
 458                        return 0;
 459                break;
 460        case ATH11K_MHI_DEINIT:
 461        case ATH11K_MHI_POWER_ON:
 462                if (test_bit(ATH11K_MHI_INIT, &ab_pci->mhi_state) &&
 463                    !test_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state))
 464                        return 0;
 465                break;
 466        case ATH11K_MHI_FORCE_POWER_OFF:
 467                if (test_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state))
 468                        return 0;
 469                break;
 470        case ATH11K_MHI_POWER_OFF:
 471        case ATH11K_MHI_SUSPEND:
 472                if (test_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state) &&
 473                    !test_bit(ATH11K_MHI_SUSPEND, &ab_pci->mhi_state))
 474                        return 0;
 475                break;
 476        case ATH11K_MHI_RESUME:
 477                if (test_bit(ATH11K_MHI_SUSPEND, &ab_pci->mhi_state))
 478                        return 0;
 479                break;
 480        case ATH11K_MHI_TRIGGER_RDDM:
 481                if (test_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state) &&
 482                    !test_bit(ATH11K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state))
 483                        return 0;
 484                break;
 485        case ATH11K_MHI_RDDM_DONE:
 486                return 0;
 487        default:
 488                ath11k_err(ab, "unhandled mhi state: %s(%d)\n",
 489                           ath11k_mhi_state_to_str(mhi_state), mhi_state);
 490        }
 491
 492        ath11k_err(ab, "failed to set mhi state %s(%d) in current mhi state (0x%lx)\n",
 493                   ath11k_mhi_state_to_str(mhi_state), mhi_state,
 494                   ab_pci->mhi_state);
 495
 496        return -EINVAL;
 497}
 498
 499static int ath11k_mhi_set_state(struct ath11k_pci *ab_pci,
 500                                enum ath11k_mhi_state mhi_state)
 501{
 502        struct ath11k_base *ab = ab_pci->ab;
 503        int ret;
 504
 505        ret = ath11k_mhi_check_state_bit(ab_pci, mhi_state);
 506        if (ret)
 507                goto out;
 508
 509        ath11k_dbg(ab, ATH11K_DBG_PCI, "setting mhi state: %s(%d)\n",
 510                   ath11k_mhi_state_to_str(mhi_state), mhi_state);
 511
 512        switch (mhi_state) {
 513        case ATH11K_MHI_INIT:
 514                ret = mhi_prepare_for_power_up(ab_pci->mhi_ctrl);
 515                break;
 516        case ATH11K_MHI_DEINIT:
 517                mhi_unprepare_after_power_down(ab_pci->mhi_ctrl);
 518                ret = 0;
 519                break;
 520        case ATH11K_MHI_POWER_ON:
 521                ret = mhi_async_power_up(ab_pci->mhi_ctrl);
 522                break;
 523        case ATH11K_MHI_POWER_OFF:
 524                mhi_power_down(ab_pci->mhi_ctrl, true);
 525                ret = 0;
 526                break;
 527        case ATH11K_MHI_FORCE_POWER_OFF:
 528                mhi_power_down(ab_pci->mhi_ctrl, false);
 529                ret = 0;
 530                break;
 531        case ATH11K_MHI_SUSPEND:
 532                ret = mhi_pm_suspend(ab_pci->mhi_ctrl);
 533                break;
 534        case ATH11K_MHI_RESUME:
 535                ret = mhi_pm_resume(ab_pci->mhi_ctrl);
 536                break;
 537        case ATH11K_MHI_TRIGGER_RDDM:
 538                ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl);
 539                break;
 540        case ATH11K_MHI_RDDM_DONE:
 541                break;
 542        default:
 543                ath11k_err(ab, "unhandled MHI state (%d)\n", mhi_state);
 544                ret = -EINVAL;
 545        }
 546
 547        if (ret)
 548                goto out;
 549
 550        ath11k_mhi_set_state_bit(ab_pci, mhi_state);
 551
 552        return 0;
 553
 554out:
 555        ath11k_err(ab, "failed to set mhi state: %s(%d)\n",
 556                   ath11k_mhi_state_to_str(mhi_state), mhi_state);
 557        return ret;
 558}
 559
 560int ath11k_mhi_start(struct ath11k_pci *ab_pci)
 561{
 562        int ret;
 563
 564        ab_pci->mhi_ctrl->timeout_ms = MHI_TIMEOUT_DEFAULT_MS;
 565
 566        ret = ath11k_mhi_set_state(ab_pci, ATH11K_MHI_INIT);
 567        if (ret)
 568                goto out;
 569
 570        ret = ath11k_mhi_set_state(ab_pci, ATH11K_MHI_POWER_ON);
 571        if (ret)
 572                goto out;
 573
 574        return 0;
 575
 576out:
 577        return ret;
 578}
 579
 580void ath11k_mhi_stop(struct ath11k_pci *ab_pci)
 581{
 582        ath11k_mhi_set_state(ab_pci, ATH11K_MHI_POWER_OFF);
 583        ath11k_mhi_set_state(ab_pci, ATH11K_MHI_DEINIT);
 584}
 585
 586void ath11k_mhi_suspend(struct ath11k_pci *ab_pci)
 587{
 588        ath11k_mhi_set_state(ab_pci, ATH11K_MHI_SUSPEND);
 589}
 590
 591void ath11k_mhi_resume(struct ath11k_pci *ab_pci)
 592{
 593        ath11k_mhi_set_state(ab_pci, ATH11K_MHI_RESUME);
 594}
 595