Commit 59c32468 authored by Srinivas Kandagatla's avatar Srinivas Kandagatla Committed by Linus Walleij

gpio: wcd934x: Add support to wcd934x gpio controller

This patch adds support to wcd934x gpio block found in
WCD9340/WC9341 Audio codecs.
Signed-off-by: default avatarSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20200107130844.20763-3-srinivas.kandagatla@linaro.orgSigned-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent e5e42ad2
...@@ -619,6 +619,13 @@ config GPIO_VX855 ...@@ -619,6 +619,13 @@ config GPIO_VX855
additional drivers must be enabled in order to use the additional drivers must be enabled in order to use the
functionality of the device. functionality of the device.
config GPIO_WCD934X
tristate "Qualcomm Technologies Inc WCD9340/WCD9341 gpio controller driver"
depends on MFD_WCD934X && OF_GPIO
help
This driver is to supprot GPIO block found on the Qualcomm Technologies
Inc WCD9340/WCD9341 Audio Codec.
config GPIO_XGENE config GPIO_XGENE
bool "APM X-Gene GPIO controller support" bool "APM X-Gene GPIO controller support"
depends on ARM64 && OF_GPIO depends on ARM64 && OF_GPIO
......
...@@ -158,6 +158,7 @@ obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o ...@@ -158,6 +158,7 @@ obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o
obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o
obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
obj-$(CONFIG_GPIO_WCD934X) += gpio-wcd934x.o
obj-$(CONFIG_GPIO_WHISKEY_COVE) += gpio-wcove.o obj-$(CONFIG_GPIO_WHISKEY_COVE) += gpio-wcove.o
obj-$(CONFIG_GPIO_WINBOND) += gpio-winbond.o obj-$(CONFIG_GPIO_WINBOND) += gpio-winbond.o
obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
......
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019, Linaro Limited
#include <linux/module.h>
#include <linux/gpio/driver.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/of_device.h>
#define WCD_PIN_MASK(p) BIT(p - 1)
#define WCD_REG_DIR_CTL_OFFSET 0x42
#define WCD_REG_VAL_CTL_OFFSET 0x43
#define WCD934X_NPINS 5
struct wcd_gpio_data {
struct regmap *map;
struct gpio_chip chip;
};
static int wcd_gpio_get_direction(struct gpio_chip *chip, unsigned int pin)
{
struct wcd_gpio_data *data = gpiochip_get_data(chip);
unsigned int value;
int ret;
ret = regmap_read(data->map, WCD_REG_DIR_CTL_OFFSET, &value);
if (ret < 0)
return ret;
if (value & WCD_PIN_MASK(pin))
return GPIO_LINE_DIRECTION_OUT;
return GPIO_LINE_DIRECTION_IN;
}
static int wcd_gpio_direction_input(struct gpio_chip *chip, unsigned int pin)
{
struct wcd_gpio_data *data = gpiochip_get_data(chip);
return regmap_update_bits(data->map, WCD_REG_DIR_CTL_OFFSET,
WCD_PIN_MASK(pin), 0);
}
static int wcd_gpio_direction_output(struct gpio_chip *chip, unsigned int pin,
int val)
{
struct wcd_gpio_data *data = gpiochip_get_data(chip);
regmap_update_bits(data->map, WCD_REG_DIR_CTL_OFFSET,
WCD_PIN_MASK(pin), WCD_PIN_MASK(pin));
return regmap_update_bits(data->map, WCD_REG_VAL_CTL_OFFSET,
WCD_PIN_MASK(pin),
val ? WCD_PIN_MASK(pin) : 0);
}
static int wcd_gpio_get(struct gpio_chip *chip, unsigned int pin)
{
struct wcd_gpio_data *data = gpiochip_get_data(chip);
int value;
regmap_read(data->map, WCD_REG_VAL_CTL_OFFSET, &value);
return !!(value && WCD_PIN_MASK(pin));
}
static void wcd_gpio_set(struct gpio_chip *chip, unsigned int pin, int val)
{
wcd_gpio_direction_output(chip, pin, val);
}
static int wcd_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct wcd_gpio_data *data;
struct gpio_chip *chip;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->map = dev_get_regmap(dev->parent, NULL);
if (!data->map) {
dev_err(dev, "%s: failed to get regmap\n", __func__);
return -EINVAL;
}
chip = &data->chip;
chip->direction_input = wcd_gpio_direction_input;
chip->direction_output = wcd_gpio_direction_output;
chip->get_direction = wcd_gpio_get_direction;
chip->get = wcd_gpio_get;
chip->set = wcd_gpio_set;
chip->parent = dev;
chip->base = -1;
chip->ngpio = WCD934X_NPINS;
chip->label = dev_name(dev);
chip->of_gpio_n_cells = 2;
chip->can_sleep = false;
return devm_gpiochip_add_data(dev, chip, data);
}
static const struct of_device_id wcd_gpio_of_match[] = {
{ .compatible = "qcom,wcd9340-gpio" },
{ .compatible = "qcom,wcd9341-gpio" },
{ }
};
MODULE_DEVICE_TABLE(of, wcd_gpio_of_match);
static struct platform_driver wcd_gpio_driver = {
.driver = {
.name = "wcd934x-gpio",
.of_match_table = wcd_gpio_of_match,
},
.probe = wcd_gpio_probe,
};
module_platform_driver(wcd_gpio_driver);
MODULE_DESCRIPTION("Qualcomm Technologies, Inc WCD GPIO control driver");
MODULE_LICENSE("GPL v2");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment