From: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
To: matti.vaittinen@fi.rohmeurope.com, mazziesaccount@gmail.com
Cc: Lee Jones <lee.jones@linaro.org>,
Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Michael Turquette <mturquette@baylibre.com>,
Stephen Boyd <sboyd@kernel.org>,
Linus Walleij <linus.walleij@linaro.org>,
Bartosz Golaszewski <bgolaszewski@baylibre.com>,
Sebastian Reichel <sre@kernel.org>,
Liam Girdwood <lgirdwood@gmail.com>,
Mark Brown <broonie@kernel.org>,
Alessandro Zummo <a.zummo@towertech.it>,
Alexandre Belloni <alexandre.belloni@bootlin.com>,
Wim Van Sebroeck <wim@linux-watchdog.org>,
Guenter Roeck <linux@roeck-us.net>,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org,
linux-pm@vger.kernel.org, linux-rtc@vger.kernel.org,
linux-watchdog@vger.kernel.org, heikki.haikola@fi.rohmeurope.com,
mikko.mutanen@fi.rohmeurope.com
Subject: [PATCH v11 5/8] gpio: Initial support for ROHM bd70528 GPIO block
Date: Mon, 25 Mar 2019 14:06:19 +0200 [thread overview]
Message-ID: <afe53bac6463d6047ebce8677f0c8d77a7fb7eb1.1553515333.git.matti.vaittinen@fi.rohmeurope.com> (raw)
In-Reply-To: <cover.1553515333.git.matti.vaittinen@fi.rohmeurope.com>
ROHM BD70528 PMIC has 4 GPIO pins. Allow them to be
controlled by GPIO framework.
IRQs are handled by regmap-irq and GPIO driver is not
aware of the irq usage.
Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
---
drivers/gpio/Kconfig | 11 ++
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-bd70528.c | 231 ++++++++++++++++++++++++++++++++++++
3 files changed, 243 insertions(+)
create mode 100644 drivers/gpio/gpio-bd70528.c
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 3f50526a771f..2789530a93ae 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -979,6 +979,17 @@ config GPIO_ARIZONA
help
Support for GPIOs on Wolfson Arizona class devices.
+config GPIO_BD70528
+ tristate "ROHM BD70528 GPIO support"
+ depends on MFD_ROHM_BD70528
+ help
+ Support for GPIOs on ROHM BD70528 PMIC. There are four GPIOs
+ available on the ROHM PMIC in total. The GPIOs can also
+ generate interrupts.
+
+ This driver can also be built as a module. If so, the module
+ will be called gpio-bd70528.
+
config GPIO_BD9571MWV
tristate "ROHM BD9571 GPIO support"
depends on MFD_BD9571MWV
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 54d55274b93a..e93e376bae0b 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_GPIO_ATH79) += gpio-ath79.o
obj-$(CONFIG_GPIO_ASPEED) += gpio-aspeed.o
obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o
obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o
+obj-$(CONFIG_GPIO_BD70528) += gpio-bd70528.o
obj-$(CONFIG_GPIO_BD9571MWV) += gpio-bd9571mwv.o
obj-$(CONFIG_GPIO_BRCMSTB) += gpio-brcmstb.o
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
diff --git a/drivers/gpio/gpio-bd70528.c b/drivers/gpio/gpio-bd70528.c
new file mode 100644
index 000000000000..507703474909
--- /dev/null
+++ b/drivers/gpio/gpio-bd70528.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 ROHM Semiconductors
+// gpio-bd70528.c ROHM BD70528MWV gpio driver
+
+#include <linux/gpio/driver.h>
+#include <linux/mfd/rohm-bd70528.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define GPIO_IN_REG(offset) (BD70528_REG_GPIO1_IN + offset*2)
+#define GPIO_OUT_REG(offset) (BD70528_REG_GPIO1_OUT + offset*2)
+
+struct bd70528_gpio {
+ struct rohm_regmap_dev chip;
+ struct gpio_chip gpio;
+};
+
+static int bd70528_set_debounce(struct bd70528_gpio *bdgpio,
+ unsigned int offset, unsigned int debounce)
+{
+ u8 val;
+
+ switch (debounce) {
+ case 0:
+ val = BD70528_DEBOUNCE_DISABLE;
+ break;
+ case 1 ... 15:
+ val = BD70528_DEBOUNCE_15MS;
+ break;
+ case 16 ... 30:
+ val = BD70528_DEBOUNCE_30MS;
+ break;
+ case 31 ... 50:
+ val = BD70528_DEBOUNCE_50MS;
+ break;
+ default:
+ dev_err(bdgpio->chip.dev,
+ "Invalid debouce value %u\n", debounce);
+ return -EINVAL;
+ }
+ return regmap_update_bits(bdgpio->chip.regmap, GPIO_IN_REG(offset),
+ BD70528_DEBOUNCE_MASK, val);
+}
+
+static int bd70528_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
+ int val, ret;
+
+ /* Do we need to do something to IRQs here? */
+ ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), &val);
+ if (ret) {
+ dev_err(bdgpio->chip.dev, "Could not read gpio direction\n");
+ return ret;
+ }
+
+ return !(val & BD70528_GPIO_OUT_EN_MASK);
+}
+
+static int bd70528_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+ unsigned long config)
+{
+ struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
+
+ switch (pinconf_to_config_param(config)) {
+ case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+ return regmap_update_bits(bdgpio->chip.regmap,
+ GPIO_OUT_REG(offset),
+ BD70528_GPIO_DRIVE_MASK,
+ BD70528_GPIO_OPEN_DRAIN);
+ break;
+ case PIN_CONFIG_DRIVE_PUSH_PULL:
+ return regmap_update_bits(bdgpio->chip.regmap,
+ GPIO_OUT_REG(offset),
+ BD70528_GPIO_DRIVE_MASK,
+ BD70528_GPIO_PUSH_PULL);
+ break;
+ case PIN_CONFIG_INPUT_DEBOUNCE:
+ return bd70528_set_debounce(bdgpio, offset,
+ pinconf_to_config_argument(config));
+ break;
+ default:
+ break;
+ }
+ return -ENOTSUPP;
+}
+
+static int bd70528_direction_input(struct gpio_chip *chip, unsigned int offset)
+{
+ struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
+
+ /* Do we need to do something to IRQs here? */
+ return regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
+ BD70528_GPIO_OUT_EN_MASK,
+ BD70528_GPIO_OUT_DISABLE);
+}
+static void bd70528_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ int ret;
+ struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
+ u8 val = (value) ? BD70528_GPIO_OUT_HI : BD70528_GPIO_OUT_LO;
+
+ ret = regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
+ BD70528_GPIO_OUT_MASK, val);
+ if (ret)
+ dev_err(bdgpio->chip.dev, "Could not set gpio to %d\n", value);
+}
+
+static int bd70528_direction_output(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
+
+ bd70528_gpio_set(chip, offset, value);
+ return regmap_update_bits(bdgpio->chip.regmap, GPIO_OUT_REG(offset),
+ BD70528_GPIO_OUT_EN_MASK,
+ BD70528_GPIO_OUT_ENABLE);
+}
+
+#define GPIO_IN_STATE_MASK(offset) (BD70528_GPIO_IN_STATE_BASE << offset)
+
+static int bd70528_gpio_get_o(struct bd70528_gpio *bdgpio, unsigned int offset)
+{
+ int ret;
+ unsigned int val;
+
+ ret = regmap_read(bdgpio->chip.regmap, GPIO_OUT_REG(offset), &val);
+ if (!ret)
+ ret = !!(val & BD70528_GPIO_OUT_MASK);
+ else
+ dev_err(bdgpio->chip.dev, "GPIO (out) state read failed\n");
+
+ return ret;
+}
+
+static int bd70528_gpio_get_i(struct bd70528_gpio *bdgpio, unsigned int offset)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(bdgpio->chip.regmap, BD70528_REG_GPIO_STATE, &val);
+
+ if (!ret)
+ ret = !(val & GPIO_IN_STATE_MASK(offset));
+ else
+ dev_err(bdgpio->chip.dev, "GPIO (in) state read failed\n");
+
+ return ret;
+}
+
+static int bd70528_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ int ret = -EINVAL;
+ struct bd70528_gpio *bdgpio = gpiochip_get_data(chip);
+
+ /*
+ * There is a race condition where someone might be changing the
+ * GPIO direction after we get it but before we read the value. But
+ * application design where GPIO direction may be changed just when
+ * we read GPIO value would be pointless as reader could not know
+ * whether the returned high/low state is caused by input or output.
+ * Or then there must be other ways to mitigate the issue. Thus
+ * locking would make no sense.
+ */
+ ret = bd70528_get_direction(chip, offset);
+ if (ret == 0)
+ ret = bd70528_gpio_get_o(bdgpio, offset);
+ else if (ret == 1)
+ ret = bd70528_gpio_get_i(bdgpio, offset);
+ else
+ dev_err(bdgpio->chip.dev, "failed to read GPIO direction\n");
+
+ return ret;
+}
+
+static int bd70528_probe(struct platform_device *pdev)
+{
+ struct bd70528_gpio *bdgpio;
+ struct rohm_regmap_dev *bd70528;
+ int ret;
+
+ bd70528 = dev_get_drvdata(pdev->dev.parent);
+ if (!bd70528) {
+ dev_err(&pdev->dev, "No MFD driver data\n");
+ return -EINVAL;
+ }
+
+ bdgpio = devm_kzalloc(&pdev->dev, sizeof(*bdgpio),
+ GFP_KERNEL);
+ if (!bdgpio)
+ return -ENOMEM;
+ bdgpio->chip.dev = &pdev->dev;
+ bdgpio->gpio.parent = pdev->dev.parent;
+ bdgpio->gpio.label = "bd70528-gpio";
+ bdgpio->gpio.owner = THIS_MODULE;
+ bdgpio->gpio.get_direction = bd70528_get_direction;
+ bdgpio->gpio.direction_input = bd70528_direction_input;
+ bdgpio->gpio.direction_output = bd70528_direction_output;
+ bdgpio->gpio.set_config = bd70528_gpio_set_config;
+ bdgpio->gpio.can_sleep = true;
+ bdgpio->gpio.get = bd70528_gpio_get;
+ bdgpio->gpio.set = bd70528_gpio_set;
+ bdgpio->gpio.ngpio = 4;
+ bdgpio->gpio.base = -1;
+#ifdef CONFIG_OF_GPIO
+ bdgpio->gpio.of_node = pdev->dev.parent->of_node;
+#endif
+ bdgpio->chip.regmap = bd70528->regmap;
+
+ ret = devm_gpiochip_add_data(&pdev->dev, &bdgpio->gpio,
+ bdgpio);
+ if (ret)
+ dev_err(&pdev->dev, "gpio_init: Failed to add bd70528-gpio\n");
+
+ return ret;
+}
+
+static struct platform_driver bd70528_gpio = {
+ .driver = {
+ .name = "bd70528-gpio"
+ },
+ .probe = bd70528_probe,
+};
+
+module_platform_driver(bd70528_gpio);
+
+MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
+MODULE_DESCRIPTION("BD70528 voltage regulator driver");
+MODULE_LICENSE("GPL");
--
2.17.2
--
Matti Vaittinen, Linux device drivers
ROHM Semiconductors, Finland SWDC
Kiviharjunlenkki 1E
90220 OULU
FINLAND
~~~ "I don't think so," said Rene Descartes. Just then he vanished ~~~
next prev parent reply other threads:[~2019-03-25 12:06 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-03-25 12:04 [PATCH v11 0/8] support ROHM BD70528 PMIC Matti Vaittinen
2019-03-25 12:04 ` [PATCH v11 1/8] mfd: regulator: clk: split rohm-bd718x7.h Matti Vaittinen
2019-04-03 6:19 ` Lee Jones
2019-03-25 12:05 ` [PATCH v11 2/8] mfd: bd70528: Support ROHM bd70528 PMIC - core Matti Vaittinen
2019-04-03 7:31 ` Lee Jones
2019-04-03 8:47 ` Matti Vaittinen
2019-04-03 9:30 ` Lee Jones
2019-04-03 10:10 ` Matti Vaittinen
2019-04-03 11:25 ` Lee Jones
2019-04-03 11:45 ` Vaittinen, Matti
2019-04-04 2:52 ` Lee Jones
2019-04-04 5:57 ` Vaittinen, Matti
2019-04-04 6:54 ` Lee Jones
2019-04-04 7:24 ` Matti Vaittinen
2019-04-04 7:56 ` Alexandre Belloni
2019-04-04 8:10 ` Vaittinen, Matti
2019-04-04 8:21 ` Lee Jones
2019-04-04 8:06 ` Lee Jones
2019-03-25 12:05 ` [PATCH v11 3/8] clk: bd718x7: Support ROHM BD70528 clk block Matti Vaittinen
2019-03-25 12:05 ` [PATCH v11 4/8] dt-bindings: mfd: Document first ROHM BD70528 bindings Matti Vaittinen
2019-04-03 7:34 ` Lee Jones
2019-04-03 9:04 ` Matti Vaittinen
2019-03-25 12:06 ` Matti Vaittinen [this message]
2019-03-25 12:06 ` [PATCH v11 6/8] rtc: bd70528: Initial support for ROHM bd70528 RTC Matti Vaittinen
2019-03-25 17:04 ` Alexandre Belloni
2019-03-26 13:51 ` Vaittinen, Matti
2019-03-26 14:05 ` Alexandre Belloni
2019-03-25 12:06 ` [PATCH v11 7/8] power: supply: Initial support for ROHM BD70528 PMIC charger block Matti Vaittinen
2019-03-25 12:07 ` [PATCH v11 8/8] watchdog: bd70528: Initial support for ROHM BD70528 watchdog block Matti Vaittinen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=afe53bac6463d6047ebce8677f0c8d77a7fb7eb1.1553515333.git.matti.vaittinen@fi.rohmeurope.com \
--to=matti.vaittinen@fi.rohmeurope.com \
--cc=a.zummo@towertech.it \
--cc=alexandre.belloni@bootlin.com \
--cc=bgolaszewski@baylibre.com \
--cc=broonie@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=heikki.haikola@fi.rohmeurope.com \
--cc=lee.jones@linaro.org \
--cc=lgirdwood@gmail.com \
--cc=linus.walleij@linaro.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=linux-rtc@vger.kernel.org \
--cc=linux-watchdog@vger.kernel.org \
--cc=linux@roeck-us.net \
--cc=mark.rutland@arm.com \
--cc=mazziesaccount@gmail.com \
--cc=mikko.mutanen@fi.rohmeurope.com \
--cc=mturquette@baylibre.com \
--cc=robh+dt@kernel.org \
--cc=sboyd@kernel.org \
--cc=sre@kernel.org \
--cc=wim@linux-watchdog.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).