0001
0002
0003
0004 #include <linux/module.h>
0005 #include <linux/gpio/driver.h>
0006 #include <linux/regmap.h>
0007 #include <linux/slab.h>
0008 #include <linux/of_device.h>
0009
0010 #define WCD_PIN_MASK(p) BIT(p)
0011 #define WCD_REG_DIR_CTL_OFFSET 0x42
0012 #define WCD_REG_VAL_CTL_OFFSET 0x43
0013 #define WCD934X_NPINS 5
0014
0015 struct wcd_gpio_data {
0016 struct regmap *map;
0017 struct gpio_chip chip;
0018 };
0019
0020 static int wcd_gpio_get_direction(struct gpio_chip *chip, unsigned int pin)
0021 {
0022 struct wcd_gpio_data *data = gpiochip_get_data(chip);
0023 unsigned int value;
0024 int ret;
0025
0026 ret = regmap_read(data->map, WCD_REG_DIR_CTL_OFFSET, &value);
0027 if (ret < 0)
0028 return ret;
0029
0030 if (value & WCD_PIN_MASK(pin))
0031 return GPIO_LINE_DIRECTION_OUT;
0032
0033 return GPIO_LINE_DIRECTION_IN;
0034 }
0035
0036 static int wcd_gpio_direction_input(struct gpio_chip *chip, unsigned int pin)
0037 {
0038 struct wcd_gpio_data *data = gpiochip_get_data(chip);
0039
0040 return regmap_update_bits(data->map, WCD_REG_DIR_CTL_OFFSET,
0041 WCD_PIN_MASK(pin), 0);
0042 }
0043
0044 static int wcd_gpio_direction_output(struct gpio_chip *chip, unsigned int pin,
0045 int val)
0046 {
0047 struct wcd_gpio_data *data = gpiochip_get_data(chip);
0048
0049 regmap_update_bits(data->map, WCD_REG_DIR_CTL_OFFSET,
0050 WCD_PIN_MASK(pin), WCD_PIN_MASK(pin));
0051
0052 return regmap_update_bits(data->map, WCD_REG_VAL_CTL_OFFSET,
0053 WCD_PIN_MASK(pin),
0054 val ? WCD_PIN_MASK(pin) : 0);
0055 }
0056
0057 static int wcd_gpio_get(struct gpio_chip *chip, unsigned int pin)
0058 {
0059 struct wcd_gpio_data *data = gpiochip_get_data(chip);
0060 unsigned int value;
0061
0062 regmap_read(data->map, WCD_REG_VAL_CTL_OFFSET, &value);
0063
0064 return !!(value & WCD_PIN_MASK(pin));
0065 }
0066
0067 static void wcd_gpio_set(struct gpio_chip *chip, unsigned int pin, int val)
0068 {
0069 struct wcd_gpio_data *data = gpiochip_get_data(chip);
0070
0071 regmap_update_bits(data->map, WCD_REG_VAL_CTL_OFFSET,
0072 WCD_PIN_MASK(pin), val ? WCD_PIN_MASK(pin) : 0);
0073 }
0074
0075 static int wcd_gpio_probe(struct platform_device *pdev)
0076 {
0077 struct device *dev = &pdev->dev;
0078 struct wcd_gpio_data *data;
0079 struct gpio_chip *chip;
0080
0081 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
0082 if (!data)
0083 return -ENOMEM;
0084
0085 data->map = dev_get_regmap(dev->parent, NULL);
0086 if (!data->map) {
0087 dev_err(dev, "%s: failed to get regmap\n", __func__);
0088 return -EINVAL;
0089 }
0090
0091 chip = &data->chip;
0092 chip->direction_input = wcd_gpio_direction_input;
0093 chip->direction_output = wcd_gpio_direction_output;
0094 chip->get_direction = wcd_gpio_get_direction;
0095 chip->get = wcd_gpio_get;
0096 chip->set = wcd_gpio_set;
0097 chip->parent = dev;
0098 chip->base = -1;
0099 chip->ngpio = WCD934X_NPINS;
0100 chip->label = dev_name(dev);
0101 chip->of_gpio_n_cells = 2;
0102 chip->can_sleep = false;
0103
0104 return devm_gpiochip_add_data(dev, chip, data);
0105 }
0106
0107 static const struct of_device_id wcd_gpio_of_match[] = {
0108 { .compatible = "qcom,wcd9340-gpio" },
0109 { .compatible = "qcom,wcd9341-gpio" },
0110 { }
0111 };
0112 MODULE_DEVICE_TABLE(of, wcd_gpio_of_match);
0113
0114 static struct platform_driver wcd_gpio_driver = {
0115 .driver = {
0116 .name = "wcd934x-gpio",
0117 .of_match_table = wcd_gpio_of_match,
0118 },
0119 .probe = wcd_gpio_probe,
0120 };
0121
0122 module_platform_driver(wcd_gpio_driver);
0123 MODULE_DESCRIPTION("Qualcomm Technologies, Inc WCD GPIO control driver");
0124 MODULE_LICENSE("GPL v2");