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