brintos

brintos / linux-shallow public Read only

0
0
Text · 15.8 KiB · df96b0f Raw
652 lines · c
1// SPDX-License-Identifier: BSD-3-Clause-Clear2/*3 * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.4 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.5 */6 7#include <linux/msi.h>8#include <linux/pci.h>9#include <linux/firmware.h>10 11#include "core.h"12#include "debug.h"13#include "mhi.h"14#include "pci.h"15 16#define MHI_TIMEOUT_DEFAULT_MS	9000017#define OTP_INVALID_BOARD_ID	0xFFFF18#define OTP_VALID_DUALMAC_BOARD_ID_MASK		0x100019#define MHI_CB_INVALID	0xff20 21static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {22	{23		.num = 20,24		.name = "IPCR",25		.num_elements = 32,26		.event_ring = 1,27		.dir = DMA_TO_DEVICE,28		.ee_mask = 0x4,29		.pollcfg = 0,30		.doorbell = MHI_DB_BRST_DISABLE,31		.lpm_notify = false,32		.offload_channel = false,33		.doorbell_mode_switch = false,34		.auto_queue = false,35	},36	{37		.num = 21,38		.name = "IPCR",39		.num_elements = 32,40		.event_ring = 1,41		.dir = DMA_FROM_DEVICE,42		.ee_mask = 0x4,43		.pollcfg = 0,44		.doorbell = MHI_DB_BRST_DISABLE,45		.lpm_notify = false,46		.offload_channel = false,47		.doorbell_mode_switch = false,48		.auto_queue = true,49	},50};51 52static struct mhi_event_config ath12k_mhi_events_qcn9274[] = {53	{54		.num_elements = 32,55		.irq_moderation_ms = 0,56		.irq = 1,57		.data_type = MHI_ER_CTRL,58		.mode = MHI_DB_BRST_DISABLE,59		.hardware_event = false,60		.client_managed = false,61		.offload_channel = false,62	},63	{64		.num_elements = 256,65		.irq_moderation_ms = 1,66		.irq = 2,67		.mode = MHI_DB_BRST_DISABLE,68		.priority = 1,69		.hardware_event = false,70		.client_managed = false,71		.offload_channel = false,72	},73};74 75const struct mhi_controller_config ath12k_mhi_config_qcn9274 = {76	.max_channels = 30,77	.timeout_ms = 10000,78	.use_bounce_buf = false,79	.buf_len = 0,80	.num_channels = ARRAY_SIZE(ath12k_mhi_channels_qcn9274),81	.ch_cfg = ath12k_mhi_channels_qcn9274,82	.num_events = ARRAY_SIZE(ath12k_mhi_events_qcn9274),83	.event_cfg = ath12k_mhi_events_qcn9274,84};85 86static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {87	{88		.num = 20,89		.name = "IPCR",90		.num_elements = 64,91		.event_ring = 1,92		.dir = DMA_TO_DEVICE,93		.ee_mask = 0x4,94		.pollcfg = 0,95		.doorbell = MHI_DB_BRST_DISABLE,96		.lpm_notify = false,97		.offload_channel = false,98		.doorbell_mode_switch = false,99		.auto_queue = false,100	},101	{102		.num = 21,103		.name = "IPCR",104		.num_elements = 64,105		.event_ring = 1,106		.dir = DMA_FROM_DEVICE,107		.ee_mask = 0x4,108		.pollcfg = 0,109		.doorbell = MHI_DB_BRST_DISABLE,110		.lpm_notify = false,111		.offload_channel = false,112		.doorbell_mode_switch = false,113		.auto_queue = true,114	},115};116 117static struct mhi_event_config ath12k_mhi_events_wcn7850[] = {118	{119		.num_elements = 32,120		.irq_moderation_ms = 0,121		.irq = 1,122		.mode = MHI_DB_BRST_DISABLE,123		.data_type = MHI_ER_CTRL,124		.hardware_event = false,125		.client_managed = false,126		.offload_channel = false,127	},128	{129		.num_elements = 256,130		.irq_moderation_ms = 1,131		.irq = 2,132		.mode = MHI_DB_BRST_DISABLE,133		.priority = 1,134		.hardware_event = false,135		.client_managed = false,136		.offload_channel = false,137	},138};139 140const struct mhi_controller_config ath12k_mhi_config_wcn7850 = {141	.max_channels = 128,142	.timeout_ms = 2000,143	.use_bounce_buf = false,144	.buf_len = 8192,145	.num_channels = ARRAY_SIZE(ath12k_mhi_channels_wcn7850),146	.ch_cfg = ath12k_mhi_channels_wcn7850,147	.num_events = ARRAY_SIZE(ath12k_mhi_events_wcn7850),148	.event_cfg = ath12k_mhi_events_wcn7850,149};150 151void ath12k_mhi_set_mhictrl_reset(struct ath12k_base *ab)152{153	u32 val;154 155	val = ath12k_pci_read32(ab, MHISTATUS);156 157	ath12k_dbg(ab, ATH12K_DBG_PCI, "MHISTATUS 0x%x\n", val);158 159	/* Observed on some targets that after SOC_GLOBAL_RESET, MHISTATUS160	 * has SYSERR bit set and thus need to set MHICTRL_RESET161	 * to clear SYSERR.162	 */163	ath12k_pci_write32(ab, MHICTRL, MHICTRL_RESET_MASK);164 165	mdelay(10);166}167 168static void ath12k_mhi_reset_txvecdb(struct ath12k_base *ab)169{170	ath12k_pci_write32(ab, PCIE_TXVECDB, 0);171}172 173static void ath12k_mhi_reset_txvecstatus(struct ath12k_base *ab)174{175	ath12k_pci_write32(ab, PCIE_TXVECSTATUS, 0);176}177 178static void ath12k_mhi_reset_rxvecdb(struct ath12k_base *ab)179{180	ath12k_pci_write32(ab, PCIE_RXVECDB, 0);181}182 183static void ath12k_mhi_reset_rxvecstatus(struct ath12k_base *ab)184{185	ath12k_pci_write32(ab, PCIE_RXVECSTATUS, 0);186}187 188void ath12k_mhi_clear_vector(struct ath12k_base *ab)189{190	ath12k_mhi_reset_txvecdb(ab);191	ath12k_mhi_reset_txvecstatus(ab);192	ath12k_mhi_reset_rxvecdb(ab);193	ath12k_mhi_reset_rxvecstatus(ab);194}195 196static int ath12k_mhi_get_msi(struct ath12k_pci *ab_pci)197{198	struct ath12k_base *ab = ab_pci->ab;199	u32 user_base_data, base_vector;200	int ret, num_vectors, i;201	int *irq;202	unsigned int msi_data;203 204	ret = ath12k_pci_get_user_msi_assignment(ab,205						 "MHI", &num_vectors,206						 &user_base_data, &base_vector);207	if (ret)208		return ret;209 210	ath12k_dbg(ab, ATH12K_DBG_PCI, "Number of assigned MSI for MHI is %d, base vector is %d\n",211		   num_vectors, base_vector);212 213	irq = kcalloc(num_vectors, sizeof(*irq), GFP_KERNEL);214	if (!irq)215		return -ENOMEM;216 217	msi_data = base_vector;218	for (i = 0; i < num_vectors; i++) {219		if (test_bit(ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))220			irq[i] = ath12k_pci_get_msi_irq(ab->dev,221							msi_data++);222		else223			irq[i] = ath12k_pci_get_msi_irq(ab->dev,224							msi_data);225	}226 227	ab_pci->mhi_ctrl->irq = irq;228	ab_pci->mhi_ctrl->nr_irqs = num_vectors;229 230	return 0;231}232 233static int ath12k_mhi_op_runtime_get(struct mhi_controller *mhi_cntrl)234{235	return 0;236}237 238static void ath12k_mhi_op_runtime_put(struct mhi_controller *mhi_cntrl)239{240}241 242static char *ath12k_mhi_op_callback_to_str(enum mhi_callback reason)243{244	switch (reason) {245	case MHI_CB_IDLE:246		return "MHI_CB_IDLE";247	case MHI_CB_PENDING_DATA:248		return "MHI_CB_PENDING_DATA";249	case MHI_CB_LPM_ENTER:250		return "MHI_CB_LPM_ENTER";251	case MHI_CB_LPM_EXIT:252		return "MHI_CB_LPM_EXIT";253	case MHI_CB_EE_RDDM:254		return "MHI_CB_EE_RDDM";255	case MHI_CB_EE_MISSION_MODE:256		return "MHI_CB_EE_MISSION_MODE";257	case MHI_CB_SYS_ERROR:258		return "MHI_CB_SYS_ERROR";259	case MHI_CB_FATAL_ERROR:260		return "MHI_CB_FATAL_ERROR";261	case MHI_CB_BW_REQ:262		return "MHI_CB_BW_REQ";263	default:264		return "UNKNOWN";265	}266}267 268static void ath12k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,269				    enum mhi_callback cb)270{271	struct ath12k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev);272	struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);273 274	ath12k_dbg(ab, ATH12K_DBG_BOOT, "mhi notify status reason %s\n",275		   ath12k_mhi_op_callback_to_str(cb));276 277	switch (cb) {278	case MHI_CB_SYS_ERROR:279		ath12k_warn(ab, "firmware crashed: MHI_CB_SYS_ERROR\n");280		break;281	case MHI_CB_EE_RDDM:282		if (ab_pci->mhi_pre_cb == MHI_CB_EE_RDDM) {283			ath12k_dbg(ab, ATH12K_DBG_BOOT,284				   "do not queue again for consecutive RDDM event\n");285			break;286		}287 288		if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags)))289			queue_work(ab->workqueue_aux, &ab->reset_work);290		break;291	default:292		break;293	}294 295	ab_pci->mhi_pre_cb = cb;296}297 298static int ath12k_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 ath12k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl,308				    void __iomem *addr,309				    u32 val)310{311	writel(val, addr);312}313 314int ath12k_mhi_register(struct ath12k_pci *ab_pci)315{316	struct ath12k_base *ab = ab_pci->ab;317	struct mhi_controller *mhi_ctrl;318	unsigned int board_id;319	int ret;320	bool dualmac = false;321 322	mhi_ctrl = mhi_alloc_controller();323	if (!mhi_ctrl)324		return -ENOMEM;325 326	ab_pci->mhi_pre_cb = MHI_CB_INVALID;327	ab_pci->mhi_ctrl = mhi_ctrl;328	mhi_ctrl->cntrl_dev = ab->dev;329	mhi_ctrl->regs = ab->mem;330	mhi_ctrl->reg_len = ab->mem_len;331	mhi_ctrl->rddm_size = ab->hw_params->rddm_size;332 333	if (ab->hw_params->otp_board_id_register) {334		board_id =335			ath12k_pci_read32(ab, ab->hw_params->otp_board_id_register);336		board_id = u32_get_bits(board_id, OTP_BOARD_ID_MASK);337 338		if (!board_id || (board_id == OTP_INVALID_BOARD_ID)) {339			ath12k_dbg(ab, ATH12K_DBG_BOOT,340				   "failed to read board id\n");341		} else if (board_id & OTP_VALID_DUALMAC_BOARD_ID_MASK) {342			dualmac = true;343			ath12k_dbg(ab, ATH12K_DBG_BOOT,344				   "dualmac fw selected for board id: %x\n", board_id);345		}346	}347 348	if (dualmac) {349		if (ab->fw.amss_dualmac_data && ab->fw.amss_dualmac_len > 0) {350			/* use MHI firmware file from firmware-N.bin */351			mhi_ctrl->fw_data = ab->fw.amss_dualmac_data;352			mhi_ctrl->fw_sz = ab->fw.amss_dualmac_len;353		} else {354			ath12k_warn(ab, "dualmac firmware IE not present in firmware-N.bin\n");355			ret = -ENOENT;356			goto free_controller;357		}358	} else {359		if (ab->fw.amss_data && ab->fw.amss_len > 0) {360			/* use MHI firmware file from firmware-N.bin */361			mhi_ctrl->fw_data = ab->fw.amss_data;362			mhi_ctrl->fw_sz = ab->fw.amss_len;363		} else {364			/* use the old separate mhi.bin MHI firmware file */365			ath12k_core_create_firmware_path(ab, ATH12K_AMSS_FILE,366							 ab_pci->amss_path,367							 sizeof(ab_pci->amss_path));368			mhi_ctrl->fw_image = ab_pci->amss_path;369		}370	}371 372	ret = ath12k_mhi_get_msi(ab_pci);373	if (ret) {374		ath12k_err(ab, "failed to get msi for mhi\n");375		goto free_controller;376	}377 378	if (!test_bit(ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, &ab_pci->flags))379		mhi_ctrl->irq_flags = IRQF_SHARED | IRQF_NOBALANCING;380 381	mhi_ctrl->iova_start = 0;382	mhi_ctrl->iova_stop = 0xffffffff;383	mhi_ctrl->sbl_size = SZ_512K;384	mhi_ctrl->seg_len = SZ_512K;385	mhi_ctrl->fbc_download = true;386	mhi_ctrl->runtime_get = ath12k_mhi_op_runtime_get;387	mhi_ctrl->runtime_put = ath12k_mhi_op_runtime_put;388	mhi_ctrl->status_cb = ath12k_mhi_op_status_cb;389	mhi_ctrl->read_reg = ath12k_mhi_op_read_reg;390	mhi_ctrl->write_reg = ath12k_mhi_op_write_reg;391 392	ret = mhi_register_controller(mhi_ctrl, ab->hw_params->mhi_config);393	if (ret) {394		ath12k_err(ab, "failed to register to mhi bus, err = %d\n", ret);395		goto free_controller;396	}397 398	return 0;399 400free_controller:401	mhi_free_controller(mhi_ctrl);402	ab_pci->mhi_ctrl = NULL;403	return ret;404}405 406void ath12k_mhi_unregister(struct ath12k_pci *ab_pci)407{408	struct mhi_controller *mhi_ctrl = ab_pci->mhi_ctrl;409 410	mhi_unregister_controller(mhi_ctrl);411	kfree(mhi_ctrl->irq);412	mhi_free_controller(mhi_ctrl);413	ab_pci->mhi_ctrl = NULL;414}415 416static char *ath12k_mhi_state_to_str(enum ath12k_mhi_state mhi_state)417{418	switch (mhi_state) {419	case ATH12K_MHI_INIT:420		return "INIT";421	case ATH12K_MHI_DEINIT:422		return "DEINIT";423	case ATH12K_MHI_POWER_ON:424		return "POWER_ON";425	case ATH12K_MHI_POWER_OFF:426		return "POWER_OFF";427	case ATH12K_MHI_POWER_OFF_KEEP_DEV:428		return "POWER_OFF_KEEP_DEV";429	case ATH12K_MHI_FORCE_POWER_OFF:430		return "FORCE_POWER_OFF";431	case ATH12K_MHI_SUSPEND:432		return "SUSPEND";433	case ATH12K_MHI_RESUME:434		return "RESUME";435	case ATH12K_MHI_TRIGGER_RDDM:436		return "TRIGGER_RDDM";437	case ATH12K_MHI_RDDM_DONE:438		return "RDDM_DONE";439	default:440		return "UNKNOWN";441	}442};443 444static void ath12k_mhi_set_state_bit(struct ath12k_pci *ab_pci,445				     enum ath12k_mhi_state mhi_state)446{447	struct ath12k_base *ab = ab_pci->ab;448 449	switch (mhi_state) {450	case ATH12K_MHI_INIT:451		set_bit(ATH12K_MHI_INIT, &ab_pci->mhi_state);452		break;453	case ATH12K_MHI_DEINIT:454		clear_bit(ATH12K_MHI_INIT, &ab_pci->mhi_state);455		break;456	case ATH12K_MHI_POWER_ON:457		set_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state);458		break;459	case ATH12K_MHI_POWER_OFF:460	case ATH12K_MHI_POWER_OFF_KEEP_DEV:461	case ATH12K_MHI_FORCE_POWER_OFF:462		clear_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state);463		clear_bit(ATH12K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state);464		clear_bit(ATH12K_MHI_RDDM_DONE, &ab_pci->mhi_state);465		break;466	case ATH12K_MHI_SUSPEND:467		set_bit(ATH12K_MHI_SUSPEND, &ab_pci->mhi_state);468		break;469	case ATH12K_MHI_RESUME:470		clear_bit(ATH12K_MHI_SUSPEND, &ab_pci->mhi_state);471		break;472	case ATH12K_MHI_TRIGGER_RDDM:473		set_bit(ATH12K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state);474		break;475	case ATH12K_MHI_RDDM_DONE:476		set_bit(ATH12K_MHI_RDDM_DONE, &ab_pci->mhi_state);477		break;478	default:479		ath12k_err(ab, "unhandled mhi state (%d)\n", mhi_state);480	}481}482 483static int ath12k_mhi_check_state_bit(struct ath12k_pci *ab_pci,484				      enum ath12k_mhi_state mhi_state)485{486	struct ath12k_base *ab = ab_pci->ab;487 488	switch (mhi_state) {489	case ATH12K_MHI_INIT:490		if (!test_bit(ATH12K_MHI_INIT, &ab_pci->mhi_state))491			return 0;492		break;493	case ATH12K_MHI_DEINIT:494	case ATH12K_MHI_POWER_ON:495		if (test_bit(ATH12K_MHI_INIT, &ab_pci->mhi_state) &&496		    !test_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state))497			return 0;498		break;499	case ATH12K_MHI_FORCE_POWER_OFF:500		if (test_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state))501			return 0;502		break;503	case ATH12K_MHI_POWER_OFF:504	case ATH12K_MHI_POWER_OFF_KEEP_DEV:505	case ATH12K_MHI_SUSPEND:506		if (test_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state) &&507		    !test_bit(ATH12K_MHI_SUSPEND, &ab_pci->mhi_state))508			return 0;509		break;510	case ATH12K_MHI_RESUME:511		if (test_bit(ATH12K_MHI_SUSPEND, &ab_pci->mhi_state))512			return 0;513		break;514	case ATH12K_MHI_TRIGGER_RDDM:515		if (test_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state) &&516		    !test_bit(ATH12K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state))517			return 0;518		break;519	case ATH12K_MHI_RDDM_DONE:520		return 0;521	default:522		ath12k_err(ab, "unhandled mhi state: %s(%d)\n",523			   ath12k_mhi_state_to_str(mhi_state), mhi_state);524	}525 526	ath12k_err(ab, "failed to set mhi state %s(%d) in current mhi state (0x%lx)\n",527		   ath12k_mhi_state_to_str(mhi_state), mhi_state,528		   ab_pci->mhi_state);529 530	return -EINVAL;531}532 533static int ath12k_mhi_set_state(struct ath12k_pci *ab_pci,534				enum ath12k_mhi_state mhi_state)535{536	struct ath12k_base *ab = ab_pci->ab;537	int ret;538 539	ret = ath12k_mhi_check_state_bit(ab_pci, mhi_state);540	if (ret)541		goto out;542 543	ath12k_dbg(ab, ATH12K_DBG_PCI, "setting mhi state: %s(%d)\n",544		   ath12k_mhi_state_to_str(mhi_state), mhi_state);545 546	switch (mhi_state) {547	case ATH12K_MHI_INIT:548		ret = mhi_prepare_for_power_up(ab_pci->mhi_ctrl);549		break;550	case ATH12K_MHI_DEINIT:551		mhi_unprepare_after_power_down(ab_pci->mhi_ctrl);552		ret = 0;553		break;554	case ATH12K_MHI_POWER_ON:555		/* In case of resume, QRTR's resume_early() is called556		 * right after ath12k' resume_early(). Since QRTR requires557		 * MHI mission mode state when preparing IPCR channels558		 * (see ee_mask of that channel), we need to use the 'sync'559		 * version here to make sure MHI is in that state when we560		 * return. Or QRTR might resume before that state comes,561		 * and as a result it fails.562		 *563		 * The 'sync' version works for non-resume (normal power on)564		 * case as well.565		 */566		ret = mhi_sync_power_up(ab_pci->mhi_ctrl);567		break;568	case ATH12K_MHI_POWER_OFF:569		mhi_power_down(ab_pci->mhi_ctrl, true);570		ret = 0;571		break;572	case ATH12K_MHI_POWER_OFF_KEEP_DEV:573		mhi_power_down_keep_dev(ab_pci->mhi_ctrl, true);574		ret = 0;575		break;576	case ATH12K_MHI_FORCE_POWER_OFF:577		mhi_power_down(ab_pci->mhi_ctrl, false);578		ret = 0;579		break;580	case ATH12K_MHI_SUSPEND:581		ret = mhi_pm_suspend(ab_pci->mhi_ctrl);582		break;583	case ATH12K_MHI_RESUME:584		ret = mhi_pm_resume(ab_pci->mhi_ctrl);585		break;586	case ATH12K_MHI_TRIGGER_RDDM:587		ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl);588		break;589	case ATH12K_MHI_RDDM_DONE:590		break;591	default:592		ath12k_err(ab, "unhandled MHI state (%d)\n", mhi_state);593		ret = -EINVAL;594	}595 596	if (ret)597		goto out;598 599	ath12k_mhi_set_state_bit(ab_pci, mhi_state);600 601	return 0;602 603out:604	ath12k_err(ab, "failed to set mhi state: %s(%d)\n",605		   ath12k_mhi_state_to_str(mhi_state), mhi_state);606	return ret;607}608 609int ath12k_mhi_start(struct ath12k_pci *ab_pci)610{611	int ret;612 613	ab_pci->mhi_ctrl->timeout_ms = MHI_TIMEOUT_DEFAULT_MS;614 615	ret = ath12k_mhi_set_state(ab_pci, ATH12K_MHI_INIT);616	if (ret)617		goto out;618 619	ret = ath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_ON);620	if (ret)621		goto out;622 623	return 0;624 625out:626	return ret;627}628 629void ath12k_mhi_stop(struct ath12k_pci *ab_pci, bool is_suspend)630{631	/* During suspend we need to use mhi_power_down_keep_dev()632	 * workaround, otherwise ath12k_core_resume() will timeout633	 * during resume.634	 */635	if (is_suspend)636		ath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_OFF_KEEP_DEV);637	else638		ath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_OFF);639 640	ath12k_mhi_set_state(ab_pci, ATH12K_MHI_DEINIT);641}642 643void ath12k_mhi_suspend(struct ath12k_pci *ab_pci)644{645	ath12k_mhi_set_state(ab_pci, ATH12K_MHI_SUSPEND);646}647 648void ath12k_mhi_resume(struct ath12k_pci *ab_pci)649{650	ath12k_mhi_set_state(ab_pci, ATH12K_MHI_RESUME);651}652