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

gpiolib: Add support for WM8350 GPIO controller

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Mark Brown and committed by
Samuel Ortiz
38f6ce45 59f25070

+192
+7
drivers/gpio/Kconfig
··· 185 185 Say yes here to access the GPIO signals of WM831x power management 186 186 chips from Wolfson Microelectronics. 187 187 188 + config GPIO_WM8350 189 + tristate "WM8350 GPIOs" 190 + depends on MFD_WM8350 191 + help 192 + Say yes here to access the GPIO signals of WM8350 power management 193 + chips from Wolfson Microelectronics. 194 + 188 195 config GPIO_ADP5520 189 196 tristate "GPIO Support for ADP5520 PMIC" 190 197 depends on PMIC_ADP5520
+1
drivers/gpio/Makefile
··· 25 25 obj-$(CONFIG_GPIO_IT8761E) += it8761e_gpio.o 26 26 obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o 27 27 obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o 28 + obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o
+181
drivers/gpio/wm8350-gpiolib.c
··· 1 + /* 2 + * wm835x-gpiolib.c -- gpiolib support for Wolfson WM835x PMICs 3 + * 4 + * Copyright 2009 Wolfson Microelectronics PLC. 5 + * 6 + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the 10 + * Free Software Foundation; either version 2 of the License, or (at your 11 + * option) any later version. 12 + * 13 + */ 14 + 15 + #include <linux/kernel.h> 16 + #include <linux/module.h> 17 + #include <linux/gpio.h> 18 + #include <linux/mfd/core.h> 19 + #include <linux/platform_device.h> 20 + #include <linux/seq_file.h> 21 + 22 + #include <linux/mfd/wm8350/core.h> 23 + #include <linux/mfd/wm8350/gpio.h> 24 + 25 + struct wm8350_gpio_data { 26 + struct wm8350 *wm8350; 27 + struct gpio_chip gpio_chip; 28 + }; 29 + 30 + static inline struct wm8350_gpio_data *to_wm8350_gpio(struct gpio_chip *chip) 31 + { 32 + return container_of(chip, struct wm8350_gpio_data, gpio_chip); 33 + } 34 + 35 + static int wm8350_gpio_direction_in(struct gpio_chip *chip, unsigned offset) 36 + { 37 + struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip); 38 + struct wm8350 *wm8350 = wm8350_gpio->wm8350; 39 + 40 + return wm8350_set_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O, 41 + 1 << offset); 42 + } 43 + 44 + static int wm8350_gpio_get(struct gpio_chip *chip, unsigned offset) 45 + { 46 + struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip); 47 + struct wm8350 *wm8350 = wm8350_gpio->wm8350; 48 + int ret; 49 + 50 + ret = wm8350_reg_read(wm8350, WM8350_GPIO_LEVEL); 51 + if (ret < 0) 52 + return ret; 53 + 54 + if (ret & (1 << offset)) 55 + return 1; 56 + else 57 + return 0; 58 + } 59 + 60 + static void wm8350_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 61 + { 62 + struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip); 63 + struct wm8350 *wm8350 = wm8350_gpio->wm8350; 64 + 65 + if (value) 66 + wm8350_set_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset); 67 + else 68 + wm8350_clear_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset); 69 + } 70 + 71 + static int wm8350_gpio_direction_out(struct gpio_chip *chip, 72 + unsigned offset, int value) 73 + { 74 + struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip); 75 + struct wm8350 *wm8350 = wm8350_gpio->wm8350; 76 + int ret; 77 + 78 + ret = wm8350_clear_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O, 79 + 1 << offset); 80 + if (ret < 0) 81 + return ret; 82 + 83 + /* Don't have an atomic direction/value setup */ 84 + wm8350_gpio_set(chip, offset, value); 85 + 86 + return 0; 87 + } 88 + 89 + static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 90 + { 91 + struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip); 92 + struct wm8350 *wm8350 = wm8350_gpio->wm8350; 93 + 94 + if (!wm8350->irq_base) 95 + return -EINVAL; 96 + 97 + return wm8350->irq_base + WM8350_IRQ_GPIO(offset); 98 + } 99 + 100 + static struct gpio_chip template_chip = { 101 + .label = "wm8350", 102 + .owner = THIS_MODULE, 103 + .direction_input = wm8350_gpio_direction_in, 104 + .get = wm8350_gpio_get, 105 + .direction_output = wm8350_gpio_direction_out, 106 + .set = wm8350_gpio_set, 107 + .to_irq = wm8350_gpio_to_irq, 108 + .can_sleep = 1, 109 + }; 110 + 111 + static int __devinit wm8350_gpio_probe(struct platform_device *pdev) 112 + { 113 + struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent); 114 + struct wm8350_platform_data *pdata = wm8350->dev->platform_data; 115 + struct wm8350_gpio_data *wm8350_gpio; 116 + int ret; 117 + 118 + wm8350_gpio = kzalloc(sizeof(*wm8350_gpio), GFP_KERNEL); 119 + if (wm8350_gpio == NULL) 120 + return -ENOMEM; 121 + 122 + wm8350_gpio->wm8350 = wm8350; 123 + wm8350_gpio->gpio_chip = template_chip; 124 + wm8350_gpio->gpio_chip.ngpio = 13; 125 + wm8350_gpio->gpio_chip.dev = &pdev->dev; 126 + if (pdata && pdata->gpio_base) 127 + wm8350_gpio->gpio_chip.base = pdata->gpio_base; 128 + else 129 + wm8350_gpio->gpio_chip.base = -1; 130 + 131 + ret = gpiochip_add(&wm8350_gpio->gpio_chip); 132 + if (ret < 0) { 133 + dev_err(&pdev->dev, "Could not register gpiochip, %d\n", 134 + ret); 135 + goto err; 136 + } 137 + 138 + platform_set_drvdata(pdev, wm8350_gpio); 139 + 140 + return ret; 141 + 142 + err: 143 + kfree(wm8350_gpio); 144 + return ret; 145 + } 146 + 147 + static int __devexit wm8350_gpio_remove(struct platform_device *pdev) 148 + { 149 + struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev); 150 + int ret; 151 + 152 + ret = gpiochip_remove(&wm8350_gpio->gpio_chip); 153 + if (ret == 0) 154 + kfree(wm8350_gpio); 155 + 156 + return ret; 157 + } 158 + 159 + static struct platform_driver wm8350_gpio_driver = { 160 + .driver.name = "wm8350-gpio", 161 + .driver.owner = THIS_MODULE, 162 + .probe = wm8350_gpio_probe, 163 + .remove = __devexit_p(wm8350_gpio_remove), 164 + }; 165 + 166 + static int __init wm8350_gpio_init(void) 167 + { 168 + return platform_driver_register(&wm8350_gpio_driver); 169 + } 170 + subsys_initcall(wm8350_gpio_init); 171 + 172 + static void __exit wm8350_gpio_exit(void) 173 + { 174 + platform_driver_unregister(&wm8350_gpio_driver); 175 + } 176 + module_exit(wm8350_gpio_exit); 177 + 178 + MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 179 + MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs"); 180 + MODULE_LICENSE("GPL"); 181 + MODULE_ALIAS("platform:wm8350-gpio");
+2
include/linux/mfd/wm8350/core.h
··· 645 645 * used by the platform to configure GPIO functions and similar. 646 646 * @irq_high: Set if WM8350 IRQ is active high. 647 647 * @irq_base: Base IRQ for genirq (not currently used). 648 + * @gpio_base: Base for gpiolib. 648 649 */ 649 650 struct wm8350_platform_data { 650 651 int (*init)(struct wm8350 *wm8350); 651 652 int irq_high; 652 653 int irq_base; 654 + int gpio_base; 653 655 }; 654 656 655 657
+1
include/linux/mfd/wm8350/gpio.h
··· 29 29 #define WM8350_GPIO_FUNCTION_SELECT_2 0x8D 30 30 #define WM8350_GPIO_FUNCTION_SELECT_3 0x8E 31 31 #define WM8350_GPIO_FUNCTION_SELECT_4 0x8F 32 + #define WM8350_GPIO_LEVEL 0xE6 32 33 33 34 /* 34 35 * GPIO Functions