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 18 static 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 35 static 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 45 static 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 138 static 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 150 static 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 162 static 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 174 static 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 183 int 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 214 err: 215 return -EIO; 216 } 217 EXPORT_SYMBOL_GPL(wm8350_gpio_config); 218