Merge tag 'ib-mfd-gpio-nvmem-v6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd into gpio/for-next

Immutable branch between MFD, GPIO and NVMEM due for the v6.16 merge window
This commit is contained in:
Bartosz Golaszewski
2025-05-13 15:11:12 +02:00
14 changed files with 1764 additions and 0 deletions
@@ -0,0 +1,44 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/maxim,max77759-gpio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim Integrated MAX77759 GPIO
maintainers:
- André Draszik <andre.draszik@linaro.org>
description: |
This module is part of the MAX77759 PMIC. For additional information, see
Documentation/devicetree/bindings/mfd/maxim,max77759.yaml.
The MAX77759 is a PMIC integrating, amongst others, a GPIO controller
including interrupt support for 2 GPIO lines.
properties:
compatible:
const: maxim,max77759-gpio
"#gpio-cells":
const: 2
gpio-controller: true
gpio-line-names:
minItems: 1
maxItems: 2
"#interrupt-cells":
const: 2
interrupt-controller: true
required:
- compatible
- "#gpio-cells"
- gpio-controller
- "#interrupt-cells"
- interrupt-controller
additionalProperties: false
@@ -0,0 +1,99 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/maxim,max77759.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim Integrated MAX77759 PMIC for USB Type-C applications
maintainers:
- André Draszik <andre.draszik@linaro.org>
description: |
This is a part of device tree bindings for the MAX77759 companion Power
Management IC for USB Type-C applications.
The MAX77759 includes Battery Charger, Fuel Gauge, temperature sensors, USB
Type-C Port Controller (TCPC), NVMEM, and a GPIO expander.
properties:
compatible:
const: maxim,max77759
interrupts:
maxItems: 1
interrupt-controller: true
"#interrupt-cells":
const: 2
reg:
maxItems: 1
gpio:
$ref: /schemas/gpio/maxim,max77759-gpio.yaml
nvmem-0:
$ref: /schemas/nvmem/maxim,max77759-nvmem.yaml
required:
- compatible
- interrupts
- reg
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pmic@66 {
compatible = "maxim,max77759";
reg = <0x66>;
interrupts-extended = <&gpa8 3 IRQ_TYPE_LEVEL_LOW>;
interrupt-controller;
#interrupt-cells = <2>;
gpio {
compatible = "maxim,max77759-gpio";
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
};
nvmem-0 {
compatible = "maxim,max77759-nvmem";
nvmem-layout {
compatible = "fixed-layout";
#address-cells = <1>;
#size-cells = <1>;
reboot-mode@0 {
reg = <0x0 0x4>;
};
boot-reason@4 {
reg = <0x4 0x4>;
};
shutdown-user-flag@8 {
reg = <0x8 0x1>;
};
rsoc@10 {
reg = <0xa 0x2>;
};
};
};
};
};
@@ -0,0 +1,32 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/nvmem/maxim,max77759-nvmem.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Maxim Integrated MAX77759 Non Volatile Memory
maintainers:
- André Draszik <andre.draszik@linaro.org>
description: |
This module is part of the MAX77759 PMIC. For additional information, see
Documentation/devicetree/bindings/mfd/maxim,max77759.yaml.
The MAX77759 is a PMIC integrating, amongst others, Non Volatile Memory
(NVMEM) with 30 bytes of storage which can be used by software to store
information or communicate with a boot loader.
properties:
compatible:
const: maxim,max77759-nvmem
wp-gpios: false
required:
- compatible
allOf:
- $ref: nvmem.yaml#
unevaluatedProperties: false
+10
View File
@@ -14585,6 +14585,16 @@ F: Documentation/devicetree/bindings/mfd/maxim,max77714.yaml
F: drivers/mfd/max77714.c
F: include/linux/mfd/max77714.h
MAXIM MAX77759 PMIC MFD DRIVER
M: André Draszik <andre.draszik@linaro.org>
L: linux-kernel@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/*/maxim,max77759*.yaml
F: drivers/gpio/gpio-max77759.c
F: drivers/mfd/max77759.c
F: drivers/nvmem/max77759-nvmem.c
F: include/linux/mfd/max77759.h
MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER
M: Javier Martinez Canillas <javier@dowhile0.org>
L: linux-kernel@vger.kernel.org
+13
View File
@@ -1483,6 +1483,19 @@ config GPIO_MAX77650
GPIO driver for MAX77650/77651 PMIC from Maxim Semiconductor.
These chips have a single pin that can be configured as GPIO.
config GPIO_MAX77759
tristate "Maxim Integrated MAX77759 GPIO support"
depends on MFD_MAX77759
default MFD_MAX77759
select GPIOLIB_IRQCHIP
help
GPIO driver for MAX77759 PMIC from Maxim Integrated.
There are two GPIOs available on these chips in total, both of
which can also generate interrupts.
This driver can also be built as a module. If so, the module will be
called gpio-max77759.
config GPIO_PALMAS
bool "TI PALMAS series PMICs GPIO"
depends on MFD_PALMAS
+1
View File
@@ -106,6 +106,7 @@ obj-$(CONFIG_GPIO_MAX730X) += gpio-max730x.o
obj-$(CONFIG_GPIO_MAX732X) += gpio-max732x.o
obj-$(CONFIG_GPIO_MAX77620) += gpio-max77620.o
obj-$(CONFIG_GPIO_MAX77650) += gpio-max77650.o
obj-$(CONFIG_GPIO_MAX77759) += gpio-max77759.o
obj-$(CONFIG_GPIO_MB86S7X) += gpio-mb86s7x.o
obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o
obj-$(CONFIG_GPIO_MENZ127) += gpio-menz127.o
File diff suppressed because it is too large Load Diff
+20
View File
@@ -943,6 +943,26 @@ config MFD_MAX77714
drivers must be enabled in order to use each functionality of the
device.
config MFD_MAX77759
tristate "Maxim Integrated MAX77759 PMIC"
depends on I2C
depends on OF
select IRQ_DOMAIN
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
help
Say yes here to add support for Maxim Integrated MAX77759.
This is a companion Power Management IC for USB Type-C applications
with Battery Charger, Fuel Gauge, temperature sensors, USB Type-C
Port Controller (TCPC), NVMEM, and additional GPIO interfaces.
This driver provides common support for accessing the device;
additional drivers must be enabled in order to use the functionality
of the device.
To compile this driver as a module, choose M here: the module will be
called max77759.
config MFD_MAX77843
bool "Maxim Semiconductor MAX77843 PMIC Support"
depends on I2C=y
+1
View File
@@ -169,6 +169,7 @@ obj-$(CONFIG_MFD_MAX77686) += max77686.o
obj-$(CONFIG_MFD_MAX77693) += max77693.o
obj-$(CONFIG_MFD_MAX77705) += max77705.o
obj-$(CONFIG_MFD_MAX77714) += max77714.o
obj-$(CONFIG_MFD_MAX77759) += max77759.o
obj-$(CONFIG_MFD_MAX77843) += max77843.o
obj-$(CONFIG_MFD_MAX8907) += max8907.o
max8925-objs := max8925-core.o max8925-i2c.o
File diff suppressed because it is too large Load Diff
+12
View File
@@ -154,6 +154,18 @@ config NVMEM_LPC18XX_OTP
To compile this driver as a module, choose M here: the module
will be called nvmem_lpc18xx_otp.
config NVMEM_MAX77759
tristate "Maxim Integrated MAX77759 NVMEM Support"
depends on MFD_MAX77759
default MFD_MAX77759
help
Say Y here to include support for the user-accessible storage found
in Maxim Integrated MAX77759 PMICs. This IC provides space for 30
bytes of storage.
This driver can also be built as a module. If so, the module
will be called nvmem-max77759.
config NVMEM_MESON_EFUSE
tristate "Amlogic Meson GX eFuse Support"
depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM
+2
View File
@@ -34,6 +34,8 @@ obj-$(CONFIG_NVMEM_LPC18XX_EEPROM) += nvmem_lpc18xx_eeprom.o
nvmem_lpc18xx_eeprom-y := lpc18xx_eeprom.o
obj-$(CONFIG_NVMEM_LPC18XX_OTP) += nvmem_lpc18xx_otp.o
nvmem_lpc18xx_otp-y := lpc18xx_otp.o
obj-$(CONFIG_NVMEM_MAX77759) += nvmem-max77759.o
nvmem-max77759-y := max77759-nvmem.o
obj-$(CONFIG_NVMEM_MESON_EFUSE) += nvmem_meson_efuse.o
nvmem_meson_efuse-y := meson-efuse.o
obj-$(CONFIG_NVMEM_MESON_MX_EFUSE) += nvmem_meson_mx_efuse.o
+145
View File
@@ -0,0 +1,145 @@
// SPDX-License-Identifier: GPL-2.0-only
//
// Copyright 2020 Google Inc
// Copyright 2025 Linaro Ltd.
//
// NVMEM driver for Maxim MAX77759
#include <linux/dev_printk.h>
#include <linux/device.h>
#include <linux/device/driver.h>
#include <linux/err.h>
#include <linux/mfd/max77759.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/overflow.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#define MAX77759_NVMEM_OPCODE_HEADER_LEN 3
/*
* NVMEM commands have a three byte header (which becomes part of the command),
* so we need to subtract that.
*/
#define MAX77759_NVMEM_SIZE (MAX77759_MAXQ_OPCODE_MAXLENGTH \
- MAX77759_NVMEM_OPCODE_HEADER_LEN)
struct max77759_nvmem {
struct device *dev;
struct max77759 *max77759;
};
static int max77759_nvmem_reg_read(void *priv, unsigned int offset,
void *val, size_t bytes)
{
struct max77759_nvmem *nvmem = priv;
DEFINE_FLEX(struct max77759_maxq_command, cmd, cmd, length,
MAX77759_NVMEM_OPCODE_HEADER_LEN);
DEFINE_FLEX(struct max77759_maxq_response, rsp, rsp, length,
MAX77759_MAXQ_OPCODE_MAXLENGTH);
int ret;
cmd->cmd[0] = MAX77759_MAXQ_OPCODE_USER_SPACE_READ;
cmd->cmd[1] = offset;
cmd->cmd[2] = bytes;
rsp->length = bytes + MAX77759_NVMEM_OPCODE_HEADER_LEN;
ret = max77759_maxq_command(nvmem->max77759, cmd, rsp);
if (ret < 0)
return ret;
if (memcmp(cmd->cmd, rsp->rsp, MAX77759_NVMEM_OPCODE_HEADER_LEN)) {
dev_warn(nvmem->dev, "protocol error (read)\n");
return -EIO;
}
memcpy(val, &rsp->rsp[MAX77759_NVMEM_OPCODE_HEADER_LEN], bytes);
return 0;
}
static int max77759_nvmem_reg_write(void *priv, unsigned int offset,
void *val, size_t bytes)
{
struct max77759_nvmem *nvmem = priv;
DEFINE_FLEX(struct max77759_maxq_command, cmd, cmd, length,
MAX77759_MAXQ_OPCODE_MAXLENGTH);
DEFINE_FLEX(struct max77759_maxq_response, rsp, rsp, length,
MAX77759_MAXQ_OPCODE_MAXLENGTH);
int ret;
cmd->cmd[0] = MAX77759_MAXQ_OPCODE_USER_SPACE_WRITE;
cmd->cmd[1] = offset;
cmd->cmd[2] = bytes;
memcpy(&cmd->cmd[MAX77759_NVMEM_OPCODE_HEADER_LEN], val, bytes);
cmd->length = bytes + MAX77759_NVMEM_OPCODE_HEADER_LEN;
rsp->length = cmd->length;
ret = max77759_maxq_command(nvmem->max77759, cmd, rsp);
if (ret < 0)
return ret;
if (memcmp(cmd->cmd, rsp->rsp, cmd->length)) {
dev_warn(nvmem->dev, "protocol error (write)\n");
return -EIO;
}
return 0;
}
static int max77759_nvmem_probe(struct platform_device *pdev)
{
struct nvmem_config config = {
.dev = &pdev->dev,
.name = dev_name(&pdev->dev),
.id = NVMEM_DEVID_NONE,
.type = NVMEM_TYPE_EEPROM,
.ignore_wp = true,
.size = MAX77759_NVMEM_SIZE,
.word_size = sizeof(u8),
.stride = sizeof(u8),
.reg_read = max77759_nvmem_reg_read,
.reg_write = max77759_nvmem_reg_write,
};
struct max77759_nvmem *nvmem;
nvmem = devm_kzalloc(&pdev->dev, sizeof(*nvmem), GFP_KERNEL);
if (!nvmem)
return -ENOMEM;
nvmem->dev = &pdev->dev;
nvmem->max77759 = dev_get_drvdata(pdev->dev.parent);
config.priv = nvmem;
return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config));
}
static const struct of_device_id max77759_nvmem_of_id[] = {
{ .compatible = "maxim,max77759-nvmem", },
{ }
};
MODULE_DEVICE_TABLE(of, max77759_nvmem_of_id);
static const struct platform_device_id max77759_nvmem_platform_id[] = {
{ "max77759-nvmem", },
{ }
};
MODULE_DEVICE_TABLE(platform, max77759_nvmem_platform_id);
static struct platform_driver max77759_nvmem_driver = {
.driver = {
.name = "max77759-nvmem",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = max77759_nvmem_of_id,
},
.probe = max77759_nvmem_probe,
.id_table = max77759_nvmem_platform_id,
};
module_platform_driver(max77759_nvmem_driver);
MODULE_AUTHOR("André Draszik <andre.draszik@linaro.org>");
MODULE_DESCRIPTION("NVMEM driver for Maxim MAX77759");
MODULE_LICENSE("GPL");
+165
View File
@@ -0,0 +1,165 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2020 Google Inc.
* Copyright 2025 Linaro Ltd.
*
* Maxim MAX77759 core driver
*/
#ifndef __LINUX_MFD_MAX77759_H
#define __LINUX_MFD_MAX77759_H
#include <linux/completion.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#define MAX77759_PMIC_REG_PMIC_ID 0x00
#define MAX77759_PMIC_REG_PMIC_REVISION 0x01
#define MAX77759_PMIC_REG_OTP_REVISION 0x02
#define MAX77759_PMIC_REG_INTSRC 0x22
#define MAX77759_PMIC_REG_INTSRCMASK 0x23
#define MAX77759_PMIC_REG_INTSRC_MAXQ BIT(3)
#define MAX77759_PMIC_REG_INTSRC_TOPSYS BIT(1)
#define MAX77759_PMIC_REG_INTSRC_CHGR BIT(0)
#define MAX77759_PMIC_REG_TOPSYS_INT 0x24
#define MAX77759_PMIC_REG_TOPSYS_INT_MASK 0x26
#define MAX77759_PMIC_REG_TOPSYS_INT_TSHDN BIT(6)
#define MAX77759_PMIC_REG_TOPSYS_INT_SYSOVLO BIT(5)
#define MAX77759_PMIC_REG_TOPSYS_INT_SYSUVLO BIT(4)
#define MAX77759_PMIC_REG_TOPSYS_INT_FSHIP BIT(0)
#define MAX77759_PMIC_REG_I2C_CNFG 0x40
#define MAX77759_PMIC_REG_SWRESET 0x50
#define MAX77759_PMIC_REG_CONTROL_FG 0x51
#define MAX77759_MAXQ_REG_UIC_INT1 0x64
#define MAX77759_MAXQ_REG_UIC_INT1_APCMDRESI BIT(7)
#define MAX77759_MAXQ_REG_UIC_INT1_SYSMSGI BIT(6)
#define MAX77759_MAXQ_REG_UIC_INT1_GPIO6I BIT(1)
#define MAX77759_MAXQ_REG_UIC_INT1_GPIO5I BIT(0)
#define MAX77759_MAXQ_REG_UIC_INT1_GPIOxI(offs, en) (((en) & 1) << (offs))
#define MAX77759_MAXQ_REG_UIC_INT1_GPIOxI_MASK(offs) \
MAX77759_MAXQ_REG_UIC_INT1_GPIOxI(offs, ~0)
#define MAX77759_MAXQ_REG_UIC_INT2 0x65
#define MAX77759_MAXQ_REG_UIC_INT3 0x66
#define MAX77759_MAXQ_REG_UIC_INT4 0x67
#define MAX77759_MAXQ_REG_UIC_UIC_STATUS1 0x68
#define MAX77759_MAXQ_REG_UIC_UIC_STATUS2 0x69
#define MAX77759_MAXQ_REG_UIC_UIC_STATUS3 0x6a
#define MAX77759_MAXQ_REG_UIC_UIC_STATUS4 0x6b
#define MAX77759_MAXQ_REG_UIC_UIC_STATUS5 0x6c
#define MAX77759_MAXQ_REG_UIC_UIC_STATUS6 0x6d
#define MAX77759_MAXQ_REG_UIC_UIC_STATUS7 0x6f
#define MAX77759_MAXQ_REG_UIC_UIC_STATUS8 0x6f
#define MAX77759_MAXQ_REG_UIC_INT1_M 0x70
#define MAX77759_MAXQ_REG_UIC_INT2_M 0x71
#define MAX77759_MAXQ_REG_UIC_INT3_M 0x72
#define MAX77759_MAXQ_REG_UIC_INT4_M 0x73
#define MAX77759_MAXQ_REG_AP_DATAOUT0 0x81
#define MAX77759_MAXQ_REG_AP_DATAOUT32 0xa1
#define MAX77759_MAXQ_REG_AP_DATAIN0 0xb1
#define MAX77759_MAXQ_REG_UIC_SWRST 0xe0
#define MAX77759_CHGR_REG_CHG_INT 0xb0
#define MAX77759_CHGR_REG_CHG_INT2 0xb1
#define MAX77759_CHGR_REG_CHG_INT_MASK 0xb2
#define MAX77759_CHGR_REG_CHG_INT2_MASK 0xb3
#define MAX77759_CHGR_REG_CHG_INT_OK 0xb4
#define MAX77759_CHGR_REG_CHG_DETAILS_00 0xb5
#define MAX77759_CHGR_REG_CHG_DETAILS_01 0xb6
#define MAX77759_CHGR_REG_CHG_DETAILS_02 0xb7
#define MAX77759_CHGR_REG_CHG_DETAILS_03 0xb8
#define MAX77759_CHGR_REG_CHG_CNFG_00 0xb9
#define MAX77759_CHGR_REG_CHG_CNFG_01 0xba
#define MAX77759_CHGR_REG_CHG_CNFG_02 0xbb
#define MAX77759_CHGR_REG_CHG_CNFG_03 0xbc
#define MAX77759_CHGR_REG_CHG_CNFG_04 0xbd
#define MAX77759_CHGR_REG_CHG_CNFG_05 0xbe
#define MAX77759_CHGR_REG_CHG_CNFG_06 0xbf
#define MAX77759_CHGR_REG_CHG_CNFG_07 0xc0
#define MAX77759_CHGR_REG_CHG_CNFG_08 0xc1
#define MAX77759_CHGR_REG_CHG_CNFG_09 0xc2
#define MAX77759_CHGR_REG_CHG_CNFG_10 0xc3
#define MAX77759_CHGR_REG_CHG_CNFG_11 0xc4
#define MAX77759_CHGR_REG_CHG_CNFG_12 0xc5
#define MAX77759_CHGR_REG_CHG_CNFG_13 0xc6
#define MAX77759_CHGR_REG_CHG_CNFG_14 0xc7
#define MAX77759_CHGR_REG_CHG_CNFG_15 0xc8
#define MAX77759_CHGR_REG_CHG_CNFG_16 0xc9
#define MAX77759_CHGR_REG_CHG_CNFG_17 0xca
#define MAX77759_CHGR_REG_CHG_CNFG_18 0xcb
#define MAX77759_CHGR_REG_CHG_CNFG_19 0xcc
/* MaxQ opcodes for max77759_maxq_command() */
#define MAX77759_MAXQ_OPCODE_MAXLENGTH (MAX77759_MAXQ_REG_AP_DATAOUT32 - \
MAX77759_MAXQ_REG_AP_DATAOUT0 + \
1)
#define MAX77759_MAXQ_OPCODE_GPIO_TRIGGER_READ 0x21
#define MAX77759_MAXQ_OPCODE_GPIO_TRIGGER_WRITE 0x22
#define MAX77759_MAXQ_OPCODE_GPIO_CONTROL_READ 0x23
#define MAX77759_MAXQ_OPCODE_GPIO_CONTROL_WRITE 0x24
#define MAX77759_MAXQ_OPCODE_USER_SPACE_READ 0x81
#define MAX77759_MAXQ_OPCODE_USER_SPACE_WRITE 0x82
/**
* struct max77759 - core max77759 internal data structure
*
* @regmap_top: Regmap for accessing TOP registers
* @maxq_lock: Lock for serializing access to MaxQ
* @regmap_maxq: Regmap for accessing MaxQ registers
* @cmd_done: Used to signal completion of a MaxQ command
* @regmap_charger: Regmap for accessing charger registers
*
* The MAX77759 comprises several sub-blocks, namely TOP, MaxQ, Charger,
* Fuel Gauge, and TCPCI.
*/
struct max77759 {
struct regmap *regmap_top;
/* This protects MaxQ commands - only one can be active */
struct mutex maxq_lock;
struct regmap *regmap_maxq;
struct completion cmd_done;
struct regmap *regmap_charger;
};
/**
* struct max77759_maxq_command - structure containing the MaxQ command to
* send
*
* @length: The number of bytes to send.
* @cmd: The data to send.
*/
struct max77759_maxq_command {
u8 length;
u8 cmd[] __counted_by(length);
};
/**
* struct max77759_maxq_response - structure containing the MaxQ response
*
* @length: The number of bytes to receive.
* @rsp: The data received. Must have at least @length bytes space.
*/
struct max77759_maxq_response {
u8 length;
u8 rsp[] __counted_by(length);
};
/**
* max77759_maxq_command() - issue a MaxQ command and wait for the response
* and associated data
*
* @max77759: The core max77759 device handle.
* @cmd: The command to be sent.
* @rsp: Any response data associated with the command will be copied here;
* can be %NULL if the command has no response (other than ACK).
*
* Return: 0 on success, a negative error number otherwise.
*/
int max77759_maxq_command(struct max77759 *max77759,
const struct max77759_maxq_command *cmd,
struct max77759_maxq_response *rsp);
#endif /* __LINUX_MFD_MAX77759_H */