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 23 static 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 40 static 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 50 static 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 143 static 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 155 static 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 167 static 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 179 static 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 188 int 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 219 err: 220 return -EIO; 221 } 222 EXPORT_SYMBOL_GPL(wm8350_gpio_config); 223