Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bdd8861b authored by Rakesh Pillai's avatar Rakesh Pillai Committed by Gerrit - the friendly Code Review server
Browse files

ath10k: Add support for shadow register for WNC3990



WCN3990 needs shadow register write operation support
for copy engine for regular operation in powersave mode.
Add support for copy engine shadow register write in
datapath tx for WCN3990

CRs-Fixed: 2008518
Change-Id: Ie90ff74984021fa47070e08b2fc53ad5da46cf35
Signed-off-by: default avatarRakesh Pillai <pillair@codeaurora.org>
parent 7066afbb
Loading
Loading
Loading
Loading
+108 −3
Original line number Diff line number Diff line
/*
 * Copyright (c) 2005-2011 Atheros Communications Inc.
 * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
 * Copyright (c) 2011-2013, 2017 Qualcomm Atheros, Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
@@ -90,6 +90,20 @@ static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar,
	return ar->bus_read32(ar, ce_ctrl_addr + CURRENT_SRRI_ADDRESS);
}

static inline void ath10k_ce_shadow_src_ring_write_index_set(struct ath10k *ar,
							     u32 ce_ctrl_addr,
							     unsigned int n)
{
	ar->bus_write32(ar, shadow_sr_wr_ind_addr(ar, ce_ctrl_addr), n);
}

static inline void ath10k_ce_shadow_dest_ring_write_index_set(struct ath10k *ar,
							      u32 ce_ctrl_addr,
							      unsigned int n)
{
	ar->bus_write32(ar, shadow_dst_wr_ind_addr(ar, ce_ctrl_addr), n);
}

static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar,
						    u32 ce_ctrl_addr,
						    unsigned int addr)
@@ -259,6 +273,72 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
	ar->bus_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask);
}

u32 shadow_sr_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr)
{
	u32 addr = 0;
	u32 ce = COPY_ENGINE_ID(ctrl_addr);

	switch (ce) {
	case 0:
		addr = SHADOW_VALUE0;
		break;
	case 3:
		addr = SHADOW_VALUE3;
		break;
	case 4:
		addr = SHADOW_VALUE4;
		break;
	case 5:
		addr = SHADOW_VALUE5;
		break;
	case 7:
		addr = SHADOW_VALUE7;
		break;
	default:
		ath10k_err(ar, "invalid CE ctrl_addr (CE=%d)", ce);
		WARN_ON(1);
	}
	return addr;
}

u32 shadow_dst_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr)
{
	u32 addr = 0;
	u32 ce = COPY_ENGINE_ID(ctrl_addr);

	switch (ce) {
	case 1:
		addr = SHADOW_VALUE13;
		break;
	case 2:
		addr = SHADOW_VALUE14;
		break;
	case 5:
		addr = SHADOW_VALUE17;
		break;
	case 7:
		addr = SHADOW_VALUE19;
		break;
	case 8:
		addr = SHADOW_VALUE20;
		break;
	case 9:
		addr = SHADOW_VALUE21;
		break;
	case 10:
		addr = SHADOW_VALUE22;
		break;
	case 11:
		addr = SHADOW_VALUE23;
		break;
	default:
		ath10k_err(ar, "invalid CE ctrl_addr (CE=%d)", ce);
		WARN_ON(1);
	}

	return addr;
}

/*
 * Guts of ath10k_ce_send, used by both ath10k_ce_send and
 * ath10k_ce_sendlist_send.
@@ -325,8 +405,14 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
	write_index = CE_RING_IDX_INCR(nentries_mask, write_index);

	/* WORKAROUND */
	if (!(flags & CE_SEND_FLAG_GATHER))
		ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, write_index);
	if (!(flags & CE_SEND_FLAG_GATHER)) {
		if (QCA_REV_WCN3990(ar))
			ath10k_ce_shadow_src_ring_write_index_set(ar, ctrl_addr,
								  write_index);
		else
			ath10k_ce_src_ring_write_index_set(ar, ctrl_addr,
							   write_index);
	}

	src_ring->write_index = write_index;
exit:
@@ -957,6 +1043,24 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id,
			src_ring->base_addr_ce_space_unaligned,
			CE_DESC_RING_ALIGN);

	src_ring->shadow_base_unaligned = kzalloc(
					  nentries * sizeof(struct ce_desc),
					  GFP_KERNEL);

	if (!src_ring->shadow_base_unaligned) {
		dma_free_coherent(ar->dev,
				  (nentries * sizeof(struct ce_desc) +
				   CE_DESC_RING_ALIGN),
				   src_ring->base_addr_owner_space_unaligned,
				   base_addr);
		kfree(src_ring);
		return ERR_PTR(-ENOMEM);
	}

	src_ring->shadow_base = (struct ce_desc *)PTR_ALIGN(
				src_ring->shadow_base_unaligned,
				CE_DESC_RING_ALIGN);

	return src_ring;
}

@@ -1135,6 +1239,7 @@ void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id)
			((struct ath10k_ce_pipe *)ar->ce_states + ce_id);

	if (ce_state->src_ring) {
		kfree(ce_state->src_ring->shadow_base_unaligned);
		dma_free_coherent(ar->dev,
				  (ce_state->src_ring->nentries *
				   sizeof(struct ce_desc) +
+61 −0
Original line number Diff line number Diff line
@@ -120,6 +120,9 @@ struct ath10k_ce_ring {
	/* CE address space */
	u32 base_addr_ce_space;

	char *shadow_base_unaligned;
	struct ce_desc *shadow_base;

	/* keep last */
	void *per_transfer_context[0];
};
@@ -143,6 +146,61 @@ struct ath10k_ce_pipe {
/* Copy Engine settable attributes */
struct ce_attr;

#define SHADOW_VALUE0       (ar->shadow_reg_value->shadow_reg_value_0)
#define SHADOW_VALUE1       (ar->shadow_reg_value->shadow_reg_value_1)
#define SHADOW_VALUE2       (ar->shadow_reg_value->shadow_reg_value_2)
#define SHADOW_VALUE3       (ar->shadow_reg_value->shadow_reg_value_3)
#define SHADOW_VALUE4       (ar->shadow_reg_value->shadow_reg_value_4)
#define SHADOW_VALUE5       (ar->shadow_reg_value->shadow_reg_value_5)
#define SHADOW_VALUE6       (ar->shadow_reg_value->shadow_reg_value_6)
#define SHADOW_VALUE7       (ar->shadow_reg_value->shadow_reg_value_7)
#define SHADOW_VALUE8       (ar->shadow_reg_value->shadow_reg_value_8)
#define SHADOW_VALUE9       (ar->shadow_reg_value->shadow_reg_value_9)
#define SHADOW_VALUE10      (ar->shadow_reg_value->shadow_reg_value_10)
#define SHADOW_VALUE11      (ar->shadow_reg_value->shadow_reg_value_11)
#define SHADOW_VALUE12      (ar->shadow_reg_value->shadow_reg_value_12)
#define SHADOW_VALUE13      (ar->shadow_reg_value->shadow_reg_value_13)
#define SHADOW_VALUE14      (ar->shadow_reg_value->shadow_reg_value_14)
#define SHADOW_VALUE15      (ar->shadow_reg_value->shadow_reg_value_15)
#define SHADOW_VALUE16      (ar->shadow_reg_value->shadow_reg_value_16)
#define SHADOW_VALUE17      (ar->shadow_reg_value->shadow_reg_value_17)
#define SHADOW_VALUE18      (ar->shadow_reg_value->shadow_reg_value_18)
#define SHADOW_VALUE19      (ar->shadow_reg_value->shadow_reg_value_19)
#define SHADOW_VALUE20      (ar->shadow_reg_value->shadow_reg_value_20)
#define SHADOW_VALUE21      (ar->shadow_reg_value->shadow_reg_value_21)
#define SHADOW_VALUE22      (ar->shadow_reg_value->shadow_reg_value_22)
#define SHADOW_VALUE23      (ar->shadow_reg_value->shadow_reg_value_23)
#define SHADOW_ADDRESS0     (ar->shadow_reg_address->shadow_reg_address_0)
#define SHADOW_ADDRESS1     (ar->shadow_reg_address->shadow_reg_address_1)
#define SHADOW_ADDRESS2     (ar->shadow_reg_address->shadow_reg_address_2)
#define SHADOW_ADDRESS3     (ar->shadow_reg_address->shadow_reg_address_3)
#define SHADOW_ADDRESS4     (ar->shadow_reg_address->shadow_reg_address_4)
#define SHADOW_ADDRESS5     (ar->shadow_reg_address->shadow_reg_address_5)
#define SHADOW_ADDRESS6     (ar->shadow_reg_address->shadow_reg_address_6)
#define SHADOW_ADDRESS7     (ar->shadow_reg_address->shadow_reg_address_7)
#define SHADOW_ADDRESS8     (ar->shadow_reg_address->shadow_reg_address_8)
#define SHADOW_ADDRESS9     (ar->shadow_reg_address->shadow_reg_address_9)
#define SHADOW_ADDRESS10    (ar->shadow_reg_address->shadow_reg_address_10)
#define SHADOW_ADDRESS11    (ar->shadow_reg_address->shadow_reg_address_11)
#define SHADOW_ADDRESS12    (ar->shadow_reg_address->shadow_reg_address_12)
#define SHADOW_ADDRESS13    (ar->shadow_reg_address->shadow_reg_address_13)
#define SHADOW_ADDRESS14    (ar->shadow_reg_address->shadow_reg_address_14)
#define SHADOW_ADDRESS15    (ar->shadow_reg_address->shadow_reg_address_15)
#define SHADOW_ADDRESS16    (ar->shadow_reg_address->shadow_reg_address_16)
#define SHADOW_ADDRESS17    (ar->shadow_reg_address->shadow_reg_address_17)
#define SHADOW_ADDRESS18    (ar->shadow_reg_address->shadow_reg_address_18)
#define SHADOW_ADDRESS19    (ar->shadow_reg_address->shadow_reg_address_19)
#define SHADOW_ADDRESS20    (ar->shadow_reg_address->shadow_reg_address_20)
#define SHADOW_ADDRESS21    (ar->shadow_reg_address->shadow_reg_address_21)
#define SHADOW_ADDRESS22    (ar->shadow_reg_address->shadow_reg_address_22)
#define SHADOW_ADDRESS23    (ar->shadow_reg_address->shadow_reg_address_23)

#define SHADOW_ADDRESS(i) (SHADOW_ADDRESS0 + \
			   i * (SHADOW_ADDRESS1 - SHADOW_ADDRESS0))

u32 shadow_sr_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr);
u32 shadow_dst_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr);

/*==================Send====================*/

/* ath10k_ce_send flags */
@@ -591,6 +649,9 @@ struct ce_attr {
				     & (uint64_t)(0xF00000000)) >> 32))
#endif

#define COPY_ENGINE_ID(COPY_ENGINE_BASE_ADDRESS) ((COPY_ENGINE_BASE_ADDRESS \
		- CE0_BASE_ADDRESS) / (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS))

static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
{
	return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id;
+2 −0
Original line number Diff line number Diff line
@@ -2350,6 +2350,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
		/* WCN3990 chip set is non bmi based */
		ar->is_bmi = false;
		ar->fw_flags = &wcn3990_fw_flags;
		ar->shadow_reg_value = &wcn3990_shadow_reg_value;
		ar->shadow_reg_address = &wcn3990_shadow_reg_address;
		break;
	default:
		ath10k_err(ar, "unsupported core hardware revision %d\n",
+2 −0
Original line number Diff line number Diff line
@@ -741,6 +741,8 @@ struct ath10k {

	const struct ath10k_hw_regs *regs;
	const struct ath10k_hw_values *hw_values;
	struct ath10k_shadow_reg_value *shadow_reg_value;
	struct ath10k_shadow_reg_address *shadow_reg_address;
	struct ath10k_bmi bmi;
	struct ath10k_wmi wmi;
	struct ath10k_htc htc;
+54 −0
Original line number Diff line number Diff line
@@ -220,6 +220,60 @@ struct fw_flag wcn3990_fw_flags = {
	.flags = 0x82E,
};

struct ath10k_shadow_reg_value wcn3990_shadow_reg_value = {
	.shadow_reg_value_0  = 0x00032000,
	.shadow_reg_value_1  = 0x00032004,
	.shadow_reg_value_2  = 0x00032008,
	.shadow_reg_value_3  = 0x0003200C,
	.shadow_reg_value_4  = 0x00032010,
	.shadow_reg_value_5  = 0x00032014,
	.shadow_reg_value_6  = 0x00032018,
	.shadow_reg_value_7  = 0x0003201C,
	.shadow_reg_value_8  = 0x00032020,
	.shadow_reg_value_9  = 0x00032024,
	.shadow_reg_value_10 = 0x00032028,
	.shadow_reg_value_11 = 0x0003202C,
	.shadow_reg_value_12 = 0x00032030,
	.shadow_reg_value_13 = 0x00032034,
	.shadow_reg_value_14 = 0x00032038,
	.shadow_reg_value_15 = 0x0003203C,
	.shadow_reg_value_16 = 0x00032040,
	.shadow_reg_value_17 = 0x00032044,
	.shadow_reg_value_18 = 0x00032048,
	.shadow_reg_value_19 = 0x0003204C,
	.shadow_reg_value_20 = 0x00032050,
	.shadow_reg_value_21 = 0x00032054,
	.shadow_reg_value_22 = 0x00032058,
	.shadow_reg_value_23 = 0x0003205C
};

struct ath10k_shadow_reg_address wcn3990_shadow_reg_address = {
	.shadow_reg_address_0  = 0x00030020,
	.shadow_reg_address_1  = 0x00030024,
	.shadow_reg_address_2  = 0x00030028,
	.shadow_reg_address_3  = 0x0003002C,
	.shadow_reg_address_4  = 0x00030030,
	.shadow_reg_address_5  = 0x00030034,
	.shadow_reg_address_6  = 0x00030038,
	.shadow_reg_address_7  = 0x0003003C,
	.shadow_reg_address_8  = 0x00030040,
	.shadow_reg_address_9  = 0x00030044,
	.shadow_reg_address_10 = 0x00030048,
	.shadow_reg_address_11 = 0x0003004C,
	.shadow_reg_address_12 = 0x00030050,
	.shadow_reg_address_13 = 0x00030054,
	.shadow_reg_address_14 = 0x00030058,
	.shadow_reg_address_15 = 0x0003005C,
	.shadow_reg_address_16 = 0x00030060,
	.shadow_reg_address_17 = 0x00030064,
	.shadow_reg_address_18 = 0x00030068,
	.shadow_reg_address_19 = 0x0003006C,
	.shadow_reg_address_20 = 0x00030070,
	.shadow_reg_address_21 = 0x00030074,
	.shadow_reg_address_22 = 0x00030078,
	.shadow_reg_address_23 = 0x0003007C
};

void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
				u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev)
{
Loading