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