Commit f00dc1d7 authored by Jérôme Pouiller's avatar Jérôme Pouiller Committed by Greg Kroah-Hartman
Browse files

staging: wfx: poll IRQ during init



When the chip starts in SDIO mode, the external IRQ (aka Out-Of-Band
IRQ) cannot be used before to configure it. Therefore, the first
exchanges with the chip have to be done without the OOB IRQ.

This patch allow to poll the data until the OOB IRQ is correctly setup.
In order to keep the code simpler, this patch also poll data even if OOB
IRQ is not used.

Signed-off-by: default avatarJérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20200505123757.39506-9-Jerome.Pouiller@silabs.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 57aa557f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -320,6 +320,7 @@ void wfx_bh_poll_irq(struct wfx_dev *wdev)
	ktime_t now, start;
	u32 reg;

	WARN(!wdev->poll_irq, "unexpected IRQ polling can mask IRQ");
	start = ktime_get();
	for (;;) {
		control_reg_read(wdev, &reg);
+2 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ struct hwbus_ops {
			    void *dst, size_t count);
	int (*copy_to_io)(void *bus_priv, unsigned int addr,
			  const void *src, size_t count);
	int (*irq_subscribe)(void *bus_priv);
	int (*irq_unsubscribe)(void *bus_priv);
	void (*lock)(void *bus_priv);
	void (*unlock)(void *bus_priv);
	size_t (*align_size)(void *bus_priv, size_t size);
+7 −10
Original line number Diff line number Diff line
@@ -106,8 +106,9 @@ static irqreturn_t wfx_sdio_irq_handler_ext(int irq, void *priv)
	return IRQ_HANDLED;
}

static int wfx_sdio_irq_subscribe(struct wfx_sdio_priv *bus)
static int wfx_sdio_irq_subscribe(void *priv)
{
	struct wfx_sdio_priv *bus = priv;
	u32 flags;
	int ret;
	u8 cccr;
@@ -134,8 +135,9 @@ static int wfx_sdio_irq_subscribe(struct wfx_sdio_priv *bus)
					 "wfx", bus);
}

static int wfx_sdio_irq_unsubscribe(struct wfx_sdio_priv *bus)
static int wfx_sdio_irq_unsubscribe(void *priv)
{
	struct wfx_sdio_priv *bus = priv;
	int ret;

	if (bus->of_irq)
@@ -156,6 +158,8 @@ static size_t wfx_sdio_align_size(void *priv, size_t size)
static const struct hwbus_ops wfx_sdio_hwbus_ops = {
	.copy_from_io = wfx_sdio_copy_from_io,
	.copy_to_io = wfx_sdio_copy_to_io,
	.irq_subscribe = wfx_sdio_irq_subscribe,
	.irq_unsubscribe = wfx_sdio_irq_unsubscribe,
	.lock			= wfx_sdio_lock,
	.unlock			= wfx_sdio_unlock,
	.align_size		= wfx_sdio_align_size,
@@ -218,18 +222,12 @@ static int wfx_sdio_probe(struct sdio_func *func,
		goto err1;
	}

	ret = wfx_sdio_irq_subscribe(bus);
	if (ret)
		goto err1;

	ret = wfx_probe(bus->core);
	if (ret)
		goto err2;
		goto err1;

	return 0;

err2:
	wfx_sdio_irq_unsubscribe(bus);
err1:
	sdio_claim_host(func);
	sdio_disable_func(func);
@@ -243,7 +241,6 @@ static void wfx_sdio_remove(struct sdio_func *func)
	struct wfx_sdio_priv *bus = sdio_get_drvdata(func);

	wfx_release(bus->core);
	wfx_sdio_irq_unsubscribe(bus);
	sdio_claim_host(func);
	sdio_disable_func(func);
	sdio_release_host(func);
+13 −3
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/gpio/consumer.h>
#include <linux/spi/spi.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/of.h>

#include "bus.h"
@@ -143,8 +144,9 @@ static irqreturn_t wfx_spi_irq_handler(int irq, void *priv)
	return IRQ_HANDLED;
}

static int wfx_spi_irq_subscribe(struct wfx_spi_priv *bus)
static int wfx_spi_irq_subscribe(void *priv)
{
	struct wfx_spi_priv *bus = priv;
	u32 flags;

	flags = irq_get_trigger_type(bus->func->irq);
@@ -156,6 +158,14 @@ static int wfx_spi_irq_subscribe(struct wfx_spi_priv *bus)
					 "wfx", bus);
}

static int wfx_spi_irq_unsubscribe(void *priv)
{
	struct wfx_spi_priv *bus = priv;

	devm_free_irq(&bus->func->dev, bus->func->irq, bus);
	return 0;
}

static size_t wfx_spi_align_size(void *priv, size_t size)
{
	// Most of SPI controllers avoid DMA if buffer size is not 32bit aligned
@@ -165,6 +175,8 @@ static size_t wfx_spi_align_size(void *priv, size_t size)
static const struct hwbus_ops wfx_spi_hwbus_ops = {
	.copy_from_io = wfx_spi_copy_from_io,
	.copy_to_io = wfx_spi_copy_to_io,
	.irq_subscribe = wfx_spi_irq_subscribe,
	.irq_unsubscribe = wfx_spi_irq_unsubscribe,
	.lock			= wfx_spi_lock,
	.unlock			= wfx_spi_unlock,
	.align_size		= wfx_spi_align_size,
@@ -216,8 +228,6 @@ static int wfx_spi_probe(struct spi_device *func)
	if (!bus->core)
		return -EIO;

	wfx_spi_irq_subscribe(bus);

	return wfx_probe(bus->core);
}

+3 −0
Original line number Diff line number Diff line
@@ -82,6 +82,9 @@ int wfx_cmd_send(struct wfx_dev *wdev, struct hif_msg *request, void *reply,
	if (async)
		return 0;

	if (wdev->poll_irq)
		wfx_bh_poll_irq(wdev);

	ret = wait_for_completion_timeout(&wdev->hif_cmd.done, 1 * HZ);
	if (!ret) {
		dev_err(wdev->dev, "chip is abnormally long to answer\n");
Loading