#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
+#include <linux/delay.h>
struct rfkill_gpio_data {
const char *name;
struct clk *clk;
bool clk_enabled;
+ bool blocked;
+ bool edge_triggered;
};
+static void rfkill_gpiod_toggle(struct gpio_desc *desc, bool blocked)
+{
+ gpiod_set_value_cansleep(desc, blocked);
+ msleep(10);
+ gpiod_set_value_cansleep(desc, !blocked);
+}
+
static int rfkill_gpio_set_power(void *data, bool blocked)
{
struct rfkill_gpio_data *rfkill = data;
if (!blocked && !IS_ERR(rfkill->clk) && !rfkill->clk_enabled)
clk_enable(rfkill->clk);
- gpiod_set_value_cansleep(rfkill->shutdown_gpio, !blocked);
- gpiod_set_value_cansleep(rfkill->reset_gpio, !blocked);
+ if (rfkill->edge_triggered &&
+ rfkill->blocked != blocked) {
+ rfkill_gpiod_toggle(rfkill->shutdown_gpio, blocked);
+ rfkill_gpiod_toggle(rfkill->reset_gpio, blocked);
+
+ rfkill->blocked = blocked;
+ } else {
+ gpiod_set_value_cansleep(rfkill->shutdown_gpio, !blocked);
+ gpiod_set_value_cansleep(rfkill->reset_gpio, !blocked);
+ }
+
if (blocked && !IS_ERR(rfkill->clk) && rfkill->clk_enabled)
clk_disable(rfkill->clk);
return ret;
}
+ rfkill->edge_triggered =
+ device_property_read_bool(&pdev->dev, "edge-triggered");
+
rfkill->clk = devm_clk_get(&pdev->dev, NULL);
gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_ASIS);
if (!rfkill->rfkill_dev)
return -ENOMEM;
+ rfkill->blocked = true;
+
ret = rfkill_register(rfkill->rfkill_dev);
if (ret < 0)
goto err_destroy;