Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   1// SPDX-License-Identifier: BSD-3-Clause-Clear
   2/*
   3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
   4 */
   5
   6#include <linux/module.h>
   7#include <linux/platform_device.h>
   8#include <linux/of_device.h>
   9#include <linux/of.h>
  10#include <linux/dma-mapping.h>
  11#include "ahb.h"
  12#include "debug.h"
  13#include "hif.h"
  14#include <linux/remoteproc.h>
  15
  16static const struct of_device_id ath11k_ahb_of_match[] = {
  17	/* TODO: Should we change the compatible string to something similar
  18	 * to one that ath10k uses?
  19	 */
  20	{ .compatible = "qcom,ipq8074-wifi",
  21	  .data = (void *)ATH11K_HW_IPQ8074,
  22	},
  23	{ }
  24};
  25
  26MODULE_DEVICE_TABLE(of, ath11k_ahb_of_match);
  27
  28/* Target firmware's Copy Engine configuration. */
  29static const struct ce_pipe_config target_ce_config_wlan[] = {
  30	/* CE0: host->target HTC control and raw streams */
  31	{
  32		.pipenum = __cpu_to_le32(0),
  33		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
  34		.nentries = __cpu_to_le32(32),
  35		.nbytes_max = __cpu_to_le32(2048),
  36		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
  37		.reserved = __cpu_to_le32(0),
  38	},
  39
  40	/* CE1: target->host HTT + HTC control */
  41	{
  42		.pipenum = __cpu_to_le32(1),
  43		.pipedir = __cpu_to_le32(PIPEDIR_IN),
  44		.nentries = __cpu_to_le32(32),
  45		.nbytes_max = __cpu_to_le32(2048),
  46		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
  47		.reserved = __cpu_to_le32(0),
  48	},
  49
  50	/* CE2: target->host WMI */
  51	{
  52		.pipenum = __cpu_to_le32(2),
  53		.pipedir = __cpu_to_le32(PIPEDIR_IN),
  54		.nentries = __cpu_to_le32(32),
  55		.nbytes_max = __cpu_to_le32(2048),
  56		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
  57		.reserved = __cpu_to_le32(0),
  58	},
  59
  60	/* CE3: host->target WMI */
  61	{
  62		.pipenum = __cpu_to_le32(3),
  63		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
  64		.nentries = __cpu_to_le32(32),
  65		.nbytes_max = __cpu_to_le32(2048),
  66		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
  67		.reserved = __cpu_to_le32(0),
  68	},
  69
  70	/* CE4: host->target HTT */
  71	{
  72		.pipenum = __cpu_to_le32(4),
  73		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
  74		.nentries = __cpu_to_le32(256),
  75		.nbytes_max = __cpu_to_le32(256),
  76		.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
  77		.reserved = __cpu_to_le32(0),
  78	},
  79
  80	/* CE5: target->host Pktlog */
  81	{
  82		.pipenum = __cpu_to_le32(5),
  83		.pipedir = __cpu_to_le32(PIPEDIR_IN),
  84		.nentries = __cpu_to_le32(32),
  85		.nbytes_max = __cpu_to_le32(2048),
  86		.flags = __cpu_to_le32(0),
  87		.reserved = __cpu_to_le32(0),
  88	},
  89
  90	/* CE6: Reserved for target autonomous hif_memcpy */
  91	{
  92		.pipenum = __cpu_to_le32(6),
  93		.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
  94		.nentries = __cpu_to_le32(32),
  95		.nbytes_max = __cpu_to_le32(65535),
  96		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
  97		.reserved = __cpu_to_le32(0),
  98	},
  99
 100	/* CE7 used only by Host */
 101	{
 102		.pipenum = __cpu_to_le32(7),
 103		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
 104		.nentries = __cpu_to_le32(32),
 105		.nbytes_max = __cpu_to_le32(2048),
 106		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
 107		.reserved = __cpu_to_le32(0),
 108	},
 109
 110	/* CE8 target->host used only by IPA */
 111	{
 112		.pipenum = __cpu_to_le32(8),
 113		.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
 114		.nentries = __cpu_to_le32(32),
 115		.nbytes_max = __cpu_to_le32(65535),
 116		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
 117		.reserved = __cpu_to_le32(0),
 118	},
 119
 120	/* CE9 host->target HTT */
 121	{
 122		.pipenum = __cpu_to_le32(9),
 123		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
 124		.nentries = __cpu_to_le32(32),
 125		.nbytes_max = __cpu_to_le32(2048),
 126		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
 127		.reserved = __cpu_to_le32(0),
 128	},
 129
 130	/* CE10 target->host HTT */
 131	{
 132		.pipenum = __cpu_to_le32(10),
 133		.pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
 134		.nentries = __cpu_to_le32(0),
 135		.nbytes_max = __cpu_to_le32(0),
 136		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
 137		.reserved = __cpu_to_le32(0),
 138	},
 139
 140	/* CE11 Not used */
 141	{
 142		.pipenum = __cpu_to_le32(0),
 143		.pipedir = __cpu_to_le32(0),
 144		.nentries = __cpu_to_le32(0),
 145		.nbytes_max = __cpu_to_le32(0),
 146		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
 147		.reserved = __cpu_to_le32(0),
 148	},
 149};
 150
 151/* Map from service/endpoint to Copy Engine.
 152 * This table is derived from the CE_PCI TABLE, above.
 153 * It is passed to the Target at startup for use by firmware.
 154 */
 155static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
 156	{
 157		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
 158		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
 159		.pipenum = __cpu_to_le32(3),
 160	},
 161	{
 162		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
 163		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
 164		.pipenum = __cpu_to_le32(2),
 165	},
 166	{
 167		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
 168		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
 169		.pipenum = __cpu_to_le32(3),
 170	},
 171	{
 172		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
 173		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
 174		.pipenum = __cpu_to_le32(2),
 175	},
 176	{
 177		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
 178		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
 179		.pipenum = __cpu_to_le32(3),
 180	},
 181	{
 182		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
 183		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
 184		.pipenum = __cpu_to_le32(2),
 185	},
 186	{
 187		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
 188		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
 189		.pipenum = __cpu_to_le32(3),
 190	},
 191	{
 192		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
 193		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
 194		.pipenum = __cpu_to_le32(2),
 195	},
 196	{
 197		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
 198		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
 199		.pipenum = __cpu_to_le32(3),
 200	},
 201	{
 202		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
 203		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
 204		.pipenum = __cpu_to_le32(2),
 205	},
 206	{
 207		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
 208		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
 209		.pipenum = __cpu_to_le32(7),
 210	},
 211	{
 212		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
 213		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
 214		.pipenum = __cpu_to_le32(2),
 215	},
 216	{
 217		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
 218		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
 219		.pipenum = __cpu_to_le32(9),
 220	},
 221	{
 222		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
 223		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
 224		.pipenum = __cpu_to_le32(2),
 225	},
 226	{
 227		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
 228		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
 229		.pipenum = __cpu_to_le32(0),
 230	},
 231	{
 232		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
 233		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
 234		.pipenum = __cpu_to_le32(1),
 235	},
 236	{ /* not used */
 237		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
 238		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
 239		.pipenum = __cpu_to_le32(0),
 240	},
 241	{ /* not used */
 242		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
 243		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
 244		.pipenum = __cpu_to_le32(1),
 245	},
 246	{
 247		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
 248		.pipedir = __cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
 249		.pipenum = __cpu_to_le32(4),
 250	},
 251	{
 252		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
 253		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
 254		.pipenum = __cpu_to_le32(1),
 255	},
 256	{
 257		.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_PKT_LOG),
 258		.pipedir = __cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
 259		.pipenum = __cpu_to_le32(5),
 260	},
 261
 262	/* (Additions here) */
 263
 264	{ /* terminator entry */ }
 265};
 266
 267#define ATH11K_IRQ_CE0_OFFSET 4
 268
 269static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
 270	"misc-pulse1",
 271	"misc-latch",
 272	"sw-exception",
 273	"watchdog",
 274	"ce0",
 275	"ce1",
 276	"ce2",
 277	"ce3",
 278	"ce4",
 279	"ce5",
 280	"ce6",
 281	"ce7",
 282	"ce8",
 283	"ce9",
 284	"ce10",
 285	"ce11",
 286	"host2wbm-desc-feed",
 287	"host2reo-re-injection",
 288	"host2reo-command",
 289	"host2rxdma-monitor-ring3",
 290	"host2rxdma-monitor-ring2",
 291	"host2rxdma-monitor-ring1",
 292	"reo2ost-exception",
 293	"wbm2host-rx-release",
 294	"reo2host-status",
 295	"reo2host-destination-ring4",
 296	"reo2host-destination-ring3",
 297	"reo2host-destination-ring2",
 298	"reo2host-destination-ring1",
 299	"rxdma2host-monitor-destination-mac3",
 300	"rxdma2host-monitor-destination-mac2",
 301	"rxdma2host-monitor-destination-mac1",
 302	"ppdu-end-interrupts-mac3",
 303	"ppdu-end-interrupts-mac2",
 304	"ppdu-end-interrupts-mac1",
 305	"rxdma2host-monitor-status-ring-mac3",
 306	"rxdma2host-monitor-status-ring-mac2",
 307	"rxdma2host-monitor-status-ring-mac1",
 308	"host2rxdma-host-buf-ring-mac3",
 309	"host2rxdma-host-buf-ring-mac2",
 310	"host2rxdma-host-buf-ring-mac1",
 311	"rxdma2host-destination-ring-mac3",
 312	"rxdma2host-destination-ring-mac2",
 313	"rxdma2host-destination-ring-mac1",
 314	"host2tcl-input-ring4",
 315	"host2tcl-input-ring3",
 316	"host2tcl-input-ring2",
 317	"host2tcl-input-ring1",
 318	"wbm2host-tx-completions-ring3",
 319	"wbm2host-tx-completions-ring2",
 320	"wbm2host-tx-completions-ring1",
 321	"tcl2host-status-ring",
 322};
 323
 324#define ATH11K_TX_RING_MASK_0 0x1
 325#define ATH11K_TX_RING_MASK_1 0x2
 326#define ATH11K_TX_RING_MASK_2 0x4
 327
 328#define ATH11K_RX_RING_MASK_0 0x1
 329#define ATH11K_RX_RING_MASK_1 0x2
 330#define ATH11K_RX_RING_MASK_2 0x4
 331#define ATH11K_RX_RING_MASK_3 0x8
 332
 333#define ATH11K_RX_ERR_RING_MASK_0 0x1
 334
 335#define ATH11K_RX_WBM_REL_RING_MASK_0 0x1
 336
 337#define ATH11K_REO_STATUS_RING_MASK_0 0x1
 338
 339#define ATH11K_RXDMA2HOST_RING_MASK_0 0x1
 340#define ATH11K_RXDMA2HOST_RING_MASK_1 0x2
 341#define ATH11K_RXDMA2HOST_RING_MASK_2 0x4
 342
 343#define ATH11K_HOST2RXDMA_RING_MASK_0 0x1
 344#define ATH11K_HOST2RXDMA_RING_MASK_1 0x2
 345#define ATH11K_HOST2RXDMA_RING_MASK_2 0x4
 346
 347#define ATH11K_RX_MON_STATUS_RING_MASK_0 0x1
 348#define ATH11K_RX_MON_STATUS_RING_MASK_1 0x2
 349#define ATH11K_RX_MON_STATUS_RING_MASK_2 0x4
 350
 351const u8 ath11k_tx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
 352	ATH11K_TX_RING_MASK_0,
 353	ATH11K_TX_RING_MASK_1,
 354	ATH11K_TX_RING_MASK_2,
 355};
 356
 357const u8 rx_mon_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
 358	0, 0, 0, 0,
 359	ATH11K_RX_MON_STATUS_RING_MASK_0,
 360	ATH11K_RX_MON_STATUS_RING_MASK_1,
 361	ATH11K_RX_MON_STATUS_RING_MASK_2,
 362};
 363
 364const u8 ath11k_rx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
 365	0, 0, 0, 0, 0, 0, 0,
 366	ATH11K_RX_RING_MASK_0,
 367	ATH11K_RX_RING_MASK_1,
 368	ATH11K_RX_RING_MASK_2,
 369	ATH11K_RX_RING_MASK_3,
 370};
 371
 372const u8 ath11k_rx_err_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
 373	ATH11K_RX_ERR_RING_MASK_0,
 374};
 375
 376const u8 ath11k_rx_wbm_rel_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
 377	ATH11K_RX_WBM_REL_RING_MASK_0,
 378};
 379
 380const u8 ath11k_reo_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
 381	ATH11K_REO_STATUS_RING_MASK_0,
 382};
 383
 384const u8 ath11k_rxdma2host_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
 385	ATH11K_RXDMA2HOST_RING_MASK_0,
 386	ATH11K_RXDMA2HOST_RING_MASK_1,
 387	ATH11K_RXDMA2HOST_RING_MASK_2,
 388};
 389
 390const u8 ath11k_host2rxdma_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
 391	ATH11K_HOST2RXDMA_RING_MASK_0,
 392	ATH11K_HOST2RXDMA_RING_MASK_1,
 393	ATH11K_HOST2RXDMA_RING_MASK_2,
 394};
 395
 396/* enum ext_irq_num - irq numbers that can be used by external modules
 397 * like datapath
 398 */
 399enum ext_irq_num {
 400	host2wbm_desc_feed = 16,
 401	host2reo_re_injection,
 402	host2reo_command,
 403	host2rxdma_monitor_ring3,
 404	host2rxdma_monitor_ring2,
 405	host2rxdma_monitor_ring1,
 406	reo2host_exception,
 407	wbm2host_rx_release,
 408	reo2host_status,
 409	reo2host_destination_ring4,
 410	reo2host_destination_ring3,
 411	reo2host_destination_ring2,
 412	reo2host_destination_ring1,
 413	rxdma2host_monitor_destination_mac3,
 414	rxdma2host_monitor_destination_mac2,
 415	rxdma2host_monitor_destination_mac1,
 416	ppdu_end_interrupts_mac3,
 417	ppdu_end_interrupts_mac2,
 418	ppdu_end_interrupts_mac1,
 419	rxdma2host_monitor_status_ring_mac3,
 420	rxdma2host_monitor_status_ring_mac2,
 421	rxdma2host_monitor_status_ring_mac1,
 422	host2rxdma_host_buf_ring_mac3,
 423	host2rxdma_host_buf_ring_mac2,
 424	host2rxdma_host_buf_ring_mac1,
 425	rxdma2host_destination_ring_mac3,
 426	rxdma2host_destination_ring_mac2,
 427	rxdma2host_destination_ring_mac1,
 428	host2tcl_input_ring4,
 429	host2tcl_input_ring3,
 430	host2tcl_input_ring2,
 431	host2tcl_input_ring1,
 432	wbm2host_tx_completions_ring3,
 433	wbm2host_tx_completions_ring2,
 434	wbm2host_tx_completions_ring1,
 435	tcl2host_status_ring,
 436};
 437
 438static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset)
 439{
 440	return ioread32(ab->mem + offset);
 441}
 442
 443static inline void ath11k_ahb_write32(struct ath11k_base *ab, u32 offset, u32 value)
 444{
 445	iowrite32(value, ab->mem + offset);
 446}
 447
 448static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab)
 449{
 450	int i;
 451
 452	for (i = 0; i < CE_COUNT; i++) {
 453		struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
 454
 455		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
 456			continue;
 457
 458		tasklet_kill(&ce_pipe->intr_tq);
 459	}
 460}
 461
 462static void ath11k_ahb_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
 463{
 464	int i;
 465
 466	for (i = 0; i < irq_grp->num_irq; i++)
 467		disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
 468}
 469
 470static void __ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
 471{
 472	int i;
 473
 474	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
 475		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
 476
 477		ath11k_ahb_ext_grp_disable(irq_grp);
 478
 479		napi_synchronize(&irq_grp->napi);
 480		napi_disable(&irq_grp->napi);
 481	}
 482}
 483
 484static void ath11k_ahb_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
 485{
 486	int i;
 487
 488	for (i = 0; i < irq_grp->num_irq; i++)
 489		enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
 490}
 491
 492static void ath11k_ahb_setbit32(struct ath11k_base *ab, u8 bit, u32 offset)
 493{
 494	u32 val;
 495
 496	val = ath11k_ahb_read32(ab, offset);
 497	ath11k_ahb_write32(ab, offset, val | BIT(bit));
 498}
 499
 500static void ath11k_ahb_clearbit32(struct ath11k_base *ab, u8 bit, u32 offset)
 501{
 502	u32 val;
 503
 504	val = ath11k_ahb_read32(ab, offset);
 505	ath11k_ahb_write32(ab, offset, val & ~BIT(bit));
 506}
 507
 508static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
 509{
 510	const struct ce_pipe_config *ce_config;
 511
 512	ce_config = &target_ce_config_wlan[ce_id];
 513	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
 514		ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
 515
 516	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) {
 517		ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
 518		ath11k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
 519				    CE_HOST_IE_3_ADDRESS);
 520	}
 521}
 522
 523static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
 524{
 525	const struct ce_pipe_config *ce_config;
 526
 527	ce_config = &target_ce_config_wlan[ce_id];
 528	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
 529		ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
 530
 531	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) {
 532		ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
 533		ath11k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
 534				      CE_HOST_IE_3_ADDRESS);
 535	}
 536}
 537
 538static void ath11k_ahb_sync_ce_irqs(struct ath11k_base *ab)
 539{
 540	int i;
 541	int irq_idx;
 542
 543	for (i = 0; i < CE_COUNT; i++) {
 544		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
 545			continue;
 546
 547		irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
 548		synchronize_irq(ab->irq_num[irq_idx]);
 549	}
 550}
 551
 552static void ath11k_ahb_sync_ext_irqs(struct ath11k_base *ab)
 553{
 554	int i, j;
 555	int irq_idx;
 556
 557	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
 558		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
 559
 560		for (j = 0; j < irq_grp->num_irq; j++) {
 561			irq_idx = irq_grp->irqs[j];
 562			synchronize_irq(ab->irq_num[irq_idx]);
 563		}
 564	}
 565}
 566
 567static void ath11k_ahb_ce_irqs_enable(struct ath11k_base *ab)
 568{
 569	int i;
 570
 571	for (i = 0; i < CE_COUNT; i++) {
 572		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
 573			continue;
 574		ath11k_ahb_ce_irq_enable(ab, i);
 575	}
 576}
 577
 578static void ath11k_ahb_ce_irqs_disable(struct ath11k_base *ab)
 579{
 580	int i;
 581
 582	for (i = 0; i < CE_COUNT; i++) {
 583		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
 584			continue;
 585		ath11k_ahb_ce_irq_disable(ab, i);
 586	}
 587}
 588
 589static int ath11k_ahb_start(struct ath11k_base *ab)
 590{
 591	ath11k_ahb_ce_irqs_enable(ab);
 592	ath11k_ce_rx_post_buf(ab);
 593
 594	return 0;
 595}
 596
 597static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab)
 598{
 599	int i;
 600
 601	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
 602		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
 603
 604		napi_enable(&irq_grp->napi);
 605		ath11k_ahb_ext_grp_enable(irq_grp);
 606	}
 607}
 608
 609static void ath11k_ahb_ext_irq_disable(struct ath11k_base *ab)
 610{
 611	__ath11k_ahb_ext_irq_disable(ab);
 612	ath11k_ahb_sync_ext_irqs(ab);
 613}
 614
 615static void ath11k_ahb_stop(struct ath11k_base *ab)
 616{
 617	if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags))
 618		ath11k_ahb_ce_irqs_disable(ab);
 619	ath11k_ahb_sync_ce_irqs(ab);
 620	ath11k_ahb_kill_tasklets(ab);
 621	del_timer_sync(&ab->rx_replenish_retry);
 622	ath11k_ce_cleanup_pipes(ab);
 623}
 624
 625static int ath11k_ahb_power_up(struct ath11k_base *ab)
 626{
 627	int ret;
 628
 629	ret = rproc_boot(ab->tgt_rproc);
 630	if (ret)
 631		ath11k_err(ab, "failed to boot the remote processor Q6\n");
 632
 633	return ret;
 634}
 635
 636static void ath11k_ahb_power_down(struct ath11k_base *ab)
 637{
 638	rproc_shutdown(ab->tgt_rproc);
 639}
 640
 641static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
 642{
 643	struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
 644
 645	cfg->tgt_ce_len = ARRAY_SIZE(target_ce_config_wlan) - 1;
 646	cfg->tgt_ce = target_ce_config_wlan;
 647	cfg->svc_to_ce_map_len = ARRAY_SIZE(target_service_to_ce_map_wlan);
 648	cfg->svc_to_ce_map = target_service_to_ce_map_wlan;
 649}
 650
 651static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab)
 652{
 653	int i, j;
 654
 655	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
 656		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
 657
 658		for (j = 0; j < irq_grp->num_irq; j++)
 659			free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);
 660	}
 661}
 662
 663static void ath11k_ahb_free_irq(struct ath11k_base *ab)
 664{
 665	int irq_idx;
 666	int i;
 667
 668	for (i = 0; i < CE_COUNT; i++) {
 669		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
 670			continue;
 671		irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
 672		free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
 673	}
 674
 675	ath11k_ahb_free_ext_irq(ab);
 676}
 677
 678static void ath11k_ahb_ce_tasklet(unsigned long data)
 679{
 680	struct ath11k_ce_pipe *ce_pipe = (struct ath11k_ce_pipe *)data;
 681
 682	ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
 683
 684	ath11k_ahb_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
 685}
 686
 687static irqreturn_t ath11k_ahb_ce_interrupt_handler(int irq, void *arg)
 688{
 689	struct ath11k_ce_pipe *ce_pipe = arg;
 690
 691	/* last interrupt received for this CE */
 692	ce_pipe->timestamp = jiffies;
 693
 694	ath11k_ahb_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
 695
 696	tasklet_schedule(&ce_pipe->intr_tq);
 697
 698	return IRQ_HANDLED;
 699}
 700
 701static int ath11k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget)
 702{
 703	struct ath11k_ext_irq_grp *irq_grp = container_of(napi,
 704						struct ath11k_ext_irq_grp,
 705						napi);
 706	struct ath11k_base *ab = irq_grp->ab;
 707	int work_done;
 708
 709	work_done = ath11k_dp_service_srng(ab, irq_grp, budget);
 710	if (work_done < budget) {
 711		napi_complete_done(napi, work_done);
 712		ath11k_ahb_ext_grp_enable(irq_grp);
 713	}
 714
 715	if (work_done > budget)
 716		work_done = budget;
 717
 718	return work_done;
 719}
 720
 721static irqreturn_t ath11k_ahb_ext_interrupt_handler(int irq, void *arg)
 722{
 723	struct ath11k_ext_irq_grp *irq_grp = arg;
 724
 725	/* last interrupt received for this group */
 726	irq_grp->timestamp = jiffies;
 727
 728	ath11k_ahb_ext_grp_disable(irq_grp);
 729
 730	napi_schedule(&irq_grp->napi);
 731
 732	return IRQ_HANDLED;
 733}
 734
 735static int ath11k_ahb_ext_irq_config(struct ath11k_base *ab)
 736{
 737	int i, j;
 738	int irq;
 739	int ret;
 740
 741	for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
 742		struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
 743		u32 num_irq = 0;
 744
 745		irq_grp->ab = ab;
 746		irq_grp->grp_id = i;
 747		init_dummy_netdev(&irq_grp->napi_ndev);
 748		netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
 749			       ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT);
 750
 751		for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) {
 752			if (ath11k_tx_ring_mask[i] & BIT(j)) {
 753				irq_grp->irqs[num_irq++] =
 754					wbm2host_tx_completions_ring1 - j;
 755			}
 756
 757			if (ath11k_rx_ring_mask[i] & BIT(j)) {
 758				irq_grp->irqs[num_irq++] =
 759					reo2host_destination_ring1 - j;
 760			}
 761
 762			if (ath11k_rx_err_ring_mask[i] & BIT(j))
 763				irq_grp->irqs[num_irq++] = reo2host_exception;
 764
 765			if (ath11k_rx_wbm_rel_ring_mask[i] & BIT(j))
 766				irq_grp->irqs[num_irq++] = wbm2host_rx_release;
 767
 768			if (ath11k_reo_status_ring_mask[i] & BIT(j))
 769				irq_grp->irqs[num_irq++] = reo2host_status;
 770
 771			if (j < MAX_RADIOS) {
 772				if (ath11k_rxdma2host_ring_mask[i] & BIT(j)) {
 773					irq_grp->irqs[num_irq++] =
 774						rxdma2host_destination_ring_mac1
 775						- ath11k_core_get_hw_mac_id(ab, j);
 776				}
 777
 778				if (ath11k_host2rxdma_ring_mask[i] & BIT(j)) {
 779					irq_grp->irqs[num_irq++] =
 780						host2rxdma_host_buf_ring_mac1
 781						- ath11k_core_get_hw_mac_id(ab, j);
 782				}
 783
 784				if (rx_mon_status_ring_mask[i] & BIT(j)) {
 785					irq_grp->irqs[num_irq++] =
 786						ppdu_end_interrupts_mac1 -
 787						ath11k_core_get_hw_mac_id(ab, j);
 788					irq_grp->irqs[num_irq++] =
 789						rxdma2host_monitor_status_ring_mac1 -
 790						ath11k_core_get_hw_mac_id(ab, j);
 791				}
 792			}
 793		}
 794		irq_grp->num_irq = num_irq;
 795
 796		for (j = 0; j < irq_grp->num_irq; j++) {
 797			int irq_idx = irq_grp->irqs[j];
 798
 799			irq = platform_get_irq_byname(ab->pdev,
 800						      irq_name[irq_idx]);
 801			ab->irq_num[irq_idx] = irq;
 802			irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
 803			ret = request_irq(irq, ath11k_ahb_ext_interrupt_handler,
 804					  IRQF_TRIGGER_RISING,
 805					  irq_name[irq_idx], irq_grp);
 806			if (ret) {
 807				ath11k_err(ab, "failed request_irq for %d\n",
 808					   irq);
 809			}
 810		}
 811	}
 812
 813	return 0;
 814}
 815
 816static int ath11k_ahb_config_irq(struct ath11k_base *ab)
 817{
 818	int irq, irq_idx, i;
 819	int ret;
 820
 821	/* Configure CE irqs */
 822	for (i = 0; i < CE_COUNT; i++) {
 823		struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
 824
 825		if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
 826			continue;
 827
 828		irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
 829
 830		tasklet_init(&ce_pipe->intr_tq, ath11k_ahb_ce_tasklet,
 831			     (unsigned long)ce_pipe);
 832		irq = platform_get_irq_byname(ab->pdev, irq_name[irq_idx]);
 833		ret = request_irq(irq, ath11k_ahb_ce_interrupt_handler,
 834				  IRQF_TRIGGER_RISING, irq_name[irq_idx],
 835				  ce_pipe);
 836		if (ret)
 837			return ret;
 838
 839		ab->irq_num[irq_idx] = irq;
 840	}
 841
 842	/* Configure external interrupts */
 843	ret = ath11k_ahb_ext_irq_config(ab);
 844
 845	return ret;
 846}
 847
 848static int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
 849					  u8 *ul_pipe, u8 *dl_pipe)
 850{
 851	const struct service_to_pipe *entry;
 852	bool ul_set = false, dl_set = false;
 853	int i;
 854
 855	for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) {
 856		entry = &target_service_to_ce_map_wlan[i];
 857
 858		if (__le32_to_cpu(entry->service_id) != service_id)
 859			continue;
 860
 861		switch (__le32_to_cpu(entry->pipedir)) {
 862		case PIPEDIR_NONE:
 863			break;
 864		case PIPEDIR_IN:
 865			WARN_ON(dl_set);
 866			*dl_pipe = __le32_to_cpu(entry->pipenum);
 867			dl_set = true;
 868			break;
 869		case PIPEDIR_OUT:
 870			WARN_ON(ul_set);
 871			*ul_pipe = __le32_to_cpu(entry->pipenum);
 872			ul_set = true;
 873			break;
 874		case PIPEDIR_INOUT:
 875			WARN_ON(dl_set);
 876			WARN_ON(ul_set);
 877			*dl_pipe = __le32_to_cpu(entry->pipenum);
 878			*ul_pipe = __le32_to_cpu(entry->pipenum);
 879			dl_set = true;
 880			ul_set = true;
 881			break;
 882		}
 883	}
 884
 885	if (WARN_ON(!ul_set || !dl_set))
 886		return -ENOENT;
 887
 888	return 0;
 889}
 890
 891static const struct ath11k_hif_ops ath11k_ahb_hif_ops = {
 892	.start = ath11k_ahb_start,
 893	.stop = ath11k_ahb_stop,
 894	.read32 = ath11k_ahb_read32,
 895	.write32 = ath11k_ahb_write32,
 896	.irq_enable = ath11k_ahb_ext_irq_enable,
 897	.irq_disable = ath11k_ahb_ext_irq_disable,
 898	.map_service_to_pipe = ath11k_ahb_map_service_to_pipe,
 899	.power_down = ath11k_ahb_power_down,
 900	.power_up = ath11k_ahb_power_up,
 901};
 902
 903static int ath11k_ahb_probe(struct platform_device *pdev)
 904{
 905	struct ath11k_base *ab;
 906	const struct of_device_id *of_id;
 907	struct resource *mem_res;
 908	void __iomem *mem;
 909	int ret;
 910
 911	of_id = of_match_device(ath11k_ahb_of_match, &pdev->dev);
 912	if (!of_id) {
 913		dev_err(&pdev->dev, "failed to find matching device tree id\n");
 914		return -EINVAL;
 915	}
 916
 917	mem = devm_platform_get_and_ioremap_resource(pdev, 0, &mem_res);
 918	if (IS_ERR(mem)) {
 919		dev_err(&pdev->dev, "ioremap error\n");
 920		return PTR_ERR(mem);
 921	}
 922
 923	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
 924	if (ret) {
 925		dev_err(&pdev->dev, "failed to set 32-bit consistent dma\n");
 926		return ret;
 927	}
 928
 929	ab = ath11k_core_alloc(&pdev->dev, 0, ATH11K_BUS_AHB);
 930	if (!ab) {
 931		dev_err(&pdev->dev, "failed to allocate ath11k base\n");
 932		return -ENOMEM;
 933	}
 934
 935	ab->hif.ops = &ath11k_ahb_hif_ops;
 936	ab->pdev = pdev;
 937	ab->hw_rev = (enum ath11k_hw_rev)of_id->data;
 938	ab->mem = mem;
 939	ab->mem_len = resource_size(mem_res);
 940	platform_set_drvdata(pdev, ab);
 941
 942	ret = ath11k_hal_srng_init(ab);
 943	if (ret)
 944		goto err_core_free;
 945
 946	ret = ath11k_ce_alloc_pipes(ab);
 947	if (ret) {
 948		ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
 949		goto err_hal_srng_deinit;
 950	}
 951
 952	ath11k_ahb_init_qmi_ce_config(ab);
 953
 954	ret = ath11k_ahb_config_irq(ab);
 955	if (ret) {
 956		ath11k_err(ab, "failed to configure irq: %d\n", ret);
 957		goto err_ce_free;
 958	}
 959
 960	ret = ath11k_core_init(ab);
 961	if (ret) {
 962		ath11k_err(ab, "failed to init core: %d\n", ret);
 963		goto err_ce_free;
 964	}
 965
 966	return 0;
 967
 968err_ce_free:
 969	ath11k_ce_free_pipes(ab);
 970
 971err_hal_srng_deinit:
 972	ath11k_hal_srng_deinit(ab);
 973
 974err_core_free:
 975	ath11k_core_free(ab);
 976	platform_set_drvdata(pdev, NULL);
 977
 978	return ret;
 979}
 980
 981static int ath11k_ahb_remove(struct platform_device *pdev)
 982{
 983	struct ath11k_base *ab = platform_get_drvdata(pdev);
 984
 985	reinit_completion(&ab->driver_recovery);
 986
 987	if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags))
 988		wait_for_completion_timeout(&ab->driver_recovery,
 989					    ATH11K_AHB_RECOVERY_TIMEOUT);
 990
 991	set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
 992	cancel_work_sync(&ab->restart_work);
 993
 994	ath11k_core_deinit(ab);
 995	ath11k_ahb_free_irq(ab);
 996
 997	ath11k_hal_srng_deinit(ab);
 998	ath11k_ce_free_pipes(ab);
 999	ath11k_core_free(ab);
1000	platform_set_drvdata(pdev, NULL);
1001
1002	return 0;
1003}
1004
1005static struct platform_driver ath11k_ahb_driver = {
1006	.driver         = {
1007		.name   = "ath11k",
1008		.of_match_table = ath11k_ahb_of_match,
1009	},
1010	.probe  = ath11k_ahb_probe,
1011	.remove = ath11k_ahb_remove,
1012};
1013
1014static int ath11k_ahb_init(void)
1015{
1016	return platform_driver_register(&ath11k_ahb_driver);
1017}
1018module_init(ath11k_ahb_init);
1019
1020static void ath11k_ahb_exit(void)
1021{
1022	platform_driver_unregister(&ath11k_ahb_driver);
1023}
1024module_exit(ath11k_ahb_exit);
1025
1026MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax wireless chip");
1027MODULE_LICENSE("Dual BSD/GPL");