mediatek/mt8173: Add APIs for PMIC GPIO control

BRANCH=chromeos-2015.07
BUG=none
TEST=verified on Oak rev3

Change-Id: Ied991f13b73e70b91cc267222f351b588df8df66
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 4bc08ce28611d8b940642483c09614d2b8205c1f
Original-Change-Id: If78e154ff7f553f65aa44d370820cc8c7f829c96
Original-Signed-off-by: Biao Huang <biao.huang@mediatek.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/297224
Original-Commit-Ready: Yidi Lin <yidi.lin@mediatek.com>
Original-Tested-by: Yidi Lin <yidi.lin@mediatek.com>
Original-Reviewed-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://review.coreboot.org/12609
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Biao Huang 2015-09-03 17:39:12 +08:00 committed by Patrick Georgi
parent 31ae314f0f
commit 0dd8315bcc
2 changed files with 194 additions and 0 deletions

View File

@ -308,4 +308,39 @@ void mt6391_write(u16 reg, u16 val, u32 mask, u32 shift);
void mt6391_enable_reset_when_ap_resets(void);
void mt6391_init(void);
/*
* PMIC GPIO REGISTER DEFINITION
*/
enum {
MT6391_GPIO_DIR_BASE = 0xC000,
MT6391_GPIO_PULLEN_BASE = 0xC020,
MT6391_GPIO_PULLSEL_BASE = 0xC040,
MT6391_GPIO_DOUT_BASE = 0xC080,
MT6391_GPIO_DIN_BASE = 0xC0A0,
MT6391_GPIO_MODE_BASE = 0xC0C0,
};
enum mt6391_pull_enable {
MT6391_GPIO_PULL_DISABLE = 0,
MT6391_GPIO_PULL_ENABLE = 1,
};
enum mt6391_pull_select {
MT6391_GPIO_PULL_DOWN = 0,
MT6391_GPIO_PULL_UP = 1,
};
/*
* PMIC GPIO Exported Function
*/
int mt6391_gpio_get(u32 gpio);
void mt6391_gpio_set(u32 gpio, int value);
void mt6391_gpio_input_pulldown(u32 gpio);
void mt6391_gpio_input_pullup(u32 gpio);
void mt6391_gpio_input(u32 gpio);
void mt6391_gpio_output(u32 gpio, int value);
void mt6391_gpio_set_pull(u32 gpio, enum mt6391_pull_enable enable,
enum mt6391_pull_select select);
void mt6391_gpio_set_mode(u32 gpio, int mode);
#endif /* __SOC_MEDIATEK_MT8173_MT6391_H__ */

View File

@ -16,11 +16,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <arch/io.h>
#include <assert.h>
#include <console/console.h>
#include <delay.h>
#include <soc/addressmap.h>
#include <soc/mt6391.h>
#include <soc/pmic_wrap.h>
#include <types.h>
#if CONFIG_DEBUG_PMIC
#define DEBUG_PMIC(level, x...) printk(level, x)
@ -432,3 +435,159 @@ void mt6391_init(void)
/* Adjust default BUCK voltage from eFuse */
mt6391_default_buck_voltage();
}
/* API of GPIO in PMIC MT6391 */
enum {
MAX_GPIO_REG_BITS = 16,
MAX_GPIO_MODE_PER_REG = 5,
GPIO_MODE_BITS = 3,
GPIO_PORT_OFFSET = 3,
GPIO_SET_OFFSET = 2,
GPIO_RST_OFFSET = 4,
MAX_MT6391_GPIO = 40
};
enum {
MT6391_GPIO_DIRECTION_IN = 0,
MT6391_GPIO_DIRECTION_OUT = 1,
};
enum {
MT6391_GPIO_MODE = 0,
};
static void pos_bit_calc(u32 pin, u16 *pos, u16 *bit)
{
*pos = (pin / MAX_GPIO_REG_BITS) << GPIO_PORT_OFFSET;
*bit = pin % MAX_GPIO_REG_BITS;
}
static void pos_bit_calc_mode(u32 pin, u16 *pos, u16 *bit)
{
*pos = (pin / MAX_GPIO_MODE_PER_REG) << GPIO_PORT_OFFSET;
*bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
}
static s32 mt6391_gpio_set_dir(u32 pin, u32 dir)
{
u16 pos;
u16 bit;
u16 reg;
assert(pin <= MAX_MT6391_GPIO);
pos_bit_calc(pin, &pos, &bit);
if (dir == MT6391_GPIO_DIRECTION_IN)
reg = MT6391_GPIO_DIR_BASE + pos + GPIO_RST_OFFSET;
else
reg = MT6391_GPIO_DIR_BASE + pos + GPIO_SET_OFFSET;
if (pwrap_write(reg, 1L << bit) != 0)
return -1;
return 0;
}
void mt6391_gpio_set_pull(u32 pin, enum mt6391_pull_enable enable,
enum mt6391_pull_select select)
{
u16 pos;
u16 bit;
u16 en_reg, sel_reg;
assert(pin <= MAX_MT6391_GPIO);
pos_bit_calc(pin, &pos, &bit);
if (enable == MT6391_GPIO_PULL_DISABLE) {
en_reg = MT6391_GPIO_PULLEN_BASE + pos + GPIO_RST_OFFSET;
} else {
en_reg = MT6391_GPIO_PULLEN_BASE + pos + GPIO_SET_OFFSET;
sel_reg = (select == MT6391_GPIO_PULL_DOWN) ?
(MT6391_GPIO_PULLSEL_BASE + pos + GPIO_RST_OFFSET) :
(MT6391_GPIO_PULLSEL_BASE + pos + GPIO_SET_OFFSET);
pwrap_write(sel_reg, 1L << bit);
}
pwrap_write(en_reg, 1L << bit);
}
int mt6391_gpio_get(u32 pin)
{
u16 pos;
u16 bit;
u16 reg;
u16 data;
assert(pin <= MAX_MT6391_GPIO);
pos_bit_calc(pin, &pos, &bit);
reg = MT6391_GPIO_DIN_BASE + pos;
pwrap_read(reg, &data);
return (data & (1L << bit)) ? 1 : 0;
}
void mt6391_gpio_set(u32 pin, int output)
{
u16 pos;
u16 bit;
u16 reg;
assert(pin <= MAX_MT6391_GPIO);
pos_bit_calc(pin, &pos, &bit);
if (output == 0)
reg = MT6391_GPIO_DOUT_BASE + pos + GPIO_RST_OFFSET;
else
reg = MT6391_GPIO_DOUT_BASE + pos + GPIO_SET_OFFSET;
pwrap_write(reg, 1L << bit);
}
void mt6391_gpio_set_mode(u32 pin, int mode)
{
u16 pos;
u16 bit;
u16 mask = (1L << GPIO_MODE_BITS) - 1;
assert(pin <= MAX_MT6391_GPIO);
pos_bit_calc_mode(pin, &pos, &bit);
mt6391_write(MT6391_GPIO_MODE_BASE + pos, mode, mask, bit);
}
void mt6391_gpio_input_pulldown(u32 gpio)
{
mt6391_gpio_set_pull(gpio, MT6391_GPIO_PULL_ENABLE,
MT6391_GPIO_PULL_DOWN);
mt6391_gpio_set_dir(gpio, MT6391_GPIO_DIRECTION_IN);
mt6391_gpio_set_mode(gpio, MT6391_GPIO_MODE);
}
void mt6391_gpio_input_pullup(u32 gpio)
{
mt6391_gpio_set_pull(gpio, MT6391_GPIO_PULL_ENABLE,
MT6391_GPIO_PULL_UP);
mt6391_gpio_set_dir(gpio, MT6391_GPIO_DIRECTION_IN);
mt6391_gpio_set_mode(gpio, MT6391_GPIO_MODE);
}
void mt6391_gpio_input(u32 gpio)
{
mt6391_gpio_set_pull(gpio, MT6391_GPIO_PULL_DISABLE,
MT6391_GPIO_PULL_DOWN);
mt6391_gpio_set_dir(gpio, MT6391_GPIO_DIRECTION_IN);
mt6391_gpio_set_mode(gpio, MT6391_GPIO_MODE);
}
void mt6391_gpio_output(u32 gpio, int value)
{
mt6391_gpio_set_pull(gpio, MT6391_GPIO_PULL_DISABLE,
MT6391_GPIO_PULL_DOWN);
mt6391_gpio_set(gpio, value);
mt6391_gpio_set_dir(gpio, MT6391_GPIO_DIRECTION_OUT);
mt6391_gpio_set_mode(gpio, MT6391_GPIO_MODE);
}