mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-23 13:56:20 +00:00
drivers: gpio: implement MAX77663 GPIO cell
MAXIM Semiconductor's PMIC, MAX77663 has 8 GPIO pins and 3 GPIO-like pins. It also supports interrupts from these pins. Add GPIO driver for these pins to control via GPIO APIs. Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
This commit is contained in:
parent
936d0f9dd7
commit
6b24c372c1
6 changed files with 216 additions and 0 deletions
|
@ -238,6 +238,15 @@ config MAX7320_GPIO
|
||||||
original maxim device has 8 push/pull outputs,
|
original maxim device has 8 push/pull outputs,
|
||||||
some clones offers 16bit.
|
some clones offers 16bit.
|
||||||
|
|
||||||
|
config MAX77663_GPIO
|
||||||
|
bool "MAX77663 GPIO cell of PMIC driver"
|
||||||
|
depends on DM_GPIO && DM_PMIC_MAX77663
|
||||||
|
help
|
||||||
|
GPIO driver for MAX77663 PMIC from Maxim Semiconductor.
|
||||||
|
MAX77663 PMIC has 8 pins that can be configured as GPIOs
|
||||||
|
and 3 GPIO-like pins dedicated for power/reset buttons
|
||||||
|
and LID sensor.
|
||||||
|
|
||||||
config MCP230XX_GPIO
|
config MCP230XX_GPIO
|
||||||
bool "MCP230XX GPIO driver"
|
bool "MCP230XX GPIO driver"
|
||||||
depends on DM
|
depends on DM
|
||||||
|
|
|
@ -68,6 +68,7 @@ obj-$(CONFIG_NX_GPIO) += nx_gpio.o
|
||||||
obj-$(CONFIG_SIFIVE_GPIO) += sifive-gpio.o
|
obj-$(CONFIG_SIFIVE_GPIO) += sifive-gpio.o
|
||||||
obj-$(CONFIG_NOMADIK_GPIO) += nmk_gpio.o
|
obj-$(CONFIG_NOMADIK_GPIO) += nmk_gpio.o
|
||||||
obj-$(CONFIG_MAX7320_GPIO) += max7320_gpio.o
|
obj-$(CONFIG_MAX7320_GPIO) += max7320_gpio.o
|
||||||
|
obj-$(CONFIG_$(SPL_)MAX77663_GPIO) += max77663_gpio.o
|
||||||
obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o
|
obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o
|
||||||
obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o
|
obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o
|
||||||
obj-$(CONFIG_SLG7XL45106_I2C_GPO) += gpio_slg7xl45106.o
|
obj-$(CONFIG_SLG7XL45106_I2C_GPO) += gpio_slg7xl45106.o
|
||||||
|
|
178
drivers/gpio/max77663_gpio.c
Normal file
178
drivers/gpio/max77663_gpio.c
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
/*
|
||||||
|
* Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dm.h>
|
||||||
|
#include <asm/gpio.h>
|
||||||
|
#include <power/max77663.h>
|
||||||
|
#include <power/pmic.h>
|
||||||
|
|
||||||
|
#define NUM_ENTRIES 11 /* 8 GPIOs + 3 KEYs */
|
||||||
|
#define NUM_GPIOS 8
|
||||||
|
|
||||||
|
#define MAX77663_CNFG1_GPIO 0x36
|
||||||
|
#define GPIO_REG_ADDR(offset) (MAX77663_CNFG1_GPIO + (offset))
|
||||||
|
|
||||||
|
#define MAX77663_CNFG_GPIO_DIR_MASK BIT(1)
|
||||||
|
#define MAX77663_CNFG_GPIO_DIR_INPUT BIT(1)
|
||||||
|
#define MAX77663_CNFG_GPIO_DIR_OUTPUT 0
|
||||||
|
#define MAX77663_CNFG_GPIO_INPUT_VAL_MASK BIT(2)
|
||||||
|
#define MAX77663_CNFG_GPIO_OUTPUT_VAL_MASK BIT(3)
|
||||||
|
#define MAX77663_CNFG_GPIO_OUTPUT_VAL_HIGH BIT(3)
|
||||||
|
#define MAX77663_CNFG_GPIO_OUTPUT_VAL_LOW 0
|
||||||
|
#define MAX77663_CNFG_IRQ GENMASK(5, 4)
|
||||||
|
|
||||||
|
#define MAX77663_ONOFFSTAT_REG 0x15
|
||||||
|
#define EN0 BIT(2) /* KEY 2 */
|
||||||
|
#define ACOK BIT(1) /* KEY 1 */
|
||||||
|
#define LID BIT(0) /* KEY 0 */
|
||||||
|
|
||||||
|
static int max77663_gpio_direction_input(struct udevice *dev, unsigned int offset)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (offset >= NUM_GPIOS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = pmic_clrsetbits(dev->parent, GPIO_REG_ADDR(offset),
|
||||||
|
MAX77663_CNFG_GPIO_DIR_MASK,
|
||||||
|
MAX77663_CNFG_GPIO_DIR_INPUT);
|
||||||
|
if (ret < 0)
|
||||||
|
log_debug("%s: CNFG_GPIOx dir update failed: %d\n", __func__, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int max77663_gpio_direction_output(struct udevice *dev, unsigned int offset,
|
||||||
|
int value)
|
||||||
|
{
|
||||||
|
u8 val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (offset >= NUM_GPIOS)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
val = (value) ? MAX77663_CNFG_GPIO_OUTPUT_VAL_HIGH :
|
||||||
|
MAX77663_CNFG_GPIO_OUTPUT_VAL_LOW;
|
||||||
|
|
||||||
|
ret = pmic_clrsetbits(dev->parent, GPIO_REG_ADDR(offset),
|
||||||
|
MAX77663_CNFG_GPIO_OUTPUT_VAL_MASK, val);
|
||||||
|
if (ret < 0) {
|
||||||
|
log_debug("%s: CNFG_GPIOx val update failed: %d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pmic_clrsetbits(dev->parent, GPIO_REG_ADDR(offset),
|
||||||
|
MAX77663_CNFG_GPIO_DIR_MASK,
|
||||||
|
MAX77663_CNFG_GPIO_DIR_OUTPUT);
|
||||||
|
if (ret < 0)
|
||||||
|
log_debug("%s: CNFG_GPIOx dir update failed: %d\n", __func__, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int max77663_gpio_get_value(struct udevice *dev, unsigned int offset)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (offset >= NUM_GPIOS) {
|
||||||
|
ret = pmic_reg_read(dev->parent, MAX77663_ONOFFSTAT_REG);
|
||||||
|
if (ret < 0) {
|
||||||
|
log_debug("%s: ONOFFSTAT_REG read failed: %d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!(ret & BIT(offset - NUM_GPIOS));
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pmic_reg_read(dev->parent, GPIO_REG_ADDR(offset));
|
||||||
|
if (ret < 0) {
|
||||||
|
log_debug("%s: CNFG_GPIOx read failed: %d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret & MAX77663_CNFG_GPIO_DIR_MASK)
|
||||||
|
return !!(ret & MAX77663_CNFG_GPIO_INPUT_VAL_MASK);
|
||||||
|
else
|
||||||
|
return !!(ret & MAX77663_CNFG_GPIO_OUTPUT_VAL_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int max77663_gpio_set_value(struct udevice *dev, unsigned int offset,
|
||||||
|
int value)
|
||||||
|
{
|
||||||
|
u8 val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (offset >= NUM_GPIOS)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
val = (value) ? MAX77663_CNFG_GPIO_OUTPUT_VAL_HIGH :
|
||||||
|
MAX77663_CNFG_GPIO_OUTPUT_VAL_LOW;
|
||||||
|
|
||||||
|
ret = pmic_clrsetbits(dev->parent, GPIO_REG_ADDR(offset),
|
||||||
|
MAX77663_CNFG_GPIO_OUTPUT_VAL_MASK, val);
|
||||||
|
if (ret < 0)
|
||||||
|
log_debug("%s: CNFG_GPIO_OUT update failed: %d\n", __func__, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int max77663_gpio_get_function(struct udevice *dev, unsigned int offset)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (offset >= NUM_GPIOS)
|
||||||
|
return GPIOF_INPUT;
|
||||||
|
|
||||||
|
ret = pmic_reg_read(dev->parent, GPIO_REG_ADDR(offset));
|
||||||
|
if (ret < 0) {
|
||||||
|
log_debug("%s: CNFG_GPIOx read failed: %d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret & MAX77663_CNFG_GPIO_DIR_MASK)
|
||||||
|
return GPIOF_INPUT;
|
||||||
|
else
|
||||||
|
return GPIOF_OUTPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dm_gpio_ops max77663_gpio_ops = {
|
||||||
|
.direction_input = max77663_gpio_direction_input,
|
||||||
|
.direction_output = max77663_gpio_direction_output,
|
||||||
|
.get_value = max77663_gpio_get_value,
|
||||||
|
.set_value = max77663_gpio_set_value,
|
||||||
|
.get_function = max77663_gpio_get_function,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int max77663_gpio_probe(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
uc_priv->gpio_count = NUM_ENTRIES;
|
||||||
|
uc_priv->bank_name = "GPIO";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GPIO interrupts may be left ON after bootloader, hence let's
|
||||||
|
* pre-initialize hardware to the expected state by disabling all
|
||||||
|
* the interrupts.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < NUM_GPIOS; i++) {
|
||||||
|
ret = pmic_clrsetbits(dev->parent, GPIO_REG_ADDR(i),
|
||||||
|
MAX77663_CNFG_IRQ, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
log_debug("%s: failed to disable interrupt: %d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
U_BOOT_DRIVER(max77663_gpio) = {
|
||||||
|
.name = MAX77663_GPIO_DRIVER,
|
||||||
|
.id = UCLASS_GPIO,
|
||||||
|
.probe = max77663_gpio_probe,
|
||||||
|
.ops = &max77663_gpio_ops,
|
||||||
|
};
|
|
@ -55,6 +55,15 @@ static int max77663_bind(struct udevice *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_MAX77663_GPIO)) {
|
||||||
|
ret = device_bind_driver(dev, MAX77663_GPIO_DRIVER,
|
||||||
|
"gpio", NULL);
|
||||||
|
if (ret) {
|
||||||
|
log_err("cannot bind GPIOs (ret = %d)\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
regulators_node = dev_read_subnode(dev, "regulators");
|
regulators_node = dev_read_subnode(dev, "regulators");
|
||||||
if (!ofnode_valid(regulators_node)) {
|
if (!ofnode_valid(regulators_node)) {
|
||||||
log_err("%s regulators subnode not found!\n", dev->name);
|
log_err("%s regulators subnode not found!\n", dev->name);
|
||||||
|
|
18
include/dt-bindings/pmic/max77663.h
Normal file
18
include/dt-bindings/pmic/max77663.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
/*
|
||||||
|
* Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DT_BINDINGS_MAX77663_H_
|
||||||
|
#define _DT_BINDINGS_MAX77663_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MAX77663 has 8 GPIO (0 to 7) and 3 KEYS
|
||||||
|
* KEYS are appended after GPIOs
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EN0 10
|
||||||
|
#define ACOK 9
|
||||||
|
#define LID 8
|
||||||
|
|
||||||
|
#endif
|
|
@ -13,6 +13,7 @@
|
||||||
#define MAX77663_LDO_DRIVER "max77663_ldo"
|
#define MAX77663_LDO_DRIVER "max77663_ldo"
|
||||||
#define MAX77663_SD_DRIVER "max77663_sd"
|
#define MAX77663_SD_DRIVER "max77663_sd"
|
||||||
#define MAX77663_RST_DRIVER "max77663_rst"
|
#define MAX77663_RST_DRIVER "max77663_rst"
|
||||||
|
#define MAX77663_GPIO_DRIVER "max77663_gpio"
|
||||||
|
|
||||||
/* Step-Down (SD) Regulator calculations */
|
/* Step-Down (SD) Regulator calculations */
|
||||||
#define SD_STATUS_MASK 0x30
|
#define SD_STATUS_MASK 0x30
|
||||||
|
|
Loading…
Add table
Reference in a new issue