218 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * wm8350-core.c -- Device access for Wolfson WM83504 *5 * Copyright 2007, 2008 Wolfson Microelectronics PLC.6 *7 * Author: Liam Girdwood8 */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 else28 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 else41 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 else145 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 else157 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 else169 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 else179 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