1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00
linux/drivers/net/wireless/ath/ath12k/pci.h
Ramya Gnanasekar 80e396586d wifi: ath12k: PCI ops for wakeup/release MHI
Wakeup/release MHI is not needed before pci_read/write for QCN9274.
Since wakeup & release MHI is enabled for all QCN9274 and
WCN7850, below MHI assert is seen in QCN9274

[  784.906613] BUG: sleeping function called from invalid context at drivers/bus/mhi/host/pm.c:989
[  784.906633] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 0, name: swapper/3
[  784.906637] preempt_count: 503, expected: 0
[  784.906641] RCU nest depth: 0, expected: 0
[  784.906644] 2 locks held by swapper/3/0:
[  784.906646]  #0: ffff8ed348e429e0 (&ab->ce.ce_lock){+.-.}-{2:2}, at: ath12k_ce_recv_process_cb+0xb3/0x2f0 [ath12k]
[  784.906664]  #1: ffff8ed348e491f0 (&srng->lock_key#3){+.-.}-{2:2}, at: ath12k_ce_recv_process_cb+0xfb/0x2f0 [ath12k]
[  784.906678] Preemption disabled at:
[  784.906680] [<0000000000000000>] 0x0
[  784.906686] CPU: 3 PID: 0 Comm: swapper/3 Tainted: G        W  O       6.1.0-rc2+ #3
[  784.906688] Hardware name: Intel(R) Client Systems NUC8i7HVK/NUC8i7HVB, BIOS HNKBLi70.86A.0056.2019.0506.1527 05/06/2019
[  784.906690] Call Trace:
[  784.906691]  <IRQ>
[  784.906693]  dump_stack_lvl+0x56/0x7b
[  784.906698]  __might_resched+0x21c/0x270
[  784.906704]  __mhi_device_get_sync+0x7d/0x1c0 [mhi]
[  784.906714]  mhi_device_get_sync+0xd/0x20 [mhi]
[  784.906719]  ath12k_pci_write32+0x75/0x170 [ath12k]
[  784.906729]  ath12k_hal_srng_access_end+0x55/0xc0 [ath12k]
[  784.906737]  ath12k_ce_recv_process_cb+0x1f3/0x2f0 [ath12k]
[  784.906776]  ? ath12k_pci_ce_tasklet+0x11/0x30 [ath12k]
[  784.906788]  ath12k_pci_ce_tasklet+0x11/0x30 [ath12k]
[  784.906813]  tasklet_action_common.isra.18+0xb7/0xe0
[  784.906820]  __do_softirq+0xd0/0x4c9
[  784.906826]  irq_exit_rcu+0x88/0xe0
[  784.906828]  common_interrupt+0xa5/0xc0
[  784.906831]  </IRQ>
[  784.906832]  <TASK>

Adding function callbacks for MHI wakeup and release operations.
QCN9274 does not need wakeup/release, function callbacks are initialized
to NULL. In case of WCN7850, shadow registers are used to access rings.
Since, shadow register's offset is less than ACCESS_ALWAYS_OFF,
mhi_device_get_sync() or mhi_device_put() to wakeup
and release mhi will not be called during service ring accesses.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0-03171-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4

Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20230123095141.5310-1-quic_rgnanase@quicinc.com
2023-02-22 11:50:29 +02:00

141 lines
4.4 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH12K_PCI_H
#define ATH12K_PCI_H
#include <linux/mhi.h>
#include "core.h"
#define PCIE_SOC_GLOBAL_RESET 0x3008
#define PCIE_SOC_GLOBAL_RESET_V 1
#define WLAON_WARM_SW_ENTRY 0x1f80504
#define WLAON_SOC_RESET_CAUSE_REG 0x01f8060c
#define PCIE_Q6_COOKIE_ADDR 0x01f80500
#define PCIE_Q6_COOKIE_DATA 0xc0000000
/* register to wake the UMAC from power collapse */
#define PCIE_SCRATCH_0_SOC_PCIE_REG 0x4040
/* register used for handshake mechanism to validate UMAC is awake */
#define PCIE_SOC_WAKE_PCIE_LOCAL_REG 0x3004
#define PCIE_PCIE_PARF_LTSSM 0x1e081b0
#define PARM_LTSSM_VALUE 0x111
#define GCC_GCC_PCIE_HOT_RST 0x1e38338
#define GCC_GCC_PCIE_HOT_RST_VAL 0x10
#define PCIE_PCIE_INT_ALL_CLEAR 0x1e08228
#define PCIE_SMLH_REQ_RST_LINK_DOWN 0x2
#define PCIE_INT_CLEAR_ALL 0xffffffff
#define PCIE_QSERDES_COM_SYSCLK_EN_SEL_REG(ab) \
((ab)->hw_params->regs->pcie_qserdes_sysclk_en_sel)
#define PCIE_QSERDES_COM_SYSCLK_EN_SEL_VAL 0x10
#define PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK 0xffffffff
#define PCIE_PCS_OSC_DTCT_CONFIG1_REG(ab) \
((ab)->hw_params->regs->pcie_pcs_osc_dtct_config_base)
#define PCIE_PCS_OSC_DTCT_CONFIG1_VAL 0x02
#define PCIE_PCS_OSC_DTCT_CONFIG2_REG(ab) \
((ab)->hw_params->regs->pcie_pcs_osc_dtct_config_base + 0x4)
#define PCIE_PCS_OSC_DTCT_CONFIG2_VAL 0x52
#define PCIE_PCS_OSC_DTCT_CONFIG4_REG(ab) \
((ab)->hw_params->regs->pcie_pcs_osc_dtct_config_base + 0xc)
#define PCIE_PCS_OSC_DTCT_CONFIG4_VAL 0xff
#define PCIE_PCS_OSC_DTCT_CONFIG_MSK 0x000000ff
#define WLAON_QFPROM_PWR_CTRL_REG 0x01f8031c
#define QFPROM_PWR_CTRL_VDD4BLOW_MASK 0x4
#define PCI_BAR_WINDOW0_BASE 0x1E00000
#define PCI_BAR_WINDOW0_END 0x1E7FFFC
#define PCI_SOC_RANGE_MASK 0x3FFF
#define PCI_SOC_PCI_REG_BASE 0x1E04000
#define PCI_SOC_PCI_REG_END 0x1E07FFC
#define PCI_PARF_BASE 0x1E08000
#define PCI_PARF_END 0x1E0BFFC
#define PCI_MHIREGLEN_REG 0x1E0E100
#define PCI_MHI_REGION_END 0x1E0EFFC
#define QRTR_PCI_DOMAIN_NR_MASK GENMASK(7, 4)
#define QRTR_PCI_BUS_NUMBER_MASK GENMASK(3, 0)
#define ATH12K_PCI_SOC_HW_VERSION_1 1
#define ATH12K_PCI_SOC_HW_VERSION_2 2
struct ath12k_msi_user {
const char *name;
int num_vectors;
u32 base_vector;
};
struct ath12k_msi_config {
int total_vectors;
int total_users;
const struct ath12k_msi_user *users;
};
enum ath12k_pci_flags {
ATH12K_PCI_FLAG_INIT_DONE,
ATH12K_PCI_FLAG_IS_MSI_64,
ATH12K_PCI_ASPM_RESTORE,
};
struct ath12k_pci_ops {
int (*wakeup)(struct ath12k_base *ab);
void (*release)(struct ath12k_base *ab);
};
struct ath12k_pci {
struct pci_dev *pdev;
struct ath12k_base *ab;
u16 dev_id;
char amss_path[100];
u32 msi_ep_base_data;
struct mhi_controller *mhi_ctrl;
const struct ath12k_msi_config *msi_config;
unsigned long mhi_state;
u32 register_window;
/* protects register_window above */
spinlock_t window_lock;
/* enum ath12k_pci_flags */
unsigned long flags;
u16 link_ctl;
const struct ath12k_pci_ops *pci_ops;
};
static inline struct ath12k_pci *ath12k_pci_priv(struct ath12k_base *ab)
{
return (struct ath12k_pci *)ab->drv_priv;
}
int ath12k_pci_get_user_msi_assignment(struct ath12k_base *ab, char *user_name,
int *num_vectors, u32 *user_base_data,
u32 *base_vector);
int ath12k_pci_get_msi_irq(struct device *dev, unsigned int vector);
void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value);
u32 ath12k_pci_read32(struct ath12k_base *ab, u32 offset);
int ath12k_pci_map_service_to_pipe(struct ath12k_base *ab, u16 service_id,
u8 *ul_pipe, u8 *dl_pipe);
void ath12k_pci_get_msi_address(struct ath12k_base *ab, u32 *msi_addr_lo,
u32 *msi_addr_hi);
void ath12k_pci_get_ce_msi_idx(struct ath12k_base *ab, u32 ce_id,
u32 *msi_idx);
void ath12k_pci_hif_ce_irq_enable(struct ath12k_base *ab);
void ath12k_pci_hif_ce_irq_disable(struct ath12k_base *ab);
void ath12k_pci_ext_irq_enable(struct ath12k_base *ab);
void ath12k_pci_ext_irq_disable(struct ath12k_base *ab);
int ath12k_pci_hif_suspend(struct ath12k_base *ab);
int ath12k_pci_hif_resume(struct ath12k_base *ab);
void ath12k_pci_stop(struct ath12k_base *ab);
int ath12k_pci_start(struct ath12k_base *ab);
int ath12k_pci_power_up(struct ath12k_base *ab);
void ath12k_pci_power_down(struct ath12k_base *ab);
#endif /* ATH12K_PCI_H */