mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	wl18xx: wlan_irq: support platform dependent interrupt types
* Interrupt request need to happen when the wilink chip is powered on and driving the wlan_irq line. This avoids spurious interrupt issues that are a result of different external pulls configuration on different platforms * Allow working with wl18xx level-low and falling edge irqs by configuring wl18xx to invert the device interrupt Signed-off-by: Eyal Reizer <eyalr@ti.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
		
							parent
							
								
									ad48013783
								
							
						
					
					
						commit
						bd763482c8
					
				
					 3 changed files with 40 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -24,6 +24,7 @@
 | 
			
		|||
#include <linux/ip.h>
 | 
			
		||||
#include <linux/firmware.h>
 | 
			
		||||
#include <linux/etherdevice.h>
 | 
			
		||||
#include <linux/irq.h>
 | 
			
		||||
 | 
			
		||||
#include "../wlcore/wlcore.h"
 | 
			
		||||
#include "../wlcore/debug.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -578,7 +579,7 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
 | 
			
		|||
 | 
			
		||||
static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = {
 | 
			
		||||
	[PART_TOP_PRCM_ELP_SOC] = {
 | 
			
		||||
		.mem  = { .start = 0x00A02000, .size  = 0x00010000 },
 | 
			
		||||
		.mem  = { .start = 0x00A00000, .size  = 0x00012000 },
 | 
			
		||||
		.reg  = { .start = 0x00807000, .size  = 0x00005000 },
 | 
			
		||||
		.mem2 = { .start = 0x00800000, .size  = 0x0000B000 },
 | 
			
		||||
		.mem3 = { .start = 0x00000000, .size  = 0x00000000 },
 | 
			
		||||
| 
						 | 
				
			
			@ -862,6 +863,7 @@ static int wl18xx_pre_upload(struct wl1271 *wl)
 | 
			
		|||
{
 | 
			
		||||
	u32 tmp;
 | 
			
		||||
	int ret;
 | 
			
		||||
	u16 irq_invert;
 | 
			
		||||
 | 
			
		||||
	BUILD_BUG_ON(sizeof(struct wl18xx_mac_and_phy_params) >
 | 
			
		||||
		WL18XX_PHY_INIT_MEM_SIZE);
 | 
			
		||||
| 
						 | 
				
			
			@ -911,6 +913,28 @@ static int wl18xx_pre_upload(struct wl1271 *wl)
 | 
			
		|||
	/* re-enable FDSP clock */
 | 
			
		||||
	ret = wlcore_write32(wl, WL18XX_PHY_FPGA_SPARE_1,
 | 
			
		||||
			     MEM_FDSP_CLK_120_ENABLE);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	ret = irq_get_trigger_type(wl->irq);
 | 
			
		||||
	if ((ret == IRQ_TYPE_LEVEL_LOW) || (ret == IRQ_TYPE_EDGE_FALLING)) {
 | 
			
		||||
		wl1271_info("using inverted interrupt logic: %d", ret);
 | 
			
		||||
		ret = wlcore_set_partition(wl,
 | 
			
		||||
					   &wl->ptable[PART_TOP_PRCM_ELP_SOC]);
 | 
			
		||||
		if (ret < 0)
 | 
			
		||||
			goto out;
 | 
			
		||||
 | 
			
		||||
		ret = wl18xx_top_reg_read(wl, TOP_FN0_CCCR_REG_32, &irq_invert);
 | 
			
		||||
		if (ret < 0)
 | 
			
		||||
			goto out;
 | 
			
		||||
 | 
			
		||||
		irq_invert |= BIT(1);
 | 
			
		||||
		ret = wl18xx_top_reg_write(wl, TOP_FN0_CCCR_REG_32, irq_invert);
 | 
			
		||||
		if (ret < 0)
 | 
			
		||||
			goto out;
 | 
			
		||||
 | 
			
		||||
		ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	return ret;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,6 +109,7 @@
 | 
			
		|||
 | 
			
		||||
#define WL18XX_WELP_ARM_COMMAND		(WL18XX_REGISTERS_BASE + 0x7100)
 | 
			
		||||
#define WL18XX_ENABLE			(WL18XX_REGISTERS_BASE + 0x01543C)
 | 
			
		||||
#define TOP_FN0_CCCR_REG_32		(WL18XX_TOP_OCP_BASE + 0x64)
 | 
			
		||||
 | 
			
		||||
/* PRCM registers */
 | 
			
		||||
#define PLATFORM_DETECTION		0xA0E3E0
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5966,10 +5966,6 @@ static int wl12xx_get_hw_info(struct wl1271 *wl)
 | 
			
		|||
{
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = wl12xx_set_power_on(wl);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &wl->chip.id);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		goto out;
 | 
			
		||||
| 
						 | 
				
			
			@ -5985,7 +5981,6 @@ static int wl12xx_get_hw_info(struct wl1271 *wl)
 | 
			
		|||
		ret = wl->ops->get_mac(wl);
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
	wl1271_power_off(wl);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6432,10 +6427,22 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
 | 
			
		|||
	else
 | 
			
		||||
		wl->irq_flags |= IRQF_ONESHOT;
 | 
			
		||||
 | 
			
		||||
	ret = wl12xx_set_power_on(wl);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		goto out_free_nvs;
 | 
			
		||||
 | 
			
		||||
	ret = wl12xx_get_hw_info(wl);
 | 
			
		||||
	if (ret < 0) {
 | 
			
		||||
		wl1271_error("couldn't get hw info");
 | 
			
		||||
		wl1271_power_off(wl);
 | 
			
		||||
		goto out_free_nvs;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = request_threaded_irq(wl->irq, hardirq_fn, wlcore_irq,
 | 
			
		||||
				   wl->irq_flags, pdev->name, wl);
 | 
			
		||||
	if (ret < 0) {
 | 
			
		||||
		wl1271_error("request_irq() failed: %d", ret);
 | 
			
		||||
		wl1271_error("interrupt configuration failed");
 | 
			
		||||
		wl1271_power_off(wl);
 | 
			
		||||
		goto out_free_nvs;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6449,12 +6456,7 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context)
 | 
			
		|||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	disable_irq(wl->irq);
 | 
			
		||||
 | 
			
		||||
	ret = wl12xx_get_hw_info(wl);
 | 
			
		||||
	if (ret < 0) {
 | 
			
		||||
		wl1271_error("couldn't get hw info");
 | 
			
		||||
		goto out_irq;
 | 
			
		||||
	}
 | 
			
		||||
	wl1271_power_off(wl);
 | 
			
		||||
 | 
			
		||||
	ret = wl->ops->identify_chip(wl);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue