18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause-Clear
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/module.h>
78c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
88c2ecf20Sopenharmony_ci#include <linux/of_device.h>
98c2ecf20Sopenharmony_ci#include <linux/of.h>
108c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
118c2ecf20Sopenharmony_ci#include "ahb.h"
128c2ecf20Sopenharmony_ci#include "debug.h"
138c2ecf20Sopenharmony_ci#include "hif.h"
148c2ecf20Sopenharmony_ci#include <linux/remoteproc.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistatic const struct of_device_id ath11k_ahb_of_match[] = {
178c2ecf20Sopenharmony_ci	/* TODO: Should we change the compatible string to something similar
188c2ecf20Sopenharmony_ci	 * to one that ath10k uses?
198c2ecf20Sopenharmony_ci	 */
208c2ecf20Sopenharmony_ci	{ .compatible = "qcom,ipq8074-wifi",
218c2ecf20Sopenharmony_ci	  .data = (void *)ATH11K_HW_IPQ8074,
228c2ecf20Sopenharmony_ci	},
238c2ecf20Sopenharmony_ci	{ .compatible = "qcom,ipq6018-wifi",
248c2ecf20Sopenharmony_ci	  .data = (void *)ATH11K_HW_IPQ6018_HW10,
258c2ecf20Sopenharmony_ci	},
268c2ecf20Sopenharmony_ci	{ }
278c2ecf20Sopenharmony_ci};
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, ath11k_ahb_of_match);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic const struct ath11k_bus_params ath11k_ahb_bus_params = {
328c2ecf20Sopenharmony_ci	.mhi_support = false,
338c2ecf20Sopenharmony_ci	.m3_fw_support = false,
348c2ecf20Sopenharmony_ci	.fixed_bdf_addr = true,
358c2ecf20Sopenharmony_ci	.fixed_mem_region = true,
368c2ecf20Sopenharmony_ci};
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define ATH11K_IRQ_CE0_OFFSET 4
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistatic const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
418c2ecf20Sopenharmony_ci	"misc-pulse1",
428c2ecf20Sopenharmony_ci	"misc-latch",
438c2ecf20Sopenharmony_ci	"sw-exception",
448c2ecf20Sopenharmony_ci	"watchdog",
458c2ecf20Sopenharmony_ci	"ce0",
468c2ecf20Sopenharmony_ci	"ce1",
478c2ecf20Sopenharmony_ci	"ce2",
488c2ecf20Sopenharmony_ci	"ce3",
498c2ecf20Sopenharmony_ci	"ce4",
508c2ecf20Sopenharmony_ci	"ce5",
518c2ecf20Sopenharmony_ci	"ce6",
528c2ecf20Sopenharmony_ci	"ce7",
538c2ecf20Sopenharmony_ci	"ce8",
548c2ecf20Sopenharmony_ci	"ce9",
558c2ecf20Sopenharmony_ci	"ce10",
568c2ecf20Sopenharmony_ci	"ce11",
578c2ecf20Sopenharmony_ci	"host2wbm-desc-feed",
588c2ecf20Sopenharmony_ci	"host2reo-re-injection",
598c2ecf20Sopenharmony_ci	"host2reo-command",
608c2ecf20Sopenharmony_ci	"host2rxdma-monitor-ring3",
618c2ecf20Sopenharmony_ci	"host2rxdma-monitor-ring2",
628c2ecf20Sopenharmony_ci	"host2rxdma-monitor-ring1",
638c2ecf20Sopenharmony_ci	"reo2ost-exception",
648c2ecf20Sopenharmony_ci	"wbm2host-rx-release",
658c2ecf20Sopenharmony_ci	"reo2host-status",
668c2ecf20Sopenharmony_ci	"reo2host-destination-ring4",
678c2ecf20Sopenharmony_ci	"reo2host-destination-ring3",
688c2ecf20Sopenharmony_ci	"reo2host-destination-ring2",
698c2ecf20Sopenharmony_ci	"reo2host-destination-ring1",
708c2ecf20Sopenharmony_ci	"rxdma2host-monitor-destination-mac3",
718c2ecf20Sopenharmony_ci	"rxdma2host-monitor-destination-mac2",
728c2ecf20Sopenharmony_ci	"rxdma2host-monitor-destination-mac1",
738c2ecf20Sopenharmony_ci	"ppdu-end-interrupts-mac3",
748c2ecf20Sopenharmony_ci	"ppdu-end-interrupts-mac2",
758c2ecf20Sopenharmony_ci	"ppdu-end-interrupts-mac1",
768c2ecf20Sopenharmony_ci	"rxdma2host-monitor-status-ring-mac3",
778c2ecf20Sopenharmony_ci	"rxdma2host-monitor-status-ring-mac2",
788c2ecf20Sopenharmony_ci	"rxdma2host-monitor-status-ring-mac1",
798c2ecf20Sopenharmony_ci	"host2rxdma-host-buf-ring-mac3",
808c2ecf20Sopenharmony_ci	"host2rxdma-host-buf-ring-mac2",
818c2ecf20Sopenharmony_ci	"host2rxdma-host-buf-ring-mac1",
828c2ecf20Sopenharmony_ci	"rxdma2host-destination-ring-mac3",
838c2ecf20Sopenharmony_ci	"rxdma2host-destination-ring-mac2",
848c2ecf20Sopenharmony_ci	"rxdma2host-destination-ring-mac1",
858c2ecf20Sopenharmony_ci	"host2tcl-input-ring4",
868c2ecf20Sopenharmony_ci	"host2tcl-input-ring3",
878c2ecf20Sopenharmony_ci	"host2tcl-input-ring2",
888c2ecf20Sopenharmony_ci	"host2tcl-input-ring1",
898c2ecf20Sopenharmony_ci	"wbm2host-tx-completions-ring3",
908c2ecf20Sopenharmony_ci	"wbm2host-tx-completions-ring2",
918c2ecf20Sopenharmony_ci	"wbm2host-tx-completions-ring1",
928c2ecf20Sopenharmony_ci	"tcl2host-status-ring",
938c2ecf20Sopenharmony_ci};
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci/* enum ext_irq_num - irq numbers that can be used by external modules
968c2ecf20Sopenharmony_ci * like datapath
978c2ecf20Sopenharmony_ci */
988c2ecf20Sopenharmony_cienum ext_irq_num {
998c2ecf20Sopenharmony_ci	host2wbm_desc_feed = 16,
1008c2ecf20Sopenharmony_ci	host2reo_re_injection,
1018c2ecf20Sopenharmony_ci	host2reo_command,
1028c2ecf20Sopenharmony_ci	host2rxdma_monitor_ring3,
1038c2ecf20Sopenharmony_ci	host2rxdma_monitor_ring2,
1048c2ecf20Sopenharmony_ci	host2rxdma_monitor_ring1,
1058c2ecf20Sopenharmony_ci	reo2host_exception,
1068c2ecf20Sopenharmony_ci	wbm2host_rx_release,
1078c2ecf20Sopenharmony_ci	reo2host_status,
1088c2ecf20Sopenharmony_ci	reo2host_destination_ring4,
1098c2ecf20Sopenharmony_ci	reo2host_destination_ring3,
1108c2ecf20Sopenharmony_ci	reo2host_destination_ring2,
1118c2ecf20Sopenharmony_ci	reo2host_destination_ring1,
1128c2ecf20Sopenharmony_ci	rxdma2host_monitor_destination_mac3,
1138c2ecf20Sopenharmony_ci	rxdma2host_monitor_destination_mac2,
1148c2ecf20Sopenharmony_ci	rxdma2host_monitor_destination_mac1,
1158c2ecf20Sopenharmony_ci	ppdu_end_interrupts_mac3,
1168c2ecf20Sopenharmony_ci	ppdu_end_interrupts_mac2,
1178c2ecf20Sopenharmony_ci	ppdu_end_interrupts_mac1,
1188c2ecf20Sopenharmony_ci	rxdma2host_monitor_status_ring_mac3,
1198c2ecf20Sopenharmony_ci	rxdma2host_monitor_status_ring_mac2,
1208c2ecf20Sopenharmony_ci	rxdma2host_monitor_status_ring_mac1,
1218c2ecf20Sopenharmony_ci	host2rxdma_host_buf_ring_mac3,
1228c2ecf20Sopenharmony_ci	host2rxdma_host_buf_ring_mac2,
1238c2ecf20Sopenharmony_ci	host2rxdma_host_buf_ring_mac1,
1248c2ecf20Sopenharmony_ci	rxdma2host_destination_ring_mac3,
1258c2ecf20Sopenharmony_ci	rxdma2host_destination_ring_mac2,
1268c2ecf20Sopenharmony_ci	rxdma2host_destination_ring_mac1,
1278c2ecf20Sopenharmony_ci	host2tcl_input_ring4,
1288c2ecf20Sopenharmony_ci	host2tcl_input_ring3,
1298c2ecf20Sopenharmony_ci	host2tcl_input_ring2,
1308c2ecf20Sopenharmony_ci	host2tcl_input_ring1,
1318c2ecf20Sopenharmony_ci	wbm2host_tx_completions_ring3,
1328c2ecf20Sopenharmony_ci	wbm2host_tx_completions_ring2,
1338c2ecf20Sopenharmony_ci	wbm2host_tx_completions_ring1,
1348c2ecf20Sopenharmony_ci	tcl2host_status_ring,
1358c2ecf20Sopenharmony_ci};
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_cistatic inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset)
1388c2ecf20Sopenharmony_ci{
1398c2ecf20Sopenharmony_ci	return ioread32(ab->mem + offset);
1408c2ecf20Sopenharmony_ci}
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_cistatic inline void ath11k_ahb_write32(struct ath11k_base *ab, u32 offset, u32 value)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci	iowrite32(value, ab->mem + offset);
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cistatic void ath11k_ahb_kill_tasklets(struct ath11k_base *ab)
1488c2ecf20Sopenharmony_ci{
1498c2ecf20Sopenharmony_ci	int i;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	for (i = 0; i < ab->hw_params.ce_count; i++) {
1528c2ecf20Sopenharmony_ci		struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
1558c2ecf20Sopenharmony_ci			continue;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci		tasklet_kill(&ce_pipe->intr_tq);
1588c2ecf20Sopenharmony_ci	}
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cistatic void ath11k_ahb_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	int i;
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	for (i = 0; i < irq_grp->num_irq; i++)
1668c2ecf20Sopenharmony_ci		disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
1678c2ecf20Sopenharmony_ci}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic void __ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	int i;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
1748c2ecf20Sopenharmony_ci		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci		ath11k_ahb_ext_grp_disable(irq_grp);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci		if (irq_grp->napi_enabled) {
1798c2ecf20Sopenharmony_ci			napi_synchronize(&irq_grp->napi);
1808c2ecf20Sopenharmony_ci			napi_disable(&irq_grp->napi);
1818c2ecf20Sopenharmony_ci			irq_grp->napi_enabled = false;
1828c2ecf20Sopenharmony_ci		}
1838c2ecf20Sopenharmony_ci	}
1848c2ecf20Sopenharmony_ci}
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_cistatic void ath11k_ahb_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	int i;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	for (i = 0; i < irq_grp->num_irq; i++)
1918c2ecf20Sopenharmony_ci		enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cistatic void ath11k_ahb_setbit32(struct ath11k_base *ab, u8 bit, u32 offset)
1958c2ecf20Sopenharmony_ci{
1968c2ecf20Sopenharmony_ci	u32 val;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	val = ath11k_ahb_read32(ab, offset);
1998c2ecf20Sopenharmony_ci	ath11k_ahb_write32(ab, offset, val | BIT(bit));
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistatic void ath11k_ahb_clearbit32(struct ath11k_base *ab, u8 bit, u32 offset)
2038c2ecf20Sopenharmony_ci{
2048c2ecf20Sopenharmony_ci	u32 val;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	val = ath11k_ahb_read32(ab, offset);
2078c2ecf20Sopenharmony_ci	ath11k_ahb_write32(ab, offset, val & ~BIT(bit));
2088c2ecf20Sopenharmony_ci}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_cistatic void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	const struct ce_attr *ce_attr;
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	ce_attr = &ab->hw_params.host_ce_config[ce_id];
2158c2ecf20Sopenharmony_ci	if (ce_attr->src_nentries)
2168c2ecf20Sopenharmony_ci		ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	if (ce_attr->dest_nentries) {
2198c2ecf20Sopenharmony_ci		ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
2208c2ecf20Sopenharmony_ci		ath11k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
2218c2ecf20Sopenharmony_ci				    CE_HOST_IE_3_ADDRESS);
2228c2ecf20Sopenharmony_ci	}
2238c2ecf20Sopenharmony_ci}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cistatic void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
2268c2ecf20Sopenharmony_ci{
2278c2ecf20Sopenharmony_ci	const struct ce_attr *ce_attr;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	ce_attr = &ab->hw_params.host_ce_config[ce_id];
2308c2ecf20Sopenharmony_ci	if (ce_attr->src_nentries)
2318c2ecf20Sopenharmony_ci		ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	if (ce_attr->dest_nentries) {
2348c2ecf20Sopenharmony_ci		ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
2358c2ecf20Sopenharmony_ci		ath11k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
2368c2ecf20Sopenharmony_ci				      CE_HOST_IE_3_ADDRESS);
2378c2ecf20Sopenharmony_ci	}
2388c2ecf20Sopenharmony_ci}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_cistatic void ath11k_ahb_sync_ce_irqs(struct ath11k_base *ab)
2418c2ecf20Sopenharmony_ci{
2428c2ecf20Sopenharmony_ci	int i;
2438c2ecf20Sopenharmony_ci	int irq_idx;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	for (i = 0; i < ab->hw_params.ce_count; i++) {
2468c2ecf20Sopenharmony_ci		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
2478c2ecf20Sopenharmony_ci			continue;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci		irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
2508c2ecf20Sopenharmony_ci		synchronize_irq(ab->irq_num[irq_idx]);
2518c2ecf20Sopenharmony_ci	}
2528c2ecf20Sopenharmony_ci}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_cistatic void ath11k_ahb_sync_ext_irqs(struct ath11k_base *ab)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	int i, j;
2578c2ecf20Sopenharmony_ci	int irq_idx;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
2608c2ecf20Sopenharmony_ci		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci		for (j = 0; j < irq_grp->num_irq; j++) {
2638c2ecf20Sopenharmony_ci			irq_idx = irq_grp->irqs[j];
2648c2ecf20Sopenharmony_ci			synchronize_irq(ab->irq_num[irq_idx]);
2658c2ecf20Sopenharmony_ci		}
2668c2ecf20Sopenharmony_ci	}
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_cistatic void ath11k_ahb_ce_irqs_enable(struct ath11k_base *ab)
2708c2ecf20Sopenharmony_ci{
2718c2ecf20Sopenharmony_ci	int i;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	for (i = 0; i < ab->hw_params.ce_count; i++) {
2748c2ecf20Sopenharmony_ci		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
2758c2ecf20Sopenharmony_ci			continue;
2768c2ecf20Sopenharmony_ci		ath11k_ahb_ce_irq_enable(ab, i);
2778c2ecf20Sopenharmony_ci	}
2788c2ecf20Sopenharmony_ci}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cistatic void ath11k_ahb_ce_irqs_disable(struct ath11k_base *ab)
2818c2ecf20Sopenharmony_ci{
2828c2ecf20Sopenharmony_ci	int i;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	for (i = 0; i < ab->hw_params.ce_count; i++) {
2858c2ecf20Sopenharmony_ci		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
2868c2ecf20Sopenharmony_ci			continue;
2878c2ecf20Sopenharmony_ci		ath11k_ahb_ce_irq_disable(ab, i);
2888c2ecf20Sopenharmony_ci	}
2898c2ecf20Sopenharmony_ci}
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_cistatic int ath11k_ahb_start(struct ath11k_base *ab)
2928c2ecf20Sopenharmony_ci{
2938c2ecf20Sopenharmony_ci	ath11k_ahb_ce_irqs_enable(ab);
2948c2ecf20Sopenharmony_ci	ath11k_ce_rx_post_buf(ab);
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	return 0;
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_cistatic void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab)
3008c2ecf20Sopenharmony_ci{
3018c2ecf20Sopenharmony_ci	int i;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
3048c2ecf20Sopenharmony_ci		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci		if (!irq_grp->napi_enabled) {
3078c2ecf20Sopenharmony_ci			napi_enable(&irq_grp->napi);
3088c2ecf20Sopenharmony_ci			irq_grp->napi_enabled = true;
3098c2ecf20Sopenharmony_ci		}
3108c2ecf20Sopenharmony_ci		ath11k_ahb_ext_grp_enable(irq_grp);
3118c2ecf20Sopenharmony_ci	}
3128c2ecf20Sopenharmony_ci}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_cistatic void ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	__ath11k_ahb_ext_irq_disable(ab);
3178c2ecf20Sopenharmony_ci	ath11k_ahb_sync_ext_irqs(ab);
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_cistatic void ath11k_ahb_stop(struct ath11k_base *ab)
3218c2ecf20Sopenharmony_ci{
3228c2ecf20Sopenharmony_ci	if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags))
3238c2ecf20Sopenharmony_ci		ath11k_ahb_ce_irqs_disable(ab);
3248c2ecf20Sopenharmony_ci	ath11k_ahb_sync_ce_irqs(ab);
3258c2ecf20Sopenharmony_ci	ath11k_ahb_kill_tasklets(ab);
3268c2ecf20Sopenharmony_ci	del_timer_sync(&ab->rx_replenish_retry);
3278c2ecf20Sopenharmony_ci	ath11k_ce_cleanup_pipes(ab);
3288c2ecf20Sopenharmony_ci}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_cistatic int ath11k_ahb_power_up(struct ath11k_base *ab)
3318c2ecf20Sopenharmony_ci{
3328c2ecf20Sopenharmony_ci	struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
3338c2ecf20Sopenharmony_ci	int ret;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	ret = rproc_boot(ab_ahb->tgt_rproc);
3368c2ecf20Sopenharmony_ci	if (ret)
3378c2ecf20Sopenharmony_ci		ath11k_err(ab, "failed to boot the remote processor Q6\n");
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	return ret;
3408c2ecf20Sopenharmony_ci}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_cistatic void ath11k_ahb_power_down(struct ath11k_base *ab)
3438c2ecf20Sopenharmony_ci{
3448c2ecf20Sopenharmony_ci	struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	rproc_shutdown(ab_ahb->tgt_rproc);
3478c2ecf20Sopenharmony_ci}
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_cistatic void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
3508c2ecf20Sopenharmony_ci{
3518c2ecf20Sopenharmony_ci	struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	cfg->tgt_ce_len = ab->hw_params.target_ce_count;
3548c2ecf20Sopenharmony_ci	cfg->tgt_ce = ab->hw_params.target_ce_config;
3558c2ecf20Sopenharmony_ci	cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len;
3568c2ecf20Sopenharmony_ci	cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map;
3578c2ecf20Sopenharmony_ci	ab->qmi.service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074;
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_cistatic void ath11k_ahb_free_ext_irq(struct ath11k_base *ab)
3618c2ecf20Sopenharmony_ci{
3628c2ecf20Sopenharmony_ci	int i, j;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
3658c2ecf20Sopenharmony_ci		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci		for (j = 0; j < irq_grp->num_irq; j++)
3688c2ecf20Sopenharmony_ci			free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci		netif_napi_del(&irq_grp->napi);
3718c2ecf20Sopenharmony_ci	}
3728c2ecf20Sopenharmony_ci}
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_cistatic void ath11k_ahb_free_irq(struct ath11k_base *ab)
3758c2ecf20Sopenharmony_ci{
3768c2ecf20Sopenharmony_ci	int irq_idx;
3778c2ecf20Sopenharmony_ci	int i;
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	for (i = 0; i < ab->hw_params.ce_count; i++) {
3808c2ecf20Sopenharmony_ci		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
3818c2ecf20Sopenharmony_ci			continue;
3828c2ecf20Sopenharmony_ci		irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
3838c2ecf20Sopenharmony_ci		free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
3848c2ecf20Sopenharmony_ci	}
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci	ath11k_ahb_free_ext_irq(ab);
3878c2ecf20Sopenharmony_ci}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_cistatic void ath11k_ahb_ce_tasklet(struct tasklet_struct *t)
3908c2ecf20Sopenharmony_ci{
3918c2ecf20Sopenharmony_ci	struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci	ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci	ath11k_ahb_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
3968c2ecf20Sopenharmony_ci}
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_cistatic irqreturn_t ath11k_ahb_ce_interrupt_handler(int irq, void *arg)
3998c2ecf20Sopenharmony_ci{
4008c2ecf20Sopenharmony_ci	struct ath11k_ce_pipe *ce_pipe = arg;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	/* last interrupt received for this CE */
4038c2ecf20Sopenharmony_ci	ce_pipe->timestamp = jiffies;
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	ath11k_ahb_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	tasklet_schedule(&ce_pipe->intr_tq);
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
4108c2ecf20Sopenharmony_ci}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_cistatic int ath11k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget)
4138c2ecf20Sopenharmony_ci{
4148c2ecf20Sopenharmony_ci	struct ath11k_ext_irq_grp *irq_grp = container_of(napi,
4158c2ecf20Sopenharmony_ci						struct ath11k_ext_irq_grp,
4168c2ecf20Sopenharmony_ci						napi);
4178c2ecf20Sopenharmony_ci	struct ath11k_base *ab = irq_grp->ab;
4188c2ecf20Sopenharmony_ci	int work_done;
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	work_done = ath11k_dp_service_srng(ab, irq_grp, budget);
4218c2ecf20Sopenharmony_ci	if (work_done < budget) {
4228c2ecf20Sopenharmony_ci		napi_complete_done(napi, work_done);
4238c2ecf20Sopenharmony_ci		ath11k_ahb_ext_grp_enable(irq_grp);
4248c2ecf20Sopenharmony_ci	}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	if (work_done > budget)
4278c2ecf20Sopenharmony_ci		work_done = budget;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	return work_done;
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_cistatic irqreturn_t ath11k_ahb_ext_interrupt_handler(int irq, void *arg)
4338c2ecf20Sopenharmony_ci{
4348c2ecf20Sopenharmony_ci	struct ath11k_ext_irq_grp *irq_grp = arg;
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	/* last interrupt received for this group */
4378c2ecf20Sopenharmony_ci	irq_grp->timestamp = jiffies;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	ath11k_ahb_ext_grp_disable(irq_grp);
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	napi_schedule(&irq_grp->napi);
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
4448c2ecf20Sopenharmony_ci}
4458c2ecf20Sopenharmony_ci
4468c2ecf20Sopenharmony_cistatic int ath11k_ahb_ext_irq_config(struct ath11k_base *ab)
4478c2ecf20Sopenharmony_ci{
4488c2ecf20Sopenharmony_ci	struct ath11k_hw_params *hw = &ab->hw_params;
4498c2ecf20Sopenharmony_ci	int i, j;
4508c2ecf20Sopenharmony_ci	int irq;
4518c2ecf20Sopenharmony_ci	int ret;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
4548c2ecf20Sopenharmony_ci		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
4558c2ecf20Sopenharmony_ci		u32 num_irq = 0;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci		irq_grp->ab = ab;
4588c2ecf20Sopenharmony_ci		irq_grp->grp_id = i;
4598c2ecf20Sopenharmony_ci		init_dummy_netdev(&irq_grp->napi_ndev);
4608c2ecf20Sopenharmony_ci		netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
4618c2ecf20Sopenharmony_ci			       ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT);
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci		for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) {
4648c2ecf20Sopenharmony_ci			if (ab->hw_params.ring_mask->tx[i] & BIT(j)) {
4658c2ecf20Sopenharmony_ci				irq_grp->irqs[num_irq++] =
4668c2ecf20Sopenharmony_ci					wbm2host_tx_completions_ring1 - j;
4678c2ecf20Sopenharmony_ci			}
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci			if (ab->hw_params.ring_mask->rx[i] & BIT(j)) {
4708c2ecf20Sopenharmony_ci				irq_grp->irqs[num_irq++] =
4718c2ecf20Sopenharmony_ci					reo2host_destination_ring1 - j;
4728c2ecf20Sopenharmony_ci			}
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci			if (ab->hw_params.ring_mask->rx_err[i] & BIT(j))
4758c2ecf20Sopenharmony_ci				irq_grp->irqs[num_irq++] = reo2host_exception;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci			if (ab->hw_params.ring_mask->rx_wbm_rel[i] & BIT(j))
4788c2ecf20Sopenharmony_ci				irq_grp->irqs[num_irq++] = wbm2host_rx_release;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci			if (ab->hw_params.ring_mask->reo_status[i] & BIT(j))
4818c2ecf20Sopenharmony_ci				irq_grp->irqs[num_irq++] = reo2host_status;
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci			if (j < ab->hw_params.max_radios) {
4848c2ecf20Sopenharmony_ci				if (ab->hw_params.ring_mask->rxdma2host[i] & BIT(j)) {
4858c2ecf20Sopenharmony_ci					irq_grp->irqs[num_irq++] =
4868c2ecf20Sopenharmony_ci						rxdma2host_destination_ring_mac1 -
4878c2ecf20Sopenharmony_ci						ath11k_hw_get_mac_from_pdev_id(hw, j);
4888c2ecf20Sopenharmony_ci				}
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci				if (ab->hw_params.ring_mask->host2rxdma[i] & BIT(j)) {
4918c2ecf20Sopenharmony_ci					irq_grp->irqs[num_irq++] =
4928c2ecf20Sopenharmony_ci						host2rxdma_host_buf_ring_mac1 -
4938c2ecf20Sopenharmony_ci						ath11k_hw_get_mac_from_pdev_id(hw, j);
4948c2ecf20Sopenharmony_ci				}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci				if (ab->hw_params.ring_mask->rx_mon_status[i] & BIT(j)) {
4978c2ecf20Sopenharmony_ci					irq_grp->irqs[num_irq++] =
4988c2ecf20Sopenharmony_ci						ppdu_end_interrupts_mac1 -
4998c2ecf20Sopenharmony_ci						ath11k_hw_get_mac_from_pdev_id(hw, j);
5008c2ecf20Sopenharmony_ci					irq_grp->irqs[num_irq++] =
5018c2ecf20Sopenharmony_ci						rxdma2host_monitor_status_ring_mac1 -
5028c2ecf20Sopenharmony_ci						ath11k_hw_get_mac_from_pdev_id(hw, j);
5038c2ecf20Sopenharmony_ci				}
5048c2ecf20Sopenharmony_ci			}
5058c2ecf20Sopenharmony_ci		}
5068c2ecf20Sopenharmony_ci		irq_grp->num_irq = num_irq;
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci		for (j = 0; j < irq_grp->num_irq; j++) {
5098c2ecf20Sopenharmony_ci			int irq_idx = irq_grp->irqs[j];
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci			irq = platform_get_irq_byname(ab->pdev,
5128c2ecf20Sopenharmony_ci						      irq_name[irq_idx]);
5138c2ecf20Sopenharmony_ci			ab->irq_num[irq_idx] = irq;
5148c2ecf20Sopenharmony_ci			irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
5158c2ecf20Sopenharmony_ci			ret = request_irq(irq, ath11k_ahb_ext_interrupt_handler,
5168c2ecf20Sopenharmony_ci					  IRQF_TRIGGER_RISING,
5178c2ecf20Sopenharmony_ci					  irq_name[irq_idx], irq_grp);
5188c2ecf20Sopenharmony_ci			if (ret) {
5198c2ecf20Sopenharmony_ci				ath11k_err(ab, "failed request_irq for %d\n",
5208c2ecf20Sopenharmony_ci					   irq);
5218c2ecf20Sopenharmony_ci			}
5228c2ecf20Sopenharmony_ci		}
5238c2ecf20Sopenharmony_ci	}
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	return 0;
5268c2ecf20Sopenharmony_ci}
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_cistatic int ath11k_ahb_config_irq(struct ath11k_base *ab)
5298c2ecf20Sopenharmony_ci{
5308c2ecf20Sopenharmony_ci	int irq, irq_idx, i;
5318c2ecf20Sopenharmony_ci	int ret;
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	/* Configure CE irqs */
5348c2ecf20Sopenharmony_ci	for (i = 0; i < ab->hw_params.ce_count; i++) {
5358c2ecf20Sopenharmony_ci		struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci		if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
5388c2ecf20Sopenharmony_ci			continue;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci		irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci		tasklet_setup(&ce_pipe->intr_tq, ath11k_ahb_ce_tasklet);
5438c2ecf20Sopenharmony_ci		irq = platform_get_irq_byname(ab->pdev, irq_name[irq_idx]);
5448c2ecf20Sopenharmony_ci		ret = request_irq(irq, ath11k_ahb_ce_interrupt_handler,
5458c2ecf20Sopenharmony_ci				  IRQF_TRIGGER_RISING, irq_name[irq_idx],
5468c2ecf20Sopenharmony_ci				  ce_pipe);
5478c2ecf20Sopenharmony_ci		if (ret)
5488c2ecf20Sopenharmony_ci			return ret;
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci		ab->irq_num[irq_idx] = irq;
5518c2ecf20Sopenharmony_ci	}
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	/* Configure external interrupts */
5548c2ecf20Sopenharmony_ci	ret = ath11k_ahb_ext_irq_config(ab);
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	return ret;
5578c2ecf20Sopenharmony_ci}
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_cistatic int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
5608c2ecf20Sopenharmony_ci					  u8 *ul_pipe, u8 *dl_pipe)
5618c2ecf20Sopenharmony_ci{
5628c2ecf20Sopenharmony_ci	const struct service_to_pipe *entry;
5638c2ecf20Sopenharmony_ci	bool ul_set = false, dl_set = false;
5648c2ecf20Sopenharmony_ci	int i;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	for (i = 0; i < ab->hw_params.svc_to_ce_map_len; i++) {
5678c2ecf20Sopenharmony_ci		entry = &ab->hw_params.svc_to_ce_map[i];
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci		if (__le32_to_cpu(entry->service_id) != service_id)
5708c2ecf20Sopenharmony_ci			continue;
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci		switch (__le32_to_cpu(entry->pipedir)) {
5738c2ecf20Sopenharmony_ci		case PIPEDIR_NONE:
5748c2ecf20Sopenharmony_ci			break;
5758c2ecf20Sopenharmony_ci		case PIPEDIR_IN:
5768c2ecf20Sopenharmony_ci			WARN_ON(dl_set);
5778c2ecf20Sopenharmony_ci			*dl_pipe = __le32_to_cpu(entry->pipenum);
5788c2ecf20Sopenharmony_ci			dl_set = true;
5798c2ecf20Sopenharmony_ci			break;
5808c2ecf20Sopenharmony_ci		case PIPEDIR_OUT:
5818c2ecf20Sopenharmony_ci			WARN_ON(ul_set);
5828c2ecf20Sopenharmony_ci			*ul_pipe = __le32_to_cpu(entry->pipenum);
5838c2ecf20Sopenharmony_ci			ul_set = true;
5848c2ecf20Sopenharmony_ci			break;
5858c2ecf20Sopenharmony_ci		case PIPEDIR_INOUT:
5868c2ecf20Sopenharmony_ci			WARN_ON(dl_set);
5878c2ecf20Sopenharmony_ci			WARN_ON(ul_set);
5888c2ecf20Sopenharmony_ci			*dl_pipe = __le32_to_cpu(entry->pipenum);
5898c2ecf20Sopenharmony_ci			*ul_pipe = __le32_to_cpu(entry->pipenum);
5908c2ecf20Sopenharmony_ci			dl_set = true;
5918c2ecf20Sopenharmony_ci			ul_set = true;
5928c2ecf20Sopenharmony_ci			break;
5938c2ecf20Sopenharmony_ci		}
5948c2ecf20Sopenharmony_ci	}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	if (WARN_ON(!ul_set || !dl_set))
5978c2ecf20Sopenharmony_ci		return -ENOENT;
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_ci	return 0;
6008c2ecf20Sopenharmony_ci}
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_cistatic const struct ath11k_hif_ops ath11k_ahb_hif_ops = {
6038c2ecf20Sopenharmony_ci	.start = ath11k_ahb_start,
6048c2ecf20Sopenharmony_ci	.stop = ath11k_ahb_stop,
6058c2ecf20Sopenharmony_ci	.read32 = ath11k_ahb_read32,
6068c2ecf20Sopenharmony_ci	.write32 = ath11k_ahb_write32,
6078c2ecf20Sopenharmony_ci	.irq_enable = ath11k_ahb_ext_irq_enable,
6088c2ecf20Sopenharmony_ci	.irq_disable = ath11k_ahb_ext_irq_disable,
6098c2ecf20Sopenharmony_ci	.map_service_to_pipe = ath11k_ahb_map_service_to_pipe,
6108c2ecf20Sopenharmony_ci	.power_down = ath11k_ahb_power_down,
6118c2ecf20Sopenharmony_ci	.power_up = ath11k_ahb_power_up,
6128c2ecf20Sopenharmony_ci};
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_cistatic int ath11k_core_get_rproc(struct ath11k_base *ab)
6158c2ecf20Sopenharmony_ci{
6168c2ecf20Sopenharmony_ci	struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab);
6178c2ecf20Sopenharmony_ci	struct device *dev = ab->dev;
6188c2ecf20Sopenharmony_ci	struct rproc *prproc;
6198c2ecf20Sopenharmony_ci	phandle rproc_phandle;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	if (of_property_read_u32(dev->of_node, "qcom,rproc", &rproc_phandle)) {
6228c2ecf20Sopenharmony_ci		ath11k_err(ab, "failed to get q6_rproc handle\n");
6238c2ecf20Sopenharmony_ci		return -ENOENT;
6248c2ecf20Sopenharmony_ci	}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	prproc = rproc_get_by_phandle(rproc_phandle);
6278c2ecf20Sopenharmony_ci	if (!prproc) {
6288c2ecf20Sopenharmony_ci		ath11k_dbg(ab, ATH11K_DBG_AHB, "failed to get rproc, deferring\n");
6298c2ecf20Sopenharmony_ci		return -EPROBE_DEFER;
6308c2ecf20Sopenharmony_ci	}
6318c2ecf20Sopenharmony_ci	ab_ahb->tgt_rproc = prproc;
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	return 0;
6348c2ecf20Sopenharmony_ci}
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_cistatic int ath11k_ahb_probe(struct platform_device *pdev)
6378c2ecf20Sopenharmony_ci{
6388c2ecf20Sopenharmony_ci	struct ath11k_base *ab;
6398c2ecf20Sopenharmony_ci	const struct of_device_id *of_id;
6408c2ecf20Sopenharmony_ci	struct resource *mem_res;
6418c2ecf20Sopenharmony_ci	void __iomem *mem;
6428c2ecf20Sopenharmony_ci	int ret;
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	of_id = of_match_device(ath11k_ahb_of_match, &pdev->dev);
6458c2ecf20Sopenharmony_ci	if (!of_id) {
6468c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to find matching device tree id\n");
6478c2ecf20Sopenharmony_ci		return -EINVAL;
6488c2ecf20Sopenharmony_ci	}
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	mem = devm_platform_get_and_ioremap_resource(pdev, 0, &mem_res);
6518c2ecf20Sopenharmony_ci	if (IS_ERR(mem)) {
6528c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "ioremap error\n");
6538c2ecf20Sopenharmony_ci		return PTR_ERR(mem);
6548c2ecf20Sopenharmony_ci	}
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
6578c2ecf20Sopenharmony_ci	if (ret) {
6588c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to set 32-bit consistent dma\n");
6598c2ecf20Sopenharmony_ci		return ret;
6608c2ecf20Sopenharmony_ci	}
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	ab = ath11k_core_alloc(&pdev->dev, sizeof(struct ath11k_ahb),
6638c2ecf20Sopenharmony_ci			       ATH11K_BUS_AHB,
6648c2ecf20Sopenharmony_ci			       &ath11k_ahb_bus_params);
6658c2ecf20Sopenharmony_ci	if (!ab) {
6668c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to allocate ath11k base\n");
6678c2ecf20Sopenharmony_ci		return -ENOMEM;
6688c2ecf20Sopenharmony_ci	}
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	ab->hif.ops = &ath11k_ahb_hif_ops;
6718c2ecf20Sopenharmony_ci	ab->pdev = pdev;
6728c2ecf20Sopenharmony_ci	ab->hw_rev = (enum ath11k_hw_rev)of_id->data;
6738c2ecf20Sopenharmony_ci	ab->mem = mem;
6748c2ecf20Sopenharmony_ci	ab->mem_len = resource_size(mem_res);
6758c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, ab);
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	ret = ath11k_core_pre_init(ab);
6788c2ecf20Sopenharmony_ci	if (ret)
6798c2ecf20Sopenharmony_ci		goto err_core_free;
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	ret = ath11k_hal_srng_init(ab);
6828c2ecf20Sopenharmony_ci	if (ret)
6838c2ecf20Sopenharmony_ci		goto err_core_free;
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	ret = ath11k_ce_alloc_pipes(ab);
6868c2ecf20Sopenharmony_ci	if (ret) {
6878c2ecf20Sopenharmony_ci		ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
6888c2ecf20Sopenharmony_ci		goto err_hal_srng_deinit;
6898c2ecf20Sopenharmony_ci	}
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	ath11k_ahb_init_qmi_ce_config(ab);
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	ret = ath11k_core_get_rproc(ab);
6948c2ecf20Sopenharmony_ci	if (ret) {
6958c2ecf20Sopenharmony_ci		ath11k_err(ab, "failed to get rproc: %d\n", ret);
6968c2ecf20Sopenharmony_ci		goto err_ce_free;
6978c2ecf20Sopenharmony_ci	}
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	ret = ath11k_core_init(ab);
7008c2ecf20Sopenharmony_ci	if (ret) {
7018c2ecf20Sopenharmony_ci		ath11k_err(ab, "failed to init core: %d\n", ret);
7028c2ecf20Sopenharmony_ci		goto err_ce_free;
7038c2ecf20Sopenharmony_ci	}
7048c2ecf20Sopenharmony_ci
7058c2ecf20Sopenharmony_ci	ret = ath11k_ahb_config_irq(ab);
7068c2ecf20Sopenharmony_ci	if (ret) {
7078c2ecf20Sopenharmony_ci		ath11k_err(ab, "failed to configure irq: %d\n", ret);
7088c2ecf20Sopenharmony_ci		goto err_ce_free;
7098c2ecf20Sopenharmony_ci	}
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	return 0;
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_cierr_ce_free:
7148c2ecf20Sopenharmony_ci	ath11k_ce_free_pipes(ab);
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_cierr_hal_srng_deinit:
7178c2ecf20Sopenharmony_ci	ath11k_hal_srng_deinit(ab);
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_cierr_core_free:
7208c2ecf20Sopenharmony_ci	ath11k_core_free(ab);
7218c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, NULL);
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	return ret;
7248c2ecf20Sopenharmony_ci}
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_cistatic int ath11k_ahb_remove(struct platform_device *pdev)
7278c2ecf20Sopenharmony_ci{
7288c2ecf20Sopenharmony_ci	struct ath11k_base *ab = platform_get_drvdata(pdev);
7298c2ecf20Sopenharmony_ci	unsigned long left;
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	reinit_completion(&ab->driver_recovery);
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags)) {
7348c2ecf20Sopenharmony_ci		left = wait_for_completion_timeout(&ab->driver_recovery,
7358c2ecf20Sopenharmony_ci						   ATH11K_AHB_RECOVERY_TIMEOUT);
7368c2ecf20Sopenharmony_ci		if (!left)
7378c2ecf20Sopenharmony_ci			ath11k_warn(ab, "failed to receive recovery response completion\n");
7388c2ecf20Sopenharmony_ci	}
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
7418c2ecf20Sopenharmony_ci	cancel_work_sync(&ab->restart_work);
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci	ath11k_core_deinit(ab);
7448c2ecf20Sopenharmony_ci	ath11k_ahb_free_irq(ab);
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	ath11k_hal_srng_deinit(ab);
7478c2ecf20Sopenharmony_ci	ath11k_ce_free_pipes(ab);
7488c2ecf20Sopenharmony_ci	ath11k_core_free(ab);
7498c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, NULL);
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	return 0;
7528c2ecf20Sopenharmony_ci}
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_cistatic struct platform_driver ath11k_ahb_driver = {
7558c2ecf20Sopenharmony_ci	.driver         = {
7568c2ecf20Sopenharmony_ci		.name   = "ath11k",
7578c2ecf20Sopenharmony_ci		.of_match_table = ath11k_ahb_of_match,
7588c2ecf20Sopenharmony_ci	},
7598c2ecf20Sopenharmony_ci	.probe  = ath11k_ahb_probe,
7608c2ecf20Sopenharmony_ci	.remove = ath11k_ahb_remove,
7618c2ecf20Sopenharmony_ci};
7628c2ecf20Sopenharmony_ci
7638c2ecf20Sopenharmony_cistatic int ath11k_ahb_init(void)
7648c2ecf20Sopenharmony_ci{
7658c2ecf20Sopenharmony_ci	return platform_driver_register(&ath11k_ahb_driver);
7668c2ecf20Sopenharmony_ci}
7678c2ecf20Sopenharmony_cimodule_init(ath11k_ahb_init);
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_cistatic void ath11k_ahb_exit(void)
7708c2ecf20Sopenharmony_ci{
7718c2ecf20Sopenharmony_ci	platform_driver_unregister(&ath11k_ahb_driver);
7728c2ecf20Sopenharmony_ci}
7738c2ecf20Sopenharmony_cimodule_exit(ath11k_ahb_exit);
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN AHB devices");
7768c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
777