forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
5.8 KiB
217 lines
5.8 KiB
// SPDX-License-Identifier: GPL-2.0-or-later |
|
/* |
|
* wm8350-core.c -- Device access for Wolfson WM8350 |
|
* |
|
* Copyright 2007, 2008 Wolfson Microelectronics PLC. |
|
* |
|
* Author: Liam Girdwood |
|
*/ |
|
|
|
#include <linux/kernel.h> |
|
#include <linux/module.h> |
|
#include <linux/errno.h> |
|
|
|
#include <linux/mfd/wm8350/core.h> |
|
#include <linux/mfd/wm8350/gpio.h> |
|
#include <linux/mfd/wm8350/pmic.h> |
|
|
|
static int gpio_set_dir(struct wm8350 *wm8350, int gpio, int dir) |
|
{ |
|
int ret; |
|
|
|
wm8350_reg_unlock(wm8350); |
|
if (dir == WM8350_GPIO_DIR_OUT) |
|
ret = wm8350_clear_bits(wm8350, |
|
WM8350_GPIO_CONFIGURATION_I_O, |
|
1 << gpio); |
|
else |
|
ret = wm8350_set_bits(wm8350, |
|
WM8350_GPIO_CONFIGURATION_I_O, |
|
1 << gpio); |
|
wm8350_reg_lock(wm8350); |
|
return ret; |
|
} |
|
|
|
static int wm8350_gpio_set_debounce(struct wm8350 *wm8350, int gpio, int db) |
|
{ |
|
if (db == WM8350_GPIO_DEBOUNCE_ON) |
|
return wm8350_set_bits(wm8350, WM8350_GPIO_DEBOUNCE, |
|
1 << gpio); |
|
else |
|
return wm8350_clear_bits(wm8350, |
|
WM8350_GPIO_DEBOUNCE, 1 << gpio); |
|
} |
|
|
|
static int gpio_set_func(struct wm8350 *wm8350, int gpio, int func) |
|
{ |
|
u16 reg; |
|
|
|
wm8350_reg_unlock(wm8350); |
|
switch (gpio) { |
|
case 0: |
|
reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1) |
|
& ~WM8350_GP0_FN_MASK; |
|
wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1, |
|
reg | ((func & 0xf) << 0)); |
|
break; |
|
case 1: |
|
reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1) |
|
& ~WM8350_GP1_FN_MASK; |
|
wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1, |
|
reg | ((func & 0xf) << 4)); |
|
break; |
|
case 2: |
|
reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1) |
|
& ~WM8350_GP2_FN_MASK; |
|
wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1, |
|
reg | ((func & 0xf) << 8)); |
|
break; |
|
case 3: |
|
reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_1) |
|
& ~WM8350_GP3_FN_MASK; |
|
wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_1, |
|
reg | ((func & 0xf) << 12)); |
|
break; |
|
case 4: |
|
reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2) |
|
& ~WM8350_GP4_FN_MASK; |
|
wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2, |
|
reg | ((func & 0xf) << 0)); |
|
break; |
|
case 5: |
|
reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2) |
|
& ~WM8350_GP5_FN_MASK; |
|
wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2, |
|
reg | ((func & 0xf) << 4)); |
|
break; |
|
case 6: |
|
reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2) |
|
& ~WM8350_GP6_FN_MASK; |
|
wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2, |
|
reg | ((func & 0xf) << 8)); |
|
break; |
|
case 7: |
|
reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_2) |
|
& ~WM8350_GP7_FN_MASK; |
|
wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_2, |
|
reg | ((func & 0xf) << 12)); |
|
break; |
|
case 8: |
|
reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3) |
|
& ~WM8350_GP8_FN_MASK; |
|
wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3, |
|
reg | ((func & 0xf) << 0)); |
|
break; |
|
case 9: |
|
reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3) |
|
& ~WM8350_GP9_FN_MASK; |
|
wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3, |
|
reg | ((func & 0xf) << 4)); |
|
break; |
|
case 10: |
|
reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3) |
|
& ~WM8350_GP10_FN_MASK; |
|
wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3, |
|
reg | ((func & 0xf) << 8)); |
|
break; |
|
case 11: |
|
reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_3) |
|
& ~WM8350_GP11_FN_MASK; |
|
wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_3, |
|
reg | ((func & 0xf) << 12)); |
|
break; |
|
case 12: |
|
reg = wm8350_reg_read(wm8350, WM8350_GPIO_FUNCTION_SELECT_4) |
|
& ~WM8350_GP12_FN_MASK; |
|
wm8350_reg_write(wm8350, WM8350_GPIO_FUNCTION_SELECT_4, |
|
reg | ((func & 0xf) << 0)); |
|
break; |
|
default: |
|
wm8350_reg_lock(wm8350); |
|
return -EINVAL; |
|
} |
|
|
|
wm8350_reg_lock(wm8350); |
|
return 0; |
|
} |
|
|
|
static int gpio_set_pull_up(struct wm8350 *wm8350, int gpio, int up) |
|
{ |
|
if (up) |
|
return wm8350_set_bits(wm8350, |
|
WM8350_GPIO_PIN_PULL_UP_CONTROL, |
|
1 << gpio); |
|
else |
|
return wm8350_clear_bits(wm8350, |
|
WM8350_GPIO_PIN_PULL_UP_CONTROL, |
|
1 << gpio); |
|
} |
|
|
|
static int gpio_set_pull_down(struct wm8350 *wm8350, int gpio, int down) |
|
{ |
|
if (down) |
|
return wm8350_set_bits(wm8350, |
|
WM8350_GPIO_PULL_DOWN_CONTROL, |
|
1 << gpio); |
|
else |
|
return wm8350_clear_bits(wm8350, |
|
WM8350_GPIO_PULL_DOWN_CONTROL, |
|
1 << gpio); |
|
} |
|
|
|
static int gpio_set_polarity(struct wm8350 *wm8350, int gpio, int pol) |
|
{ |
|
if (pol == WM8350_GPIO_ACTIVE_HIGH) |
|
return wm8350_set_bits(wm8350, |
|
WM8350_GPIO_PIN_POLARITY_TYPE, |
|
1 << gpio); |
|
else |
|
return wm8350_clear_bits(wm8350, |
|
WM8350_GPIO_PIN_POLARITY_TYPE, |
|
1 << gpio); |
|
} |
|
|
|
static int gpio_set_invert(struct wm8350 *wm8350, int gpio, int invert) |
|
{ |
|
if (invert == WM8350_GPIO_INVERT_ON) |
|
return wm8350_set_bits(wm8350, WM8350_GPIO_INT_MODE, 1 << gpio); |
|
else |
|
return wm8350_clear_bits(wm8350, |
|
WM8350_GPIO_INT_MODE, 1 << gpio); |
|
} |
|
|
|
int wm8350_gpio_config(struct wm8350 *wm8350, int gpio, int dir, int func, |
|
int pol, int pull, int invert, int debounce) |
|
{ |
|
/* make sure we never pull up and down at the same time */ |
|
if (pull == WM8350_GPIO_PULL_NONE) { |
|
if (gpio_set_pull_up(wm8350, gpio, 0)) |
|
goto err; |
|
if (gpio_set_pull_down(wm8350, gpio, 0)) |
|
goto err; |
|
} else if (pull == WM8350_GPIO_PULL_UP) { |
|
if (gpio_set_pull_down(wm8350, gpio, 0)) |
|
goto err; |
|
if (gpio_set_pull_up(wm8350, gpio, 1)) |
|
goto err; |
|
} else if (pull == WM8350_GPIO_PULL_DOWN) { |
|
if (gpio_set_pull_up(wm8350, gpio, 0)) |
|
goto err; |
|
if (gpio_set_pull_down(wm8350, gpio, 1)) |
|
goto err; |
|
} |
|
|
|
if (gpio_set_invert(wm8350, gpio, invert)) |
|
goto err; |
|
if (gpio_set_polarity(wm8350, gpio, pol)) |
|
goto err; |
|
if (wm8350_gpio_set_debounce(wm8350, gpio, debounce)) |
|
goto err; |
|
if (gpio_set_dir(wm8350, gpio, dir)) |
|
goto err; |
|
return gpio_set_func(wm8350, gpio, func); |
|
|
|
err: |
|
return -EIO; |
|
} |
|
EXPORT_SYMBOL_GPL(wm8350_gpio_config);
|
|
|