linux/drivers/mfd/wm8350-gpio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * wm8350-core.c  --  Device access for Wolfson WM8350
   4 *
   5 * Copyright 2007, 2008 Wolfson Microelectronics PLC.
   6 *
   7 * Author: Liam Girdwood
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/errno.h>
  13
  14#include <linux/mfd/wm8350/core.h>
  15#include <linux/mfd/wm8350/gpio.h>
  16#include <linux/mfd/wm8350/pmic.h>
  17
  18static int gpio_set_dir(struct wm8350 *wm8350, int gpio, int dir)
  19{
  20        int ret;
  21
  22        wm8350_reg_unlock(wm8350);
  23        if (dir == WM8350_GPIO_DIR_OUT)
  24                ret = wm8350_clear_bits(wm8350,
  25                                        WM8350_GPIO_CONFIGURATION_I_O,
  26                                        1 << gpio);
  27        else
  28                ret = wm8350_set_bits(wm8350,
  29                                      WM8350_GPIO_CONFIGURATION_I_O,
  30                                      1 << gpio);
  31        wm8350_reg_lock(wm8350);
  32        return ret;
  33}
  34
  35static int wm8350_gpio_set_debounce(struct wm8350 *wm8350, int gpio, int db)
  36{
  37        if (db == WM8350_GPIO_DEBOUNCE_ON)
  38                return wm8350_set_bits(wm8350, WM8350_GPIO_DEBOUNCE,
  39                                       1 << gpio);
  40        else
  41                return wm8350_clear_bits(wm8350,
  42                                         WM8350_GPIO_DEBOUNCE, 1 << gpio);
  43}
  44
  45static int gpio_set_func(struct wm8350 *wm8350, int gpio, int func)
  46{
  47        u16 reg;
  48
  49        wm8350_reg_unlock(wm8350);
  50        switch (gpio) {
  51        case 0:
  52                reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
  53                    & ~WM8350_GP0_FN_MASK;
  54                wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
  55                                 reg | ((func & 0xf) << 0));
  56                break;
  57        case 1:
  58                reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
  59                    & ~WM8350_GP1_FN_MASK;
  60                wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
  61                                 reg | ((func & 0xf) << 4));
  62                break;
  63        case 2:
  64                reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
  65                    & ~WM8350_GP2_FN_MASK;
  66                wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
  67                                 reg | ((func & 0xf) << 8));
  68                break;
  69        case 3:
  70                reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1)
  71                    & ~WM8350_GP3_FN_MASK;
  72                wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1,
  73                                 reg | ((func & 0xf) << 12));
  74                break;
  75        case 4:
  76                reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
  77                    & ~WM8350_GP4_FN_MASK;
  78                wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
  79                                 reg | ((func & 0xf) << 0));
  80                break;
  81        case 5:
  82                reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
  83                    & ~WM8350_GP5_FN_MASK;
  84                wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
  85                                 reg | ((func & 0xf) << 4));
  86                break;
  87        case 6:
  88                reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
  89                    & ~WM8350_GP6_FN_MASK;
  90                wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
  91                                 reg | ((func & 0xf) << 8));
  92                break;
  93        case 7:
  94                reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2)
  95                    & ~WM8350_GP7_FN_MASK;
  96                wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2,
  97                                 reg | ((func & 0xf) << 12));
  98                break;
  99        case 8:
 100                reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
 101                    & ~WM8350_GP8_FN_MASK;
 102                wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
 103                                 reg | ((func & 0xf) << 0));
 104                break;
 105        case 9:
 106                reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
 107                    & ~WM8350_GP9_FN_MASK;
 108                wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
 109                                 reg | ((func & 0xf) << 4));
 110                break;
 111        case 10:
 112                reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
 113                    & ~WM8350_GP10_FN_MASK;
 114                wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
 115                                 reg | ((func & 0xf) << 8));
 116                break;
 117        case 11:
 118                reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3)
 119                    & ~WM8350_GP11_FN_MASK;
 120                wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3,
 121                                 reg | ((func & 0xf) << 12));
 122                break;
 123        case 12:
 124                reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_4)
 125                    & ~WM8350_GP12_FN_MASK;
 126                wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_4,
 127                                 reg | ((func & 0xf) << 0));
 128                break;
 129        default:
 130                wm8350_reg_lock(wm8350);
 131                return -EINVAL;
 132        }
 133
 134        wm8350_reg_lock(wm8350);
 135        return 0;
 136}
 137
 138static int gpio_set_pull_up(struct wm8350 *wm8350, int gpio, int up)
 139{
 140        if (up)
 141                return wm8350_set_bits(wm8350,
 142                                       WM8350_GPIO_PIN_PULL_UP_CONTROL,
 143                                       1 << gpio);
 144        else
 145                return wm8350_clear_bits(wm8350,
 146                                         WM8350_GPIO_PIN_PULL_UP_CONTROL,
 147                                         1 << gpio);
 148}
 149
 150static int gpio_set_pull_down(struct wm8350 *wm8350, int gpio, int down)
 151{
 152        if (down)
 153                return wm8350_set_bits(wm8350,
 154                                       WM8350_GPIO_PULL_DOWN_CONTROL,
 155                                       1 << gpio);
 156        else
 157                return wm8350_clear_bits(wm8350,
 158                                         WM8350_GPIO_PULL_DOWN_CONTROL,
 159                                         1 << gpio);
 160}
 161
 162static int gpio_set_polarity(struct wm8350 *wm8350, int gpio, int pol)
 163{
 164        if (pol == WM8350_GPIO_ACTIVE_HIGH)
 165                return wm8350_set_bits(wm8350,
 166                                       WM8350_GPIO_PIN_POLARITY_TYPE,
 167                                       1 << gpio);
 168        else
 169                return wm8350_clear_bits(wm8350,
 170                                         WM8350_GPIO_PIN_POLARITY_TYPE,
 171                                         1 << gpio);
 172}
 173
 174static int gpio_set_invert(struct wm8350 *wm8350, int gpio, int invert)
 175{
 176        if (invert == WM8350_GPIO_INVERT_ON)
 177                return wm8350_set_bits(wm8350, WM8350_GPIO_INT_MODE, 1 << gpio);
 178        else
 179                return wm8350_clear_bits(wm8350,
 180                                         WM8350_GPIO_INT_MODE, 1 << gpio);
 181}
 182
 183int wm8350_gpio_config(struct wm8350 *wm8350, int gpio, int dir, int func,
 184                       int pol, int pull, int invert, int debounce)
 185{
 186        /* make sure we never pull up and down at the same time */
 187        if (pull == WM8350_GPIO_PULL_NONE) {
 188                if (gpio_set_pull_up(wm8350, gpio, 0))
 189                        goto err;
 190                if (gpio_set_pull_down(wm8350, gpio, 0))
 191                        goto err;
 192        } else if (pull == WM8350_GPIO_PULL_UP) {
 193                if (gpio_set_pull_down(wm8350, gpio, 0))
 194                        goto err;
 195                if (gpio_set_pull_up(wm8350, gpio, 1))
 196                        goto err;
 197        } else if (pull == WM8350_GPIO_PULL_DOWN) {
 198                if (gpio_set_pull_up(wm8350, gpio, 0))
 199                        goto err;
 200                if (gpio_set_pull_down(wm8350, gpio, 1))
 201                        goto err;
 202        }
 203
 204        if (gpio_set_invert(wm8350, gpio, invert))
 205                goto err;
 206        if (gpio_set_polarity(wm8350, gpio, pol))
 207                goto err;
 208        if (wm8350_gpio_set_debounce(wm8350, gpio, debounce))
 209                goto err;
 210        if (gpio_set_dir(wm8350, gpio, dir))
 211                goto err;
 212        return gpio_set_func(wm8350, gpio, func);
 213
 214err:
 215        return -EIO;
 216}
 217EXPORT_SYMBOL_GPL(wm8350_gpio_config);
 218