^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright (c) 2019, Linaro Limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/gpio/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define WCD_PIN_MASK(p) BIT(p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define WCD_REG_DIR_CTL_OFFSET 0x42
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define WCD_REG_VAL_CTL_OFFSET 0x43
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define WCD934X_NPINS 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) struct wcd_gpio_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) struct regmap *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct gpio_chip chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static int wcd_gpio_get_direction(struct gpio_chip *chip, unsigned int pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct wcd_gpio_data *data = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) unsigned int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) ret = regmap_read(data->map, WCD_REG_DIR_CTL_OFFSET, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (value & WCD_PIN_MASK(pin))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return GPIO_LINE_DIRECTION_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return GPIO_LINE_DIRECTION_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static int wcd_gpio_direction_input(struct gpio_chip *chip, unsigned int pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct wcd_gpio_data *data = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return regmap_update_bits(data->map, WCD_REG_DIR_CTL_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) WCD_PIN_MASK(pin), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int wcd_gpio_direction_output(struct gpio_chip *chip, unsigned int pin,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct wcd_gpio_data *data = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) regmap_update_bits(data->map, WCD_REG_DIR_CTL_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) WCD_PIN_MASK(pin), WCD_PIN_MASK(pin));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return regmap_update_bits(data->map, WCD_REG_VAL_CTL_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) WCD_PIN_MASK(pin),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) val ? WCD_PIN_MASK(pin) : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static int wcd_gpio_get(struct gpio_chip *chip, unsigned int pin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct wcd_gpio_data *data = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) regmap_read(data->map, WCD_REG_VAL_CTL_OFFSET, &value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return !!(value & WCD_PIN_MASK(pin));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static void wcd_gpio_set(struct gpio_chip *chip, unsigned int pin, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct wcd_gpio_data *data = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) regmap_update_bits(data->map, WCD_REG_VAL_CTL_OFFSET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) WCD_PIN_MASK(pin), val ? WCD_PIN_MASK(pin) : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static int wcd_gpio_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct wcd_gpio_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct gpio_chip *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) data->map = dev_get_regmap(dev->parent, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (!data->map) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) dev_err(dev, "%s: failed to get regmap\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) chip = &data->chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) chip->direction_input = wcd_gpio_direction_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) chip->direction_output = wcd_gpio_direction_output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) chip->get_direction = wcd_gpio_get_direction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) chip->get = wcd_gpio_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) chip->set = wcd_gpio_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) chip->parent = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) chip->base = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) chip->ngpio = WCD934X_NPINS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) chip->label = dev_name(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) chip->of_gpio_n_cells = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) chip->can_sleep = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return devm_gpiochip_add_data(dev, chip, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static const struct of_device_id wcd_gpio_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) { .compatible = "qcom,wcd9340-gpio" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) { .compatible = "qcom,wcd9341-gpio" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) MODULE_DEVICE_TABLE(of, wcd_gpio_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static struct platform_driver wcd_gpio_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .name = "wcd934x-gpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .of_match_table = wcd_gpio_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .probe = wcd_gpio_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) module_platform_driver(wcd_gpio_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) MODULE_DESCRIPTION("Qualcomm Technologies, Inc WCD GPIO control driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) MODULE_LICENSE("GPL v2");