162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */ 462306a36Sopenharmony_ci/* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/delay.h> 762306a36Sopenharmony_ci#include <linux/err.h> 862306a36Sopenharmony_ci#include <linux/memblock.h> 962306a36Sopenharmony_ci#include <linux/mhi.h> 1062306a36Sopenharmony_ci#include <linux/moduleparam.h> 1162306a36Sopenharmony_ci#include <linux/pci.h> 1262306a36Sopenharmony_ci#include <linux/sizes.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "mhi_controller.h" 1562306a36Sopenharmony_ci#include "qaic.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define MAX_RESET_TIME_SEC 25 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic unsigned int mhi_timeout_ms = 2000; /* 2 sec default */ 2062306a36Sopenharmony_cimodule_param(mhi_timeout_ms, uint, 0600); 2162306a36Sopenharmony_ciMODULE_PARM_DESC(mhi_timeout_ms, "MHI controller timeout value"); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic struct mhi_channel_config aic100_channels[] = { 2462306a36Sopenharmony_ci { 2562306a36Sopenharmony_ci .name = "QAIC_LOOPBACK", 2662306a36Sopenharmony_ci .num = 0, 2762306a36Sopenharmony_ci .num_elements = 32, 2862306a36Sopenharmony_ci .local_elements = 0, 2962306a36Sopenharmony_ci .event_ring = 0, 3062306a36Sopenharmony_ci .dir = DMA_TO_DEVICE, 3162306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 3262306a36Sopenharmony_ci .pollcfg = 0, 3362306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 3462306a36Sopenharmony_ci .lpm_notify = false, 3562306a36Sopenharmony_ci .offload_channel = false, 3662306a36Sopenharmony_ci .doorbell_mode_switch = false, 3762306a36Sopenharmony_ci .auto_queue = false, 3862306a36Sopenharmony_ci .wake_capable = false, 3962306a36Sopenharmony_ci }, 4062306a36Sopenharmony_ci { 4162306a36Sopenharmony_ci .name = "QAIC_LOOPBACK", 4262306a36Sopenharmony_ci .num = 1, 4362306a36Sopenharmony_ci .num_elements = 32, 4462306a36Sopenharmony_ci .local_elements = 0, 4562306a36Sopenharmony_ci .event_ring = 0, 4662306a36Sopenharmony_ci .dir = DMA_FROM_DEVICE, 4762306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 4862306a36Sopenharmony_ci .pollcfg = 0, 4962306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 5062306a36Sopenharmony_ci .lpm_notify = false, 5162306a36Sopenharmony_ci .offload_channel = false, 5262306a36Sopenharmony_ci .doorbell_mode_switch = false, 5362306a36Sopenharmony_ci .auto_queue = false, 5462306a36Sopenharmony_ci .wake_capable = false, 5562306a36Sopenharmony_ci }, 5662306a36Sopenharmony_ci { 5762306a36Sopenharmony_ci .name = "QAIC_SAHARA", 5862306a36Sopenharmony_ci .num = 2, 5962306a36Sopenharmony_ci .num_elements = 32, 6062306a36Sopenharmony_ci .local_elements = 0, 6162306a36Sopenharmony_ci .event_ring = 0, 6262306a36Sopenharmony_ci .dir = DMA_TO_DEVICE, 6362306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_SBL, 6462306a36Sopenharmony_ci .pollcfg = 0, 6562306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 6662306a36Sopenharmony_ci .lpm_notify = false, 6762306a36Sopenharmony_ci .offload_channel = false, 6862306a36Sopenharmony_ci .doorbell_mode_switch = false, 6962306a36Sopenharmony_ci .auto_queue = false, 7062306a36Sopenharmony_ci .wake_capable = false, 7162306a36Sopenharmony_ci }, 7262306a36Sopenharmony_ci { 7362306a36Sopenharmony_ci .name = "QAIC_SAHARA", 7462306a36Sopenharmony_ci .num = 3, 7562306a36Sopenharmony_ci .num_elements = 32, 7662306a36Sopenharmony_ci .local_elements = 0, 7762306a36Sopenharmony_ci .event_ring = 0, 7862306a36Sopenharmony_ci .dir = DMA_FROM_DEVICE, 7962306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_SBL, 8062306a36Sopenharmony_ci .pollcfg = 0, 8162306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 8262306a36Sopenharmony_ci .lpm_notify = false, 8362306a36Sopenharmony_ci .offload_channel = false, 8462306a36Sopenharmony_ci .doorbell_mode_switch = false, 8562306a36Sopenharmony_ci .auto_queue = false, 8662306a36Sopenharmony_ci .wake_capable = false, 8762306a36Sopenharmony_ci }, 8862306a36Sopenharmony_ci { 8962306a36Sopenharmony_ci .name = "QAIC_DIAG", 9062306a36Sopenharmony_ci .num = 4, 9162306a36Sopenharmony_ci .num_elements = 32, 9262306a36Sopenharmony_ci .local_elements = 0, 9362306a36Sopenharmony_ci .event_ring = 0, 9462306a36Sopenharmony_ci .dir = DMA_TO_DEVICE, 9562306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 9662306a36Sopenharmony_ci .pollcfg = 0, 9762306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 9862306a36Sopenharmony_ci .lpm_notify = false, 9962306a36Sopenharmony_ci .offload_channel = false, 10062306a36Sopenharmony_ci .doorbell_mode_switch = false, 10162306a36Sopenharmony_ci .auto_queue = false, 10262306a36Sopenharmony_ci .wake_capable = false, 10362306a36Sopenharmony_ci }, 10462306a36Sopenharmony_ci { 10562306a36Sopenharmony_ci .name = "QAIC_DIAG", 10662306a36Sopenharmony_ci .num = 5, 10762306a36Sopenharmony_ci .num_elements = 32, 10862306a36Sopenharmony_ci .local_elements = 0, 10962306a36Sopenharmony_ci .event_ring = 0, 11062306a36Sopenharmony_ci .dir = DMA_FROM_DEVICE, 11162306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 11262306a36Sopenharmony_ci .pollcfg = 0, 11362306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 11462306a36Sopenharmony_ci .lpm_notify = false, 11562306a36Sopenharmony_ci .offload_channel = false, 11662306a36Sopenharmony_ci .doorbell_mode_switch = false, 11762306a36Sopenharmony_ci .auto_queue = false, 11862306a36Sopenharmony_ci .wake_capable = false, 11962306a36Sopenharmony_ci }, 12062306a36Sopenharmony_ci { 12162306a36Sopenharmony_ci .name = "QAIC_SSR", 12262306a36Sopenharmony_ci .num = 6, 12362306a36Sopenharmony_ci .num_elements = 32, 12462306a36Sopenharmony_ci .local_elements = 0, 12562306a36Sopenharmony_ci .event_ring = 0, 12662306a36Sopenharmony_ci .dir = DMA_TO_DEVICE, 12762306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 12862306a36Sopenharmony_ci .pollcfg = 0, 12962306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 13062306a36Sopenharmony_ci .lpm_notify = false, 13162306a36Sopenharmony_ci .offload_channel = false, 13262306a36Sopenharmony_ci .doorbell_mode_switch = false, 13362306a36Sopenharmony_ci .auto_queue = false, 13462306a36Sopenharmony_ci .wake_capable = false, 13562306a36Sopenharmony_ci }, 13662306a36Sopenharmony_ci { 13762306a36Sopenharmony_ci .name = "QAIC_SSR", 13862306a36Sopenharmony_ci .num = 7, 13962306a36Sopenharmony_ci .num_elements = 32, 14062306a36Sopenharmony_ci .local_elements = 0, 14162306a36Sopenharmony_ci .event_ring = 0, 14262306a36Sopenharmony_ci .dir = DMA_FROM_DEVICE, 14362306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 14462306a36Sopenharmony_ci .pollcfg = 0, 14562306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 14662306a36Sopenharmony_ci .lpm_notify = false, 14762306a36Sopenharmony_ci .offload_channel = false, 14862306a36Sopenharmony_ci .doorbell_mode_switch = false, 14962306a36Sopenharmony_ci .auto_queue = false, 15062306a36Sopenharmony_ci .wake_capable = false, 15162306a36Sopenharmony_ci }, 15262306a36Sopenharmony_ci { 15362306a36Sopenharmony_ci .name = "QAIC_QDSS", 15462306a36Sopenharmony_ci .num = 8, 15562306a36Sopenharmony_ci .num_elements = 32, 15662306a36Sopenharmony_ci .local_elements = 0, 15762306a36Sopenharmony_ci .event_ring = 0, 15862306a36Sopenharmony_ci .dir = DMA_TO_DEVICE, 15962306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 16062306a36Sopenharmony_ci .pollcfg = 0, 16162306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 16262306a36Sopenharmony_ci .lpm_notify = false, 16362306a36Sopenharmony_ci .offload_channel = false, 16462306a36Sopenharmony_ci .doorbell_mode_switch = false, 16562306a36Sopenharmony_ci .auto_queue = false, 16662306a36Sopenharmony_ci .wake_capable = false, 16762306a36Sopenharmony_ci }, 16862306a36Sopenharmony_ci { 16962306a36Sopenharmony_ci .name = "QAIC_QDSS", 17062306a36Sopenharmony_ci .num = 9, 17162306a36Sopenharmony_ci .num_elements = 32, 17262306a36Sopenharmony_ci .local_elements = 0, 17362306a36Sopenharmony_ci .event_ring = 0, 17462306a36Sopenharmony_ci .dir = DMA_FROM_DEVICE, 17562306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 17662306a36Sopenharmony_ci .pollcfg = 0, 17762306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 17862306a36Sopenharmony_ci .lpm_notify = false, 17962306a36Sopenharmony_ci .offload_channel = false, 18062306a36Sopenharmony_ci .doorbell_mode_switch = false, 18162306a36Sopenharmony_ci .auto_queue = false, 18262306a36Sopenharmony_ci .wake_capable = false, 18362306a36Sopenharmony_ci }, 18462306a36Sopenharmony_ci { 18562306a36Sopenharmony_ci .name = "QAIC_CONTROL", 18662306a36Sopenharmony_ci .num = 10, 18762306a36Sopenharmony_ci .num_elements = 128, 18862306a36Sopenharmony_ci .local_elements = 0, 18962306a36Sopenharmony_ci .event_ring = 0, 19062306a36Sopenharmony_ci .dir = DMA_TO_DEVICE, 19162306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 19262306a36Sopenharmony_ci .pollcfg = 0, 19362306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 19462306a36Sopenharmony_ci .lpm_notify = false, 19562306a36Sopenharmony_ci .offload_channel = false, 19662306a36Sopenharmony_ci .doorbell_mode_switch = false, 19762306a36Sopenharmony_ci .auto_queue = false, 19862306a36Sopenharmony_ci .wake_capable = false, 19962306a36Sopenharmony_ci }, 20062306a36Sopenharmony_ci { 20162306a36Sopenharmony_ci .name = "QAIC_CONTROL", 20262306a36Sopenharmony_ci .num = 11, 20362306a36Sopenharmony_ci .num_elements = 128, 20462306a36Sopenharmony_ci .local_elements = 0, 20562306a36Sopenharmony_ci .event_ring = 0, 20662306a36Sopenharmony_ci .dir = DMA_FROM_DEVICE, 20762306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 20862306a36Sopenharmony_ci .pollcfg = 0, 20962306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 21062306a36Sopenharmony_ci .lpm_notify = false, 21162306a36Sopenharmony_ci .offload_channel = false, 21262306a36Sopenharmony_ci .doorbell_mode_switch = false, 21362306a36Sopenharmony_ci .auto_queue = false, 21462306a36Sopenharmony_ci .wake_capable = false, 21562306a36Sopenharmony_ci }, 21662306a36Sopenharmony_ci { 21762306a36Sopenharmony_ci .name = "QAIC_LOGGING", 21862306a36Sopenharmony_ci .num = 12, 21962306a36Sopenharmony_ci .num_elements = 32, 22062306a36Sopenharmony_ci .local_elements = 0, 22162306a36Sopenharmony_ci .event_ring = 0, 22262306a36Sopenharmony_ci .dir = DMA_TO_DEVICE, 22362306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_SBL, 22462306a36Sopenharmony_ci .pollcfg = 0, 22562306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 22662306a36Sopenharmony_ci .lpm_notify = false, 22762306a36Sopenharmony_ci .offload_channel = false, 22862306a36Sopenharmony_ci .doorbell_mode_switch = false, 22962306a36Sopenharmony_ci .auto_queue = false, 23062306a36Sopenharmony_ci .wake_capable = false, 23162306a36Sopenharmony_ci }, 23262306a36Sopenharmony_ci { 23362306a36Sopenharmony_ci .name = "QAIC_LOGGING", 23462306a36Sopenharmony_ci .num = 13, 23562306a36Sopenharmony_ci .num_elements = 32, 23662306a36Sopenharmony_ci .local_elements = 0, 23762306a36Sopenharmony_ci .event_ring = 0, 23862306a36Sopenharmony_ci .dir = DMA_FROM_DEVICE, 23962306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_SBL, 24062306a36Sopenharmony_ci .pollcfg = 0, 24162306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 24262306a36Sopenharmony_ci .lpm_notify = false, 24362306a36Sopenharmony_ci .offload_channel = false, 24462306a36Sopenharmony_ci .doorbell_mode_switch = false, 24562306a36Sopenharmony_ci .auto_queue = false, 24662306a36Sopenharmony_ci .wake_capable = false, 24762306a36Sopenharmony_ci }, 24862306a36Sopenharmony_ci { 24962306a36Sopenharmony_ci .name = "QAIC_STATUS", 25062306a36Sopenharmony_ci .num = 14, 25162306a36Sopenharmony_ci .num_elements = 32, 25262306a36Sopenharmony_ci .local_elements = 0, 25362306a36Sopenharmony_ci .event_ring = 0, 25462306a36Sopenharmony_ci .dir = DMA_TO_DEVICE, 25562306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 25662306a36Sopenharmony_ci .pollcfg = 0, 25762306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 25862306a36Sopenharmony_ci .lpm_notify = false, 25962306a36Sopenharmony_ci .offload_channel = false, 26062306a36Sopenharmony_ci .doorbell_mode_switch = false, 26162306a36Sopenharmony_ci .auto_queue = false, 26262306a36Sopenharmony_ci .wake_capable = false, 26362306a36Sopenharmony_ci }, 26462306a36Sopenharmony_ci { 26562306a36Sopenharmony_ci .name = "QAIC_STATUS", 26662306a36Sopenharmony_ci .num = 15, 26762306a36Sopenharmony_ci .num_elements = 32, 26862306a36Sopenharmony_ci .local_elements = 0, 26962306a36Sopenharmony_ci .event_ring = 0, 27062306a36Sopenharmony_ci .dir = DMA_FROM_DEVICE, 27162306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 27262306a36Sopenharmony_ci .pollcfg = 0, 27362306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 27462306a36Sopenharmony_ci .lpm_notify = false, 27562306a36Sopenharmony_ci .offload_channel = false, 27662306a36Sopenharmony_ci .doorbell_mode_switch = false, 27762306a36Sopenharmony_ci .auto_queue = false, 27862306a36Sopenharmony_ci .wake_capable = false, 27962306a36Sopenharmony_ci }, 28062306a36Sopenharmony_ci { 28162306a36Sopenharmony_ci .name = "QAIC_TELEMETRY", 28262306a36Sopenharmony_ci .num = 16, 28362306a36Sopenharmony_ci .num_elements = 32, 28462306a36Sopenharmony_ci .local_elements = 0, 28562306a36Sopenharmony_ci .event_ring = 0, 28662306a36Sopenharmony_ci .dir = DMA_TO_DEVICE, 28762306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 28862306a36Sopenharmony_ci .pollcfg = 0, 28962306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 29062306a36Sopenharmony_ci .lpm_notify = false, 29162306a36Sopenharmony_ci .offload_channel = false, 29262306a36Sopenharmony_ci .doorbell_mode_switch = false, 29362306a36Sopenharmony_ci .auto_queue = false, 29462306a36Sopenharmony_ci .wake_capable = false, 29562306a36Sopenharmony_ci }, 29662306a36Sopenharmony_ci { 29762306a36Sopenharmony_ci .name = "QAIC_TELEMETRY", 29862306a36Sopenharmony_ci .num = 17, 29962306a36Sopenharmony_ci .num_elements = 32, 30062306a36Sopenharmony_ci .local_elements = 0, 30162306a36Sopenharmony_ci .event_ring = 0, 30262306a36Sopenharmony_ci .dir = DMA_FROM_DEVICE, 30362306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 30462306a36Sopenharmony_ci .pollcfg = 0, 30562306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 30662306a36Sopenharmony_ci .lpm_notify = false, 30762306a36Sopenharmony_ci .offload_channel = false, 30862306a36Sopenharmony_ci .doorbell_mode_switch = false, 30962306a36Sopenharmony_ci .auto_queue = false, 31062306a36Sopenharmony_ci .wake_capable = false, 31162306a36Sopenharmony_ci }, 31262306a36Sopenharmony_ci { 31362306a36Sopenharmony_ci .name = "QAIC_DEBUG", 31462306a36Sopenharmony_ci .num = 18, 31562306a36Sopenharmony_ci .num_elements = 32, 31662306a36Sopenharmony_ci .local_elements = 0, 31762306a36Sopenharmony_ci .event_ring = 0, 31862306a36Sopenharmony_ci .dir = DMA_TO_DEVICE, 31962306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 32062306a36Sopenharmony_ci .pollcfg = 0, 32162306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 32262306a36Sopenharmony_ci .lpm_notify = false, 32362306a36Sopenharmony_ci .offload_channel = false, 32462306a36Sopenharmony_ci .doorbell_mode_switch = false, 32562306a36Sopenharmony_ci .auto_queue = false, 32662306a36Sopenharmony_ci .wake_capable = false, 32762306a36Sopenharmony_ci }, 32862306a36Sopenharmony_ci { 32962306a36Sopenharmony_ci .name = "QAIC_DEBUG", 33062306a36Sopenharmony_ci .num = 19, 33162306a36Sopenharmony_ci .num_elements = 32, 33262306a36Sopenharmony_ci .local_elements = 0, 33362306a36Sopenharmony_ci .event_ring = 0, 33462306a36Sopenharmony_ci .dir = DMA_FROM_DEVICE, 33562306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_AMSS, 33662306a36Sopenharmony_ci .pollcfg = 0, 33762306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 33862306a36Sopenharmony_ci .lpm_notify = false, 33962306a36Sopenharmony_ci .offload_channel = false, 34062306a36Sopenharmony_ci .doorbell_mode_switch = false, 34162306a36Sopenharmony_ci .auto_queue = false, 34262306a36Sopenharmony_ci .wake_capable = false, 34362306a36Sopenharmony_ci }, 34462306a36Sopenharmony_ci { 34562306a36Sopenharmony_ci .name = "QAIC_TIMESYNC", 34662306a36Sopenharmony_ci .num = 20, 34762306a36Sopenharmony_ci .num_elements = 32, 34862306a36Sopenharmony_ci .local_elements = 0, 34962306a36Sopenharmony_ci .event_ring = 0, 35062306a36Sopenharmony_ci .dir = DMA_TO_DEVICE, 35162306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_SBL | MHI_CH_EE_AMSS, 35262306a36Sopenharmony_ci .pollcfg = 0, 35362306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 35462306a36Sopenharmony_ci .lpm_notify = false, 35562306a36Sopenharmony_ci .offload_channel = false, 35662306a36Sopenharmony_ci .doorbell_mode_switch = false, 35762306a36Sopenharmony_ci .auto_queue = false, 35862306a36Sopenharmony_ci .wake_capable = false, 35962306a36Sopenharmony_ci }, 36062306a36Sopenharmony_ci { 36162306a36Sopenharmony_ci .num = 21, 36262306a36Sopenharmony_ci .name = "QAIC_TIMESYNC", 36362306a36Sopenharmony_ci .num_elements = 32, 36462306a36Sopenharmony_ci .local_elements = 0, 36562306a36Sopenharmony_ci .event_ring = 0, 36662306a36Sopenharmony_ci .dir = DMA_FROM_DEVICE, 36762306a36Sopenharmony_ci .ee_mask = MHI_CH_EE_SBL | MHI_CH_EE_AMSS, 36862306a36Sopenharmony_ci .pollcfg = 0, 36962306a36Sopenharmony_ci .doorbell = MHI_DB_BRST_DISABLE, 37062306a36Sopenharmony_ci .lpm_notify = false, 37162306a36Sopenharmony_ci .offload_channel = false, 37262306a36Sopenharmony_ci .doorbell_mode_switch = false, 37362306a36Sopenharmony_ci .auto_queue = false, 37462306a36Sopenharmony_ci .wake_capable = false, 37562306a36Sopenharmony_ci }, 37662306a36Sopenharmony_ci}; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_cistatic struct mhi_event_config aic100_events[] = { 37962306a36Sopenharmony_ci { 38062306a36Sopenharmony_ci .num_elements = 32, 38162306a36Sopenharmony_ci .irq_moderation_ms = 0, 38262306a36Sopenharmony_ci .irq = 0, 38362306a36Sopenharmony_ci .channel = U32_MAX, 38462306a36Sopenharmony_ci .priority = 1, 38562306a36Sopenharmony_ci .mode = MHI_DB_BRST_DISABLE, 38662306a36Sopenharmony_ci .data_type = MHI_ER_CTRL, 38762306a36Sopenharmony_ci .hardware_event = false, 38862306a36Sopenharmony_ci .client_managed = false, 38962306a36Sopenharmony_ci .offload_channel = false, 39062306a36Sopenharmony_ci }, 39162306a36Sopenharmony_ci}; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_cistatic struct mhi_controller_config aic100_config = { 39462306a36Sopenharmony_ci .max_channels = 128, 39562306a36Sopenharmony_ci .timeout_ms = 0, /* controlled by mhi_timeout */ 39662306a36Sopenharmony_ci .buf_len = 0, 39762306a36Sopenharmony_ci .num_channels = ARRAY_SIZE(aic100_channels), 39862306a36Sopenharmony_ci .ch_cfg = aic100_channels, 39962306a36Sopenharmony_ci .num_events = ARRAY_SIZE(aic100_events), 40062306a36Sopenharmony_ci .event_cfg = aic100_events, 40162306a36Sopenharmony_ci .use_bounce_buf = false, 40262306a36Sopenharmony_ci .m2_no_db = false, 40362306a36Sopenharmony_ci}; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistatic int mhi_read_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, u32 *out) 40662306a36Sopenharmony_ci{ 40762306a36Sopenharmony_ci u32 tmp; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci /* 41062306a36Sopenharmony_ci * SOC_HW_VERSION quirk 41162306a36Sopenharmony_ci * The SOC_HW_VERSION register (offset 0x224) is not reliable and 41262306a36Sopenharmony_ci * may contain uninitialized values, including 0xFFFFFFFF. This could 41362306a36Sopenharmony_ci * cause a false positive link down error. Instead, intercept any 41462306a36Sopenharmony_ci * reads and provide the correct value of the register. 41562306a36Sopenharmony_ci */ 41662306a36Sopenharmony_ci if (addr - mhi_cntrl->regs == 0x224) { 41762306a36Sopenharmony_ci *out = 0x60110200; 41862306a36Sopenharmony_ci return 0; 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci tmp = readl_relaxed(addr); 42262306a36Sopenharmony_ci if (tmp == U32_MAX) 42362306a36Sopenharmony_ci return -EIO; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci *out = tmp; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci return 0; 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistatic void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, u32 val) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci writel_relaxed(val, addr); 43362306a36Sopenharmony_ci} 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic int mhi_runtime_get(struct mhi_controller *mhi_cntrl) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci return 0; 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_cistatic void mhi_runtime_put(struct mhi_controller *mhi_cntrl) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci} 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic void mhi_status_cb(struct mhi_controller *mhi_cntrl, enum mhi_callback reason) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(mhi_cntrl->cntrl_dev)); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci /* this event occurs in atomic context */ 44962306a36Sopenharmony_ci if (reason == MHI_CB_FATAL_ERROR) 45062306a36Sopenharmony_ci pci_err(qdev->pdev, "Fatal error received from device. Attempting to recover\n"); 45162306a36Sopenharmony_ci /* this event occurs in non-atomic context */ 45262306a36Sopenharmony_ci if (reason == MHI_CB_SYS_ERROR) 45362306a36Sopenharmony_ci qaic_dev_reset_clean_local_state(qdev, true); 45462306a36Sopenharmony_ci} 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_cistatic int mhi_reset_and_async_power_up(struct mhi_controller *mhi_cntrl) 45762306a36Sopenharmony_ci{ 45862306a36Sopenharmony_ci u8 time_sec = 1; 45962306a36Sopenharmony_ci int current_ee; 46062306a36Sopenharmony_ci int ret; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci /* Reset the device to bring the device in PBL EE */ 46362306a36Sopenharmony_ci mhi_soc_reset(mhi_cntrl); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci /* 46662306a36Sopenharmony_ci * Keep checking the execution environment(EE) after every 1 second 46762306a36Sopenharmony_ci * interval. 46862306a36Sopenharmony_ci */ 46962306a36Sopenharmony_ci do { 47062306a36Sopenharmony_ci msleep(1000); 47162306a36Sopenharmony_ci current_ee = mhi_get_exec_env(mhi_cntrl); 47262306a36Sopenharmony_ci } while (current_ee != MHI_EE_PBL && time_sec++ <= MAX_RESET_TIME_SEC); 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci /* If the device is in PBL EE retry power up */ 47562306a36Sopenharmony_ci if (current_ee == MHI_EE_PBL) 47662306a36Sopenharmony_ci ret = mhi_async_power_up(mhi_cntrl); 47762306a36Sopenharmony_ci else 47862306a36Sopenharmony_ci ret = -EIO; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci return ret; 48162306a36Sopenharmony_ci} 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_cistruct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar, 48462306a36Sopenharmony_ci int mhi_irq) 48562306a36Sopenharmony_ci{ 48662306a36Sopenharmony_ci struct mhi_controller *mhi_cntrl; 48762306a36Sopenharmony_ci int ret; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci mhi_cntrl = devm_kzalloc(&pci_dev->dev, sizeof(*mhi_cntrl), GFP_KERNEL); 49062306a36Sopenharmony_ci if (!mhi_cntrl) 49162306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci mhi_cntrl->cntrl_dev = &pci_dev->dev; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci /* 49662306a36Sopenharmony_ci * Covers the entire possible physical ram region. Remote side is 49762306a36Sopenharmony_ci * going to calculate a size of this range, so subtract 1 to prevent 49862306a36Sopenharmony_ci * rollover. 49962306a36Sopenharmony_ci */ 50062306a36Sopenharmony_ci mhi_cntrl->iova_start = 0; 50162306a36Sopenharmony_ci mhi_cntrl->iova_stop = PHYS_ADDR_MAX - 1; 50262306a36Sopenharmony_ci mhi_cntrl->status_cb = mhi_status_cb; 50362306a36Sopenharmony_ci mhi_cntrl->runtime_get = mhi_runtime_get; 50462306a36Sopenharmony_ci mhi_cntrl->runtime_put = mhi_runtime_put; 50562306a36Sopenharmony_ci mhi_cntrl->read_reg = mhi_read_reg; 50662306a36Sopenharmony_ci mhi_cntrl->write_reg = mhi_write_reg; 50762306a36Sopenharmony_ci mhi_cntrl->regs = mhi_bar; 50862306a36Sopenharmony_ci mhi_cntrl->reg_len = SZ_4K; 50962306a36Sopenharmony_ci mhi_cntrl->nr_irqs = 1; 51062306a36Sopenharmony_ci mhi_cntrl->irq = devm_kmalloc(&pci_dev->dev, sizeof(*mhi_cntrl->irq), GFP_KERNEL); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci if (!mhi_cntrl->irq) 51362306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci mhi_cntrl->irq[0] = mhi_irq; 51662306a36Sopenharmony_ci mhi_cntrl->fw_image = "qcom/aic100/sbl.bin"; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci /* use latest configured timeout */ 51962306a36Sopenharmony_ci aic100_config.timeout_ms = mhi_timeout_ms; 52062306a36Sopenharmony_ci ret = mhi_register_controller(mhi_cntrl, &aic100_config); 52162306a36Sopenharmony_ci if (ret) { 52262306a36Sopenharmony_ci pci_err(pci_dev, "mhi_register_controller failed %d\n", ret); 52362306a36Sopenharmony_ci return ERR_PTR(ret); 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci ret = mhi_prepare_for_power_up(mhi_cntrl); 52762306a36Sopenharmony_ci if (ret) { 52862306a36Sopenharmony_ci pci_err(pci_dev, "mhi_prepare_for_power_up failed %d\n", ret); 52962306a36Sopenharmony_ci goto prepare_power_up_fail; 53062306a36Sopenharmony_ci } 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci ret = mhi_async_power_up(mhi_cntrl); 53362306a36Sopenharmony_ci /* 53462306a36Sopenharmony_ci * If EIO is returned it is possible that device is in SBL EE, which is 53562306a36Sopenharmony_ci * undesired. SOC reset the device and try to power up again. 53662306a36Sopenharmony_ci */ 53762306a36Sopenharmony_ci if (ret == -EIO && MHI_EE_SBL == mhi_get_exec_env(mhi_cntrl)) { 53862306a36Sopenharmony_ci pci_err(pci_dev, "Found device in SBL at MHI init. Attempting a reset.\n"); 53962306a36Sopenharmony_ci ret = mhi_reset_and_async_power_up(mhi_cntrl); 54062306a36Sopenharmony_ci } 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci if (ret) { 54362306a36Sopenharmony_ci pci_err(pci_dev, "mhi_async_power_up failed %d\n", ret); 54462306a36Sopenharmony_ci goto power_up_fail; 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci return mhi_cntrl; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_cipower_up_fail: 55062306a36Sopenharmony_ci mhi_unprepare_after_power_down(mhi_cntrl); 55162306a36Sopenharmony_ciprepare_power_up_fail: 55262306a36Sopenharmony_ci mhi_unregister_controller(mhi_cntrl); 55362306a36Sopenharmony_ci return ERR_PTR(ret); 55462306a36Sopenharmony_ci} 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_civoid qaic_mhi_free_controller(struct mhi_controller *mhi_cntrl, bool link_up) 55762306a36Sopenharmony_ci{ 55862306a36Sopenharmony_ci mhi_power_down(mhi_cntrl, link_up); 55962306a36Sopenharmony_ci mhi_unprepare_after_power_down(mhi_cntrl); 56062306a36Sopenharmony_ci mhi_unregister_controller(mhi_cntrl); 56162306a36Sopenharmony_ci} 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_civoid qaic_mhi_start_reset(struct mhi_controller *mhi_cntrl) 56462306a36Sopenharmony_ci{ 56562306a36Sopenharmony_ci mhi_power_down(mhi_cntrl, true); 56662306a36Sopenharmony_ci} 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_civoid qaic_mhi_reset_done(struct mhi_controller *mhi_cntrl) 56962306a36Sopenharmony_ci{ 57062306a36Sopenharmony_ci struct pci_dev *pci_dev = container_of(mhi_cntrl->cntrl_dev, struct pci_dev, dev); 57162306a36Sopenharmony_ci int ret; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci ret = mhi_async_power_up(mhi_cntrl); 57462306a36Sopenharmony_ci if (ret) 57562306a36Sopenharmony_ci pci_err(pci_dev, "mhi_async_power_up failed after reset %d\n", ret); 57662306a36Sopenharmony_ci} 577