Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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