Enable buttons GPIO passthrough

Wang, Kuiying kuiying.wang at intel.com
Tue Jan 22 21:39:21 AEDT 2019


Hi Linus,
Let me attach a draft patch, it will be easy to understand.

if someone wanna enable passthrough just need to override like " gpio->chip.direction_passthrough = aspeed_gpio_dir_passthrough;"
else passthrough is disabled.

In app level, just need to echo "passthrough" to enable passthrough like "echo passthrough > /sys/class/gpio/gpio35/direction"

diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index 2342e154029b..1091ceded76a 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -482,6 +482,33 @@ static int aspeed_gpio_dir_out(struct gpio_chip *gc,
 	return 0;
 }
 
+static int aspeed_gpio_dir_passthrough(struct gpio_chip *gc,
+			       unsigned int offset)
+{
+	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
+	const struct aspeed_gpio_bank *bank = to_bank(offset);
+	void __iomem *addr = bank_reg(gpio, bank, reg_dir);
+	unsigned long flags;
+	bool copro;
+	u32 reg;
+	printk("kwin::aspeed_gpio_dir_passthrough");
+	//TODO enable_passthrouhg();
+	spin_lock_irqsave(&gpio->lock, flags);
+
+	reg = ioread32(addr);
+	reg |= GPIO_BIT(offset);
+
+	copro = aspeed_gpio_copro_request(gpio, offset);
+	//__aspeed_gpio_set(gc, offset, val);
+	iowrite32(reg, addr);
+
+	if (copro)
+		aspeed_gpio_copro_release(gpio, offset);
+	spin_unlock_irqrestore(&gpio->lock, flags);
+
+	return 0;
+}
+
 static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
 {
 	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
@@ -1188,6 +1215,7 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
 	gpio->chip.parent = &pdev->dev;
 	gpio->chip.direction_input = aspeed_gpio_dir_in;
 	gpio->chip.direction_output = aspeed_gpio_dir_out;
+	gpio->chip.direction_passthrough = aspeed_gpio_dir_passthrough;
 	gpio->chip.get_direction = aspeed_gpio_get_direction;
 	gpio->chip.request = aspeed_gpio_request;
 	gpio->chip.free = aspeed_gpio_free;
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c
index 3dbaf489a8a5..5c78067ad250 100644
--- a/drivers/gpio/gpiolib-sysfs.c
+++ b/drivers/gpio/gpiolib-sysfs.c
@@ -89,6 +89,8 @@ static ssize_t direction_store(struct device *dev,
 		status = gpiod_direction_output_raw(desc, 0);
 	else if (sysfs_streq(buf, "in"))
 		status = gpiod_direction_input(desc);
+	else if (sysfs_streq(buf, "passthrough"))
+		status = gpiod_direction_passthrough(desc);
 	else
 		status = -EINVAL;
 
@@ -300,6 +302,8 @@ static ssize_t edge_store(struct device *dev,
 }
 static DEVICE_ATTR_RW(edge);
 
+
+
 /* Caller holds gpiod-data mutex. */
 static int gpio_sysfs_set_active_low(struct device *dev, int value)
 {
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index a8e01d99919c..530573bd8711 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2536,6 +2536,33 @@ int gpiod_direction_input(struct gpio_desc *desc)
 }
 EXPORT_SYMBOL_GPL(gpiod_direction_input);
 
+
+int gpiod_direction_passthrough(struct gpio_desc *desc)
+{
+	struct gpio_chip	*chip;
+	int			status = -EINVAL;
+
+	VALIDATE_DESC(desc);
+	chip = desc->gdev->chip;
+
+	if (!chip->direction_passthrough) {
+		gpiod_warn(desc,
+			"%s: missing direction_passthrough() operations\n",
+			__func__);
+		return -EIO;
+	}
+
+	status = chip->direction_passthrough(chip, gpio_chip_hwgpio(desc));
+	if (status == 0)
+		clear_bit(FLAG_IS_OUT, &desc->flags);
+
+	trace_gpio_direction(desc_to_gpio(desc), 1, status);
+
+	return status;
+}
+EXPORT_SYMBOL_GPL(gpiod_direction_passthrough);
+
+
 static int gpio_set_drive_single_ended(struct gpio_chip *gc, unsigned offset,
 				       enum pin_config_param mode)
 {
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index a4d5eb37744a..07e30f9e3bce 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -245,6 +245,8 @@ struct gpio_chip {
 						unsigned offset);
 	int			(*direction_output)(struct gpio_chip *chip,
 						unsigned offset, int value);
+	int			(*direction_passthrough)(struct gpio_chip *chip,
+						unsigned offset);
 	int			(*get)(struct gpio_chip *chip,
 						unsigned offset);
 	int			(*get_multiple)(struct gpio_chip *chip,


Thanks,
Kwin.


-----Original Message-----
From: Linus Walleij [mailto:linus.walleij at linaro.org] 
Sent: Monday, January 21, 2019 9:10 PM
To: Wang, Kuiying <kuiying.wang at intel.com>
Cc: Joel Stanley <joel at jms.id.au>; Andrew Jeffery <andrew at aj.id.au>; Thomas Petazzoni <thomas.petazzoni at bootlin.com>; open list:GPIO SUBSYSTEM <linux-gpio at vger.kernel.org>; Andrew Geissler <geissonator at gmail.com>; OpenBMC Maillist <openbmc at lists.ozlabs.org>; Mauery, Vernon <vernon.mauery at intel.com>; Feist, James <james.feist at intel.com>; Yoo, Jae Hyun <jae.hyun.yoo at intel.com>; Nguyen, Hai V <hai.v.nguyen at intel.com>; Khetan, Sharad <sharad.khetan at intel.com>
Subject: Re: Enable buttons GPIO passthrough

Hi Kwin,

On Wed, Jan 16, 2019 at 3:30 PM Wang, Kuiying <kuiying.wang at intel.com> wrote:

> Hi Joel,
> Do agree to use proposal #1? (extend "passthrough" to the "direction" 
> property of gpio, use  "value" to control it be disabled/enabled.)
>
> All,
> Any other comments?

I think you maybe misunderstood my previous mail, or I misunderstood yours :)

Make sure that passthrough mode is set up in the .set_config() callback, nothing else.

Do not change the signatures of the direction functions or set_value() functions in gpiolib.

But maybe you are talking about implementation details in the specific GPIO driver for Aspeed? Then I just missed that part, sorry.

Yours,
Linus Walleij


More information about the openbmc mailing list