mfd: add max77851 pmic MFD driver

Adding MAX77851 MFD driver provided by Maxim.
 - fix android warning/error for uninitialized variable return

Bug 200749982

Change-Id: I6ef82a6c06fe7bbd4df2c71991ec6c5c15e28474
Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-5.10/+/2591158
Signed-off-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2938653
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Shubhi Garg
2021-09-08 14:18:34 +05:30
committed by mobile promotions
parent cdc64f43fa
commit 1ab8a495fc
5 changed files with 2789 additions and 1 deletions

View File

@@ -0,0 +1,258 @@
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
%YAML 1.2
---
$id: http://devicetree.org/schemas/mfd/max77851.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
maintainers:
- Joan Na<Joan.na@maximintegrated.com>
- Shubhi Garg <shgarg@nvidia.com>
description: |
MAX77851 Power management IC from Maxim Semiconductor.
properties:
compatible:
const: "maxim,max77851-pmic"
reg:
maxItems: 1
description:
I2C device address.
interrupts:
maxItems: 1
description:
The interrupt on the parent the controller is connected to.
interrupt-controller:
description:
Marks the device node as an interrupt controller.
"#interrupt-cells":
const: 2
description:
is <2> and their usage is compliant to the 2 cells
variant of <../interrupt-controller/interrupts.txt>
IRQ numbers for different interrupt source of MAX77851
are defined at dt-bindings/mfd/max77620.h.
required:
- compatible
- reg
additionalProperties:
- interrupts
- interrupt-controller
- #interrupt-cells
Optional subnodes and their properties:
Flexible power sequence configurations:
The Flexible Power Sequencer (FPS) allows each regulator to power up under
hardware or software control.
- maxim,power-down-slot-period-us: Inter Master Power-Down Slot Period
- maxim,power-up-slot-period-us: Inter Master Power-Up Slot Period
- maxim,sleep-entry-slot-period-us: Inter Master Sleep Entry Slot Period
- maxim,sleep-exit-slot-period-us: Inter Master Sleep Exit Slot Period
- maxim,power-down-time-period-us: Master 0/1/2/3 Power-Down Slot Period
- maxim,power-up-time-period-us: Master 0/1/2/3 Power-Up Slot Period
- maxim,sleep-entry-time-period-us: Master 0/1/2/3 Sleep Entry Slot Period
- maxim,sleep-exit-time-period-us: Master 0/1/2/3 Sleep Exit Slot Period
Valid values for slot period are:
FPS_PERIOD_32KHZ_30US
FPS_PERIOD_32KHZ_61US
FPS_PERIOD_32KHZ_122US
FPS_PERIOD_32KHZ_244US
FPS_PERIOD_32KHZ_488US
FPS_PERIOD_32KHZ_762US
FPS_PERIOD_32KHZ_1007US
FPS_PERIOD_32KHZ_1251US
FPS_PERIOD_32KHZ_1495US
FPS_PERIOD_32KHZ_1739US
FPS_PERIOD_32KHZ_2014US
FPS_PERIOD_32KHZ_2990US
FPS_PERIOD_32KHZ_3997US
FPS_PERIOD_32KHZ_5004US
FPS_PERIOD_32KHZ_6011US
FPS_PERIOD_32KHZ_7995US
FPS_PERIOD_4KHZ_025US
FPS_PERIOD_4KHZ_050US
FPS_PERIOD_4KHZ_1US
FPS_PERIOD_4KHZ_2US
FPS_PERIOD_4KHZ_4US
FPS_PERIOD_4KHZ_8US
FPS_PERIOD_4KHZ_16US
FPS_PERIOD_4KHZ_25US
FPS_PERIOD_4KHZ_50US
FPS_PERIOD_4KHZ_100US
FPS_PERIOD_4KHZ_250US
FPS_PERIOD_4KHZ_500US
FPS_PERIOD_4KHZ_1000US
FPS_PERIOD_4KHZ_2000US
FPS_PERIOD_4KHZ_3000US
- maxim,fps-enable: FPS Enable
Valid values for FPS enable are:
MAX77851_FPS_DISABLE
MAX77851_FPS_ENABLE
- maxim,abort-enable: FPS Abort Enable
Valid values for FPS enable are:
MAX77851_FPS_ABORT_DISABLE
MAX77851_FPS_ABORT_ENABLE
- maxim,sleep-enable: FPS Sleep Enable
Valid values for FPS sleep enable are:
MAX77851_FPS_SLEEP_DISABLE
MAX77851_FPS_SLEEP_ENABLE
MAX77851_FPS_SLEEP_LPM
MAX77851_FPS_SLEEP_ULPM
- maxim,abort-mode: FPS Abort Mode
Valid values for FPS sleep abort mode are:
MAX77851_FPS_ABORT_NEXT_SLOT
MAX77851_FPS_ABORT_NEXT_MASTER_SLOT
- maxim,pd-max-slot: Master 0/1/2/3 Power-Down Max Used Slots
- maxim,pu-max-slot: Master 0/1/2/3 Power-Up Max Used Slots
- maxim,slpy-max-slot: Master 0/1/2/3 Sleep Entry Max Used Slots
- maxim,slpx-max-slot: Master 0/1/2/3 Sleep Exit Max Used Slots
Valid values for FPS Max Used Slots are:
MAX77851_FPS_SLOT_0
MAX77851_FPS_SLOT_1
MAX77851_FPS_SLOT_2
MAX77851_FPS_SLOT_3
MAX77851_FPS_SLOT_4
MAX77851_FPS_SLOT_5
MAX77851_FPS_SLOT_6
MAX77851_FPS_SLOT_7
MAX77851_FPS_SLOT_8
MAX77851_FPS_SLOT_9
MAX77851_FPS_SLOT_A
MAX77851_FPS_SLOT_B
MAX77851_FPS_SLOT_C
MAX77851_FPS_SLOT_D
MAX77851_FPS_SLOT_E
MAX77851_FPS_SLOT_F
- maxim,sleep-on-suspend: Enter SLEEP state when system is suspended.
Bool property. Add this property if required to
enter SLEEP state during system suspend.
examples:
- |
#include <dt-bindings/mfd/max77620.h>
max77851: max77851@3c {
compatible = "maxim,max77851-pmic";
reg = <0x3c>;
interrupt-parent = <&gpio>;
interrupt-names = "max77851_irq";
interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
#thermal-sensor-cells = <0>;
system-power-controller;
#interrupt-cells = <2>;
interrupt-controller;
#gpio-cells = <2>;
gpio-controller;
fps {
maxim,power-down-slot-period-us = <FPS_PERIOD_4KHZ_050US>;
maxim,power-up-slot-period-us = <FPS_PERIOD_32KHZ_122US>;
maxim,sleep-entry-slot-period-us = <FPS_PERIOD_4KHZ_050US>;
maxim,sleep-exit-slot-period-us = <FPS_PERIOD_32KHZ_122US>;
fps0 {
maxim,pd-fps-master-slot = <MAX77851_FPS_MX_MASTER_SLOT_0>;
maxim,pu-fps-master-slot = <MAX77851_FPS_MX_MASTER_SLOT_0>;
maxim,power-down-time-period-us = <FPS_PERIOD_4KHZ_100US>;
maxim,power-up-time-period-us = <FPS_PERIOD_32KHZ_244US>;
maxim,fps-enable = <MAX77851_FPS_ENABLE>;
maxim,abort-enable = <MAX77851_FPS_ABORT_ENABLE>;
maxim,sleep-enable = <MAX77851_FPS_SLEEP_DISABLE>;
maxim,abort-mode = <MAX77851_FPS_ABORT_NEXT_MASTER_SLOT>;
maxim,pd-max-slot = <MAX77851_FPS_12_SLOTS>;
maxim,pu-max-slot = <MAX77851_FPS_10_SLOTS>;
};
fps1 {
maxim,pd-fps-master-slot = <MAX77851_FPS_MX_MASTER_SLOT_0>;
maxim,pu-fps-master-slot = <MAX77851_FPS_MX_MASTER_SLOT_0>;
maxim,slpy-fps-master-slot = <MAX77851_FPS_MX_MASTER_SLOT_0>;
maxim,slpx-fps-master-slot = <MAX77851_FPS_MX_MASTER_SLOT_0>;
maxim,power-down-time-period-us = <FPS_PERIOD_4KHZ_100US>;
maxim,power-up-time-period-us = <FPS_PERIOD_32KHZ_244US>;
maxim,sleep-entry-time-period-us = <FPS_PERIOD_4KHZ_100US>;
maxim,sleep-exit-time-period-us = <FPS_PERIOD_32KHZ_244US>;
maxim,fps-enable = <MAX77851_FPS_ENABLE>;
maxim,abort-enable = <MAX77851_FPS_ABORT_ENABLE>;
maxim,sleep-enable = <MAX77851_FPS_SLEEP_ENABLE>;
maxim,abort-mode = <MAX77851_FPS_ABORT_NEXT_MASTER_SLOT>;
maxim,pd-max-slot = <MAX77851_FPS_12_SLOTS>;
maxim,pu-max-slot = <MAX77851_FPS_10_SLOTS>;
maxim,slpy-max-slot = <MAX77851_FPS_08_SLOTS>;
maxim,slpx-max-slot = <MAX77851_FPS_08_SLOTS>;
#maxim,fps-event-source = <MAX77851_FPS_EVENT_SRC_EN0>;
};
fps2 {
maxim,pd-fps-master-slot = <MAX77851_FPS_MX_MASTER_SLOT_0>;
maxim,pu-fps-master-slot = <MAX77851_FPS_MX_MASTER_SLOT_0>;
maxim,power-down-time-period-us = <FPS_PERIOD_4KHZ_100US>;
maxim,power-up-time-period-us = <FPS_PERIOD_32KHZ_244US>;
maxim,fps-enable = <MAX77851_FPS_ENABLE>;
maxim,abort-enable = <MAX77851_FPS_ABORT_ENABLE>;
maxim,sleep-enable = <MAX77851_FPS_SLEEP_LPM>;
maxim,abort-mode = <MAX77851_FPS_ABORT_NEXT_MASTER_SLOT>;
maxim,pd-max-slot = <MAX77851_FPS_12_SLOTS>;
maxim,pu-max-slot = <MAX77851_FPS_10_SLOTS>;
};
fps3 {
maxim,pd-fps-master-slot = <MAX77851_FPS_MX_MASTER_SLOT_0>;
maxim,pu-fps-master-slot = <MAX77851_FPS_MX_MASTER_SLOT_0>;
maxim,power-down-time-period-us = <FPS_PERIOD_4KHZ_100US>;
maxim,power-up-time-period-us = <FPS_PERIOD_32KHZ_244US>;
maxim,fps-enable = <MAX77851_FPS_ENABLE>;
maxim,abort-enable = <MAX77851_FPS_ABORT_ENABLE>;
maxim,sleep-enable = <MAX77851_FPS_SLEEP_ENABLE>;
maxim,abort-mode = <MAX77851_FPS_ABORT_NEXT_MASTER_SLOT>;
maxim,pd-max-slot = <MAX77851_FPS_12_SLOTS>;
maxim,pu-max-slot = <MAX77851_FPS_10_SLOTS>;
#maxim,fps-event-source = <MAX77851_FPS_EVENT_SRC_EN0>;
};
};
};

View File

@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. # SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
obj-m += nvidia-vrs-pseq.o obj-m += nvidia-vrs-pseq.o
obj-m += max77851.o

663
drivers/mfd/max77851.c Normal file
View File

@@ -0,0 +1,663 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Maxim MAX77851 MFD Driver
*/
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/mfd/max77851.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/version.h>
#define IS_MX_MASTER23(fps) ((fps == MX_FPS_MASTER2) || (fps == MX_FPS_MASTER3))
#define IS_MX_MASTER01(fps) ((fps == MX_FPS_MASTER0) || (fps == MX_FPS_MASTER1))
#define MAX77851_FPS_CNFG_LENGTH 5
struct max77851_chip *max77851_chip;
static const struct resource gpio_resources[] = {
DEFINE_RES_IRQ(MAX77851_IRQ_TOP_GPIO),
};
static const struct resource power_resources[] = {
DEFINE_RES_IRQ(MAX77851_IRQ_TOP_LB),
};
static const struct resource rtc_resources[] = {
DEFINE_RES_IRQ(MAX77851_IRQ_TOP_RTC),
};
static const struct resource thermal_resources[] = {
DEFINE_RES_IRQ(MAX77851_IRQ_TOP_TJ_SHDN),
DEFINE_RES_IRQ(MAX77851_IRQ_TOP_TJ_ALM1),
DEFINE_RES_IRQ(MAX77851_IRQ_TOP_TJ_ALM2),
};
static const struct regmap_irq max77851_top_irqs[] = {
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_BUCK, 0, TOP_INT0_BUCK_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_EN, 0, TOP_INT0_EN_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_FPS, 0, TOP_INT0_FPS_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_GPIO, 0, TOP_INT0_GPIO_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_IO, 0, TOP_INT0_IO_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_LDO, 0, TOP_INT0_LDO_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_RLOGIC, 0, TOP_INT0_RLOGIC_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_RTC, 0, TOP_INT0_RTC_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_UVLO, 1, TOP_INT1_UVLO_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_LB, 1, TOP_INT1_LB_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_LDO, 1, TOP_INT1_LB_ALM_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_OVLO, 1, TOP_INT1_OVLO_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_TJ_SHDN, 1, TOP_INT1_TJ_SHDN_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_TJ_ALM1, 1, TOP_INT1_TJ_ALM1_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_TJ_ALM2, 1, TOP_INT1_TJ_ALM2_I),
REGMAP_IRQ_REG(MAX77851_IRQ_TOP_TJ_SMPL, 1, TOP_INT1_SMPL_I)
};
static const struct mfd_cell max77851_children[] = {
{ .name = "max77851-pinctrl", },
{ .name = "max77851-clock", },
{ .name = "max77851-regulator", },
{ .name = "max77851-watchdog", },
{
.name = "max77851-gpio",
.resources = gpio_resources,
.num_resources = ARRAY_SIZE(gpio_resources),
}, {
.name = "max77851-rtc",
.resources = rtc_resources,
.num_resources = ARRAY_SIZE(rtc_resources),
}, {
.name = "max77851-power",
.resources = power_resources,
.num_resources = ARRAY_SIZE(power_resources),
}, {
.name = "max77851-thermal",
.resources = thermal_resources,
.num_resources = ARRAY_SIZE(thermal_resources),
},
};
static const struct regmap_range max77851_readable_ranges[] = {
regmap_reg_range(TOP_ID_REG, BUCK4_CFG7_REG),
};
static const struct regmap_access_table max77851_readable_table = {
.yes_ranges = max77851_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(max77851_readable_ranges),
};
static const struct regmap_range max77851_writable_ranges[] = {
regmap_reg_range(TOP_ID_REG, BUCK4_CFG7_REG),
};
static const struct regmap_access_table max77851_writable_table = {
.yes_ranges = max77851_writable_ranges,
.n_yes_ranges = ARRAY_SIZE(max77851_writable_ranges),
};
static const struct regmap_config max77851_regmap_config = {
.name = "max77851-pmic",
.reg_bits = 8,
.val_bits = 8,
.max_register = BUCK4_CFG7_REG + 1,
.rd_table = &max77851_readable_table,
.wr_table = &max77851_writable_table,
};
static struct regmap_irq_chip max77851_top_irq_chip = {
.name = "max77851-top",
.irqs = max77851_top_irqs,
.num_irqs = ARRAY_SIZE(max77851_top_irqs),
.num_regs = 2,
.status_base = TOP_INT0_REG,
.mask_base = TOP_MSK0_REG,
};
/*
* 0 : Mater 0 + Mater 1
* 1 : Mater 2 + Mater 3
*/
static int max77851_master_register_rw_set(struct regmap *rmap, u8 select)
{
int ret;
unsigned int val;
if (IS_MX_MASTER01(select))
val = BIT_IS_ZERO;
else
val = FPS_CFG_MX_RW;
ret = regmap_update_bits(rmap, FPS_CFG_REG, FPS_CFG_MX_RW, val);
return ret;
}
static u8 max77851_get_fps_register_addr(unsigned int fps)
{
u8 ret;
switch (fps) {
case MX_FPS_MASTER0:
ret = FPS_M02_CFG0_REG;
break;
case MX_FPS_MASTER1:
ret = FPS_M13_CFG0_REG;
break;
case MX_FPS_MASTER2:
ret = FPS_M02_CFG0_REG;
break;
case MX_FPS_MASTER3:
ret = FPS_M13_CFG0_REG;
break;
default:
ret = FPS_M02_CFG0_REG;
}
return ret;
}
static int max77851_config_master_fps(struct max77851_chip *chip)
{
struct device *dev = chip->dev;
struct device_node *np;
u32 pval;
u32 cnfg0, cnfg1;
int ret = 0;
np = of_get_child_by_name(dev->of_node, "fps");
if (!np) {
dev_err(dev, "FPS master node is not valid: %d\n", ret);
return ret;
}
ret = of_property_read_u32(np, "maxim,power-down-slot-period-us", &pval);
chip->fps_master_pd_slot_period = (!ret) ? pval : FPS_PERIOD_4KHZ_050US;
ret = of_property_read_u32(np, "maxim,power-up-slot-period-us", &pval);
chip->fps_master_pu_slot_period = (!ret) ? pval : FPS_PERIOD_32KHZ_122US;
cnfg0 = BITS_REAL_VALUE(chip->fps_master_pd_slot_period, MAX77851_FPS_PD_SLOT_MASK) |
BITS_REAL_VALUE(chip->fps_master_pu_slot_period, MAX77851_FPS_PU_SLOT_MASK);
ret = regmap_write(chip->rmap, FPS_IM_CFG0_REG, (u8)cnfg0);
if (ret < 0) {
dev_err(dev, "Reg 0x%02x write failed, %d\n", FPS_IM_CFG0_REG, ret);
return ret;
}
ret = of_property_read_u32(np, "maxim,sleep-exit-slot-period-us", &pval);
chip->fps_master_slpx_slot_period = (!ret) ? pval : FPS_PERIOD_4KHZ_050US;
ret = of_property_read_u32(np, "maxim,sleep-entry-slot-period-us", &pval);
chip->fps_master_slpy_slot_period = (!ret) ? pval : FPS_PERIOD_32KHZ_122US;
cnfg1 = BITS_REAL_VALUE(chip->fps_master_slpy_slot_period, MAX77851_FPS_SLPY_SLOT_MASK) |
BITS_REAL_VALUE(chip->fps_master_slpx_slot_period, MAX77851_FPS_SLPX_SLOT_MASK);
ret = regmap_write(chip->rmap, FPS_IM_CFG1_REG, (u8)cnfg1);
if (ret < 0) {
dev_err(dev, "Reg 0x%02x write failed, %d\n", FPS_IM_CFG1_REG, ret);
return ret;
}
return 0;
}
static int max77851_config_fps(struct max77851_chip *chip,
struct device_node *fps_np)
{
struct device *dev = chip->dev;
//unsigned int mask = 0, config = 0;
u32 fps_max_period;
u32 pval;
unsigned int rval;
int fps_id;
int ret;
char fps_name[10];
u8 reg_addr;
fps_max_period = MAX77851_FPS_PERIOD_MAX_US;
for (fps_id = 0; fps_id < MX_FPS_MASTER_NUM; fps_id++) {
sprintf(fps_name, "fps%d", fps_id);
if (!strcmp(fps_np->name, fps_name))
break;
}
if (fps_id == MX_FPS_MASTER_NUM) {
dev_err(dev, "FPS node name fps[%s] is not valid\n", fps_np->name);
return -EINVAL;
}
max77851_master_register_rw_set(chip->rmap, fps_id);
reg_addr = max77851_get_fps_register_addr(fps_id);
ret = of_property_read_u32(fps_np, "maxim,fps-enable", &pval);
chip->fps_master_data[fps_id].enable = (!ret) ? pval : MAX77851_FPS_DEFAULT;
if (chip->fps_master_data[fps_id].enable == MAX77851_FPS_DEFAULT) {
dev_info(dev, "fps master[%d]: using default setting\n", fps_id);
return 0;
}
ret = of_property_read_u32(fps_np, "maxim,pd-fps-master-slot", &pval);
chip->fps_master_data[fps_id].pd_slot = (!ret) ? pval : FPS_MX_MASTER_SLOT_0;
ret = of_property_read_u32(fps_np, "maxim,pu-fps-master-slot", &pval);
chip->fps_master_data[fps_id].pu_slot = (!ret) ? pval : FPS_MX_MASTER_SLOT_0;
ret = of_property_read_u32(fps_np, "maxim,slpy-fps-master-slot", &pval);
chip->fps_master_data[fps_id].slpy_slot = (!ret) ? pval : FPS_MX_MASTER_SLOT_0;
ret = of_property_read_u32(fps_np, "maxim,slpx-fps-master-slot", &pval);
chip->fps_master_data[fps_id].slpx_slot = (!ret) ? pval : FPS_MX_MASTER_SLOT_0;
ret = of_property_read_u32(fps_np, "maxim,power-down-time-period-us", &pval);
chip->fps_master_data[fps_id].pd_period = (!ret) ? pval : FPS_PERIOD_4KHZ_100US;
ret = of_property_read_u32(fps_np, "maxim,power-up-time-period-us", &pval);
chip->fps_master_data[fps_id].pu_period = (!ret) ? pval : FPS_PERIOD_32KHZ_244US;
ret = of_property_read_u32(fps_np, "maxim,sleep-entry-time-period-us", &pval);
chip->fps_master_data[fps_id].slpy_period = (!ret) ? pval : FPS_PERIOD_32KHZ_244US;
ret = of_property_read_u32(fps_np, "maxim,sleep-exit-time-period-us", &pval);
chip->fps_master_data[fps_id].slpx_period = (!ret) ? pval : FPS_PERIOD_4KHZ_100US;
ret = of_property_read_u32(fps_np, "maxim,abort-enable", &pval);
chip->fps_master_data[fps_id].abort_enable = (!ret) ? pval : MAX77851_FPS_ABORT_DISABLE;
ret = of_property_read_u32(fps_np, "maxim,sleep-enable", &pval);
chip->fps_master_data[fps_id].sleep_mode = (!ret) ? pval : MAX77851_FPS_SLEEP_DISABLE;
ret = of_property_read_u32(fps_np, "maxim,abort-mode", &pval);
chip->fps_master_data[fps_id].abort_mode = (!ret) ? pval : MAX77851_FPS_ABORT_NEXT_SLOT;
ret = of_property_read_u32(fps_np, "maxim,pd-max-slot", &pval);
chip->fps_master_data[fps_id].pd_max_slot = (!ret) ? pval : MAX77851_FPS_16_SLOTS;
ret = of_property_read_u32(fps_np, "maxim,pu-max-slot", &pval);
chip->fps_master_data[fps_id].pu_max_slot = (!ret) ? pval : MAX77851_FPS_16_SLOTS;
ret = of_property_read_u32(fps_np, "maxim,slpy-max-slot", &pval);
chip->fps_master_data[fps_id].slpy_max_slot = (!ret) ? pval : MAX77851_FPS_16_SLOTS;
ret = of_property_read_u32(fps_np, "maxim,slpx-max-slot", &pval);
chip->fps_master_data[fps_id].slpx_max_slot = (!ret) ? pval : MAX77851_FPS_16_SLOTS;
rval = BITS_REAL_VALUE(chip->fps_master_data[fps_id].pd_slot, FPS_CFG0_PD) |
BITS_REAL_VALUE(chip->fps_master_data[fps_id].pu_slot, FPS_CFG0_PU) |
BITS_REAL_VALUE(chip->fps_master_data[fps_id].enable, FPS_CFG0_EN) |
BITS_REAL_VALUE(chip->fps_master_data[fps_id].abort_enable, FPS_CFG0_ABT_EN);
ret = regmap_write(chip->rmap, reg_addr, rval);
if (ret < 0) {
dev_err(dev, "Reg 0x%02x write failed, %d\n", FPS_M02_CFG0_REG, ret);
return ret;
}
rval = BITS_REAL_VALUE(chip->fps_master_data[fps_id].slpy_slot, FPS_CFG1_SLPY) |
BITS_REAL_VALUE(chip->fps_master_data[fps_id].slpx_slot, FPS_CFG1_SLPX) |
BITS_REAL_VALUE(chip->fps_master_data[fps_id].sleep_mode, FPS_CFG1_SLP_EN) |
BITS_REAL_VALUE(chip->fps_master_data[fps_id].abort_mode, FPS_CFG1_ABT);
ret = regmap_write(chip->rmap, (reg_addr + 1), rval);
if (ret < 0) {
dev_err(dev, "Reg 0x%02x write failed, %d\n", FPS_M02_CFG1_REG, ret);
return ret;
}
rval = BITS_REAL_VALUE(chip->fps_master_data[fps_id].pd_period, FPS_CFG2_PD_T) |
BITS_REAL_VALUE(chip->fps_master_data[fps_id].pu_period, FPS_CFG2_PU_T);
ret = regmap_write(chip->rmap, (reg_addr + 2), rval);
if (ret < 0) {
dev_err(dev, "Reg 0x%02x write failed, %d\n", FPS_M02_CFG2_REG, ret);
return ret;
}
rval = BITS_REAL_VALUE(chip->fps_master_data[fps_id].slpy_period, FPS_CFG3_SLPY_T) |
BITS_REAL_VALUE(chip->fps_master_data[fps_id].slpx_period, FPS_CFG3_SLPX_T);
ret = regmap_write(chip->rmap, (reg_addr + 3), rval);
if (ret < 0) {
dev_err(dev, "Reg 0x%02x write failed, %d\n", FPS_M02_CFG3_REG, ret);
return ret;
}
rval = BITS_REAL_VALUE(chip->fps_master_data[fps_id].pd_max_slot, FPS_CFG4_PD_MAX) |
BITS_REAL_VALUE(chip->fps_master_data[fps_id].slpy_max_slot, FPS_CFG4_SLPY_MAX) |
BITS_REAL_VALUE(chip->fps_master_data[fps_id].pu_max_slot, FPS_CFG4_PU_MAX) |
BITS_REAL_VALUE(chip->fps_master_data[fps_id].slpx_max_slot, FPS_CFG4_SLPX_MAX);
ret = regmap_write(chip->rmap, (reg_addr + 4), rval);
if (ret < 0) {
dev_err(dev, "Reg 0x%02x write failed, %d\n", FPS_M02_CFG4_REG, ret);
return ret;
}
return 0;
}
static int max77851_initialise_fps(struct max77851_chip *chip)
{
struct device *dev = chip->dev;
struct device_node *fps_np, *fps_child;
unsigned int val_buf[5];
unsigned int val;
unsigned int *pval;
int fps_num;
int ret;
u8 reg_addr;
ret = regmap_read(chip->rmap, FPS_IM_CFG0_REG, &val);
if (ret < 0) {
dev_err(chip->dev, "Failed to read %d\n", ret);
return ret;
}
chip->fps_master_pd_slot_period = BITS_VALUE(val, FPS_IM_CFG0_PD_T);
chip->fps_master_pu_slot_period = BITS_VALUE(val, FPS_IM_CFG0_PU_T);
ret = regmap_read(chip->rmap, FPS_IM_CFG1_REG, &val);
if (ret < 0) {
dev_err(chip->dev, "Failed to read %d\n", ret);
return ret;
}
chip->fps_master_slpy_slot_period = BITS_VALUE(val, FPS_IM_CFG1_SLPY_T);
chip->fps_master_slpx_slot_period = BITS_VALUE(val, FPS_IM_CFG1_SLPX_T);
/* Master 0/1/2/3 Configiuration */
for (fps_num = 0 ; fps_num < MX_FPS_MASTER_NUM; fps_num++) {
max77851_master_register_rw_set(chip->rmap, fps_num);
reg_addr = max77851_get_fps_register_addr(fps_num);
ret = regmap_raw_read(chip->rmap, reg_addr, val_buf, MAX77851_FPS_CNFG_LENGTH);
if (ret < 0) {
dev_err(chip->dev, "Failed to read %d\n", ret);
return ret;
}
pval = val_buf;
chip->fps_master_data[fps_num].pd_slot = BITS_VALUE(val_buf[0], FPS_CFG0_PD_MASK);
chip->fps_master_data[fps_num].enable = BITS_VALUE(val_buf[0], FPS_CFG0_EN_MASK);
chip->fps_master_data[fps_num].pu_slot = BITS_VALUE(val_buf[0], FPS_CFG0_PU_MASK);
chip->fps_master_data[fps_num].abort_enable = BITS_VALUE(val_buf[0], FPS_CFG0_ABT_EN_MASK);
chip->fps_master_data[fps_num].slpx_slot = BITS_VALUE(val_buf[1], FPS_CFG1_SLPX_MASK);
chip->fps_master_data[fps_num].slpy_slot = BITS_VALUE(val_buf[1], FPS_CFG1_SLPY_MASK);
chip->fps_master_data[fps_num].sleep_mode = BITS_VALUE(val_buf[1], FPS_CFG1_SLP_EN_MASK);
chip->fps_master_data[fps_num].abort_mode = BITS_VALUE(val_buf[1], FPS_CFG1_ABT_MASK);
chip->fps_master_data[fps_num].pd_period = BITS_VALUE(val_buf[2], FPS_CFG2_PD_T_MASK);
chip->fps_master_data[fps_num].pu_period = BITS_VALUE(val_buf[2], FPS_CFG2_PU_T_MASK);
chip->fps_master_data[fps_num].slpx_period = BITS_VALUE(val_buf[3], FPS_CFG3_SLPX_T_MASK);
chip->fps_master_data[fps_num].slpy_period = BITS_VALUE(val_buf[3], FPS_CFG3_SLPY_T_MASK);
chip->fps_master_data[fps_num].pd_max_slot = BITS_VALUE(val_buf[4], FPS_CFG4_PD_MAX_MASK);
chip->fps_master_data[fps_num].pu_max_slot = BITS_VALUE(val_buf[4], FPS_CFG4_PU_MAX_MASK);
chip->fps_master_data[fps_num].slpy_max_slot = BITS_VALUE(val_buf[4], FPS_CFG4_SLPY_MAX_MASK);
chip->fps_master_data[fps_num].slpx_max_slot = BITS_VALUE(val_buf[4], FPS_CFG4_SLPX_MAX_MASK);
}
/* FPS Master */
max77851_config_master_fps(chip);
fps_np = of_get_child_by_name(dev->of_node, "fps");
if (!fps_np)
return 0;
for_each_child_of_node(fps_np, fps_child) {
ret = max77851_config_fps(chip, fps_child);
if (ret < 0)
return ret;
}
return 0;
}
static int max77851_init_low_battery_monitor(struct max77851_chip *chip)
{
struct device *dev = chip->dev;
struct device_node *np;
u32 pval;
u8 mask = 0;
u8 val = 0;
int low_bat_en = 0;
int low_bat_alm_en = 0;
int ret;
np = of_get_child_by_name(dev->of_node, "low-battery-monitor");
if (!np)
return 0;
ret = of_property_read_u32(np,
"maxim,low-battery-enable", &pval);
low_bat_en = (!ret) ? pval : MAX77851_LOW_BAT_ENABLE;
ret = of_property_read_u32(np,
"maxim,low-battery-alarm-enable", &pval);
low_bat_alm_en = (!ret) ? pval : MAX77851_LOW_BAT_ALARM_ENABLE;
val = BITS_REAL_VALUE(low_bat_en, TOP_CFG0_LB_EN) |
BITS_REAL_VALUE(low_bat_alm_en, TOP_CFG0_LB_ALM_EN);
mask = TOP_CFG0_LB_EN | TOP_CFG0_LB_ALM_EN;
ret = regmap_update_bits(chip->rmap, TOP_CFG0_REG, mask, val);
if (ret < 0) {
dev_err(dev, "Reg 0x%02x update failed, %d\n", TOP_CFG0_REG, ret);
return ret;
}
return 0;
}
static int max77851_read_version(struct max77851_chip *chip)
{
unsigned int val;
u8 cid_val[3];
int i;
int ret;
for (i = TOP_ID_REG; i <= TOP_OTP_REV_REG; i++) {
ret = regmap_read(chip->rmap, i, &val);
if (ret < 0) {
dev_err(chip->dev, "Failed to read CID: %d\n", ret);
return ret;
}
cid_val[i] = val;
}
dev_info(chip->dev, "PMIC(0x%X) OTP Revision:0x%X, Device Revision:0x%X\n",
cid_val[0], cid_val[2], cid_val[1]);
return ret;
}
static void max77851_pm_power_off(void)
{
struct max77851_chip *chip = max77851_chip;
regmap_update_bits(chip->rmap, FPS_SW_REG,
FPS_SW_COLD_RST, FPS_SW_COLD_RST);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0)
static int max77851_probe(struct i2c_client *client)
#else
static int max77851_probe(struct i2c_client *client,
const struct i2c_device_id *id)
#endif
{
const struct regmap_config *rmap_config;
struct max77851_chip *chip;
const struct mfd_cell *mfd_cells;
int n_mfd_cells;
bool pm_off;
int ret;
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
i2c_set_clientdata(client, chip);
chip->dev = &client->dev;
chip->irq_base = -1;
chip->chip_irq = client->irq;
mfd_cells = max77851_children;
n_mfd_cells = ARRAY_SIZE(max77851_children);
rmap_config = &max77851_regmap_config;
chip->rmap = devm_regmap_init_i2c(client, rmap_config);
if (IS_ERR(chip->rmap)) {
ret = PTR_ERR(chip->rmap);
dev_err(chip->dev, "Failed to initialise regmap: %d\n", ret);
return ret;
}
ret = max77851_read_version(chip);
if (ret < 0)
return ret;
max77851_top_irq_chip.irq_drv_data = chip;
ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq,
IRQF_ONESHOT | IRQF_SHARED,
chip->irq_base, &max77851_top_irq_chip,
&chip->top_irq_data);
if (ret < 0) {
dev_err(chip->dev, "Failed to add regmap irq: %d\n", ret);
return ret;
}
ret = max77851_initialise_fps(chip);
if (ret < 0)
return ret;
ret = max77851_init_low_battery_monitor(chip);
if (ret < 0)
return ret;
ret = devm_mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE,
mfd_cells, n_mfd_cells, NULL, 0,
regmap_irq_get_domain(chip->top_irq_data));
if (ret < 0) {
dev_err(chip->dev, "Failed to add MFD children: %d\n", ret);
return ret;
}
pm_off = of_device_is_system_power_controller(client->dev.of_node);
//if (pm_off && !pm_power_off) {
if (pm_off) {
max77851_chip = chip;
pm_power_off = max77851_pm_power_off;
}
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int max77851_i2c_suspend(struct device *dev)
{
struct max77851_chip *chip = dev_get_drvdata(dev);
struct i2c_client *client = to_i2c_client(dev);
int ret;
/* FPS on -> sleep */
ret = regmap_write(chip->rmap, FPS_SW_REG, FPS_SW_SLP);
if (ret < 0) {
dev_err(dev, "Reg 0x%02x write failed, %d\n", FPS_SW_REG, ret);
return ret;
}
disable_irq(client->irq);
return 0;
}
static int max77851_i2c_resume(struct device *dev)
{
struct max77851_chip *chip = dev_get_drvdata(dev);
struct i2c_client *client = to_i2c_client(dev);
int ret;
/* FPS sleep -> on */
ret = regmap_write(chip->rmap, FPS_SW_REG, FPS_SW_ON);
if (ret < 0) {
dev_err(dev, "Reg 0x%02x write failed, %d\n", FPS_SW_REG, ret);
return ret;
}
enable_irq(client->irq);
return 0;
}
#endif
static const struct i2c_device_id max77851_id[] = {
{"maxim,max77851-pmic", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, max77851_id);
#ifdef CONFIG_OF
static const struct of_device_id max77851_of_match[] = {
{.compatible = "maxim,max77851-pmic",},
{},
};
MODULE_DEVICE_TABLE(of, max77851_of_match);
#endif
static const struct dev_pm_ops max77851_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(max77851_i2c_suspend, max77851_i2c_resume)
};
static struct i2c_driver max77851_driver = {
.driver = {
.name = "maxim,max77851-pmic",
.of_match_table = of_match_ptr(max77851_of_match),
.pm = &max77851_pm_ops,
},
.probe = max77851_probe,
.id_table = max77851_id,
};
#if 0
static int __init max77851_init(void)
{
return i2c_add_driver(&max77851_driver);
}
module_init(max77851_init);
static void __exit max77851_exit(void)
{
i2c_del_driver(&max77851_driver);
}
module_exit(max77851_exit);
#endif
module_i2c_driver(max77851_driver);
MODULE_DESCRIPTION("MAX77851 Multi Function Device Core Driver");
MODULE_AUTHOR("Shubhi Garg<shgarg@nvidia.com>");
MODULE_AUTHOR("Joan Na<Joan.na@maximintegrated.com>");
MODULE_ALIAS("i2c:max77851");
MODULE_LICENSE("GPL v2");

View File

@@ -0,0 +1,147 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
/*
* This header provides macros for MAXIM MAX77851 device bindings.
*/
#ifndef _DT_BINDINGS_MFD_MAX77851_H
#define _DT_BINDINGS_MFD_MAX77851_H
/* MAX77851 interrupts */
#define MAX77851_IRQ_TOP_GLBL 0 /* Low-Battery */
#define MAX77851_IRQ_TOP_SD 1 /* SD power fail */
#define MAX77851_IRQ_TOP_LDO 2 /* LDO power fail */
#define MAX77851_IRQ_TOP_GPIO 3 /* GPIO internal int to MAX77851 */
#define MAX77851_IRQ_TOP_RTC 4 /* RTC */
#define MAX77851_IRQ_TOP_32K 5 /* 32kHz oscillator */
#define MAX77851_IRQ_TOP_ONOFF 6 /* ON/OFF oscillator */
#define MAX77851_IRQ_LBT_MBATLOW 7 /* Thermal alarm status, > 120C */
#define MAX77851_IRQ_LBT_TJALRM1 8 /* Thermal alarm status, > 120C */
#define MAX77851_IRQ_LBT_TJALRM2 9 /* Thermal alarm status, > 140C */
/* FPS event source */
#define MAX77851_FPS_EVENT_SRC_EN0 0
#define MAX77851_FPS_EVENT_SRC_EN1 1
#define MAX77851_FPS_EVENT_SRC_SW 2
/* Device state when FPS event LOW */
#define MAX77851_FPS_INACTIVE_STATE_SLEEP 0
#define MAX77851_FPS_INACTIVE_STATE_LOW_POWER 1
/* FPS source */
#define MAX77851_FPS_SRC_0 0
#define MAX77851_FPS_SRC_1 1
#define MAX77851_FPS_SRC_2 2
#define MAX77851_FPS_SRC_NONE 3
#define MAX77851_FPS_SRC_DEF 4
/* FPS Period */
#define FPS_PERIOD_32KHZ_30US 0x00
#define FPS_PERIOD_32KHZ_61US 0x01
#define FPS_PERIOD_32KHZ_122US 0x02
#define FPS_PERIOD_32KHZ_244US 0x03
#define FPS_PERIOD_32KHZ_488US 0x04
#define FPS_PERIOD_32KHZ_762US 0x05
#define FPS_PERIOD_32KHZ_1007US 0x06
#define FPS_PERIOD_32KHZ_1251US 0x07
#define FPS_PERIOD_32KHZ_1495US 0x08
#define FPS_PERIOD_32KHZ_1739US 0x09
#define FPS_PERIOD_32KHZ_2014US 0x0A
#define FPS_PERIOD_32KHZ_2990US 0x0B
#define FPS_PERIOD_32KHZ_3997US 0x0C
#define FPS_PERIOD_32KHZ_5004US 0x0D
#define FPS_PERIOD_32KHZ_6011US 0x0E
#define FPS_PERIOD_32KHZ_7995US 0x0F
#define FPS_PERIOD_4KHZ_025US 0x00
#define FPS_PERIOD_4KHZ_050US 0x01
#define FPS_PERIOD_4KHZ_1US 0x02
#define FPS_PERIOD_4KHZ_2US 0x03
#define FPS_PERIOD_4KHZ_4US 0x04
#define FPS_PERIOD_4KHZ_8US 0x05
#define FPS_PERIOD_4KHZ_16US 0x06
#define FPS_PERIOD_4KHZ_25US 0x07
#define FPS_PERIOD_4KHZ_50US 0x08
#define FPS_PERIOD_4KHZ_100US 0x09
#define FPS_PERIOD_4KHZ_250US 0x0A
#define FPS_PERIOD_4KHZ_500US 0x0B
#define FPS_PERIOD_4KHZ_1000US 0x0C
#define FPS_PERIOD_4KHZ_2000US 0x0D
#define FPS_PERIOD_4KHZ_3000US 0x0E
#define FPS_PERIOD_4KHZ_4000US 0x0F
/* INPUT DEBOUNCE FILTER */
#define MAX77851_NO_RESYNC_NO_DEB 0x00
#define MAX77851_RESYNC_NO_DEB 0x01
#define MAX77851_RESYNC_100US_DEB 0x02
#define MAX77851_RESYNC_1MS_DEB 0x03
#define MAX77851_RESYNC_4MS_DEB 0x04
#define MAX77851_RESYNC_8MS_DEB 0x05
#define MAX77851_RESYNC_16MS_DEB 0x06
#define MAX77851_RESYNC_32MS_DEB 0x07
#define MAX77851_FPS_DISABLE 0x00
#define MAX77851_FPS_ENABLE 0x01
#define MAX77851_FPS_DEFAULT 0x02
#define MAX77851_FPS_ABORT_DISABLE 0x00
#define MAX77851_FPS_ABORT_ENABLE 0x01
#define MAX77851_FPS_SLEEP_DISABLE 0x00
#define MAX77851_FPS_SLEEP_ENABLE 0x01
#define MAX77851_FPS_SLEEP_LPM 0x02
#define MAX77851_FPS_SLEEP_ULPM 0x03
#define MAX77851_FPS_ABORT_NEXT_SLOT 0x00
#define MAX77851_FPS_ABORT_NEXT_MASTER_SLOT 0x01
#define MAX77851_FPS_16_SLOTS 0x00
#define MAX77851_FPS_12_SLOTS 0x01
#define MAX77851_FPS_10_SLOTS 0x02
#define MAX77851_FPS_08_SLOTS 0x03
#define MAX77851_FPS_MASTER_SLOT_0 0x1
#define MAX77851_FPS_MASTER_SLOT_1 0x2
#define MAX77851_FPS_MASTER_SLOT_2 0x4
#define MAX77851_FPS_MASTER_SLOT_3 0x8
#define MAX77851_FPS_MX_MASTER_SLOT_0 0x0
#define MAX77851_FPS_MX_MASTER_SLOT_1 0x1
#define MAX77851_FPS_MX_MASTER_SLOT_2 0x2
#define MAX77851_FPS_MX_MASTER_SLOT_3 0x3
#define MAX77851_FPS_SLOT_0 0x0
#define MAX77851_FPS_SLOT_1 0x1
#define MAX77851_FPS_SLOT_2 0x2
#define MAX77851_FPS_SLOT_3 0x3
#define MAX77851_FPS_SLOT_4 0x4
#define MAX77851_FPS_SLOT_5 0x5
#define MAX77851_FPS_SLOT_6 0x6
#define MAX77851_FPS_SLOT_7 0x7
#define MAX77851_FPS_SLOT_8 0x8
#define MAX77851_FPS_SLOT_9 0x9
#define MAX77851_FPS_SLOT_A 0xA
#define MAX77851_FPS_SLOT_B 0xB
#define MAX77851_FPS_SLOT_C 0xC
#define MAX77851_FPS_SLOT_D 0xD
#define MAX77851_FPS_SLOT_E 0xE
#define MAX77851_FPS_SLOT_F 0xF
#define MAX77851_LOW_BAT_ENABLE 0x01
#define MAX77851_LOW_BAT_DISABLE 0x00
#define MAX77851_LOW_BAT_ALARM_ENABLE 0x01
#define MAX77851_LOW_BAT_ALARM_AUTO_MODE 0x00
#define MAX77851_PIN_ACTIVE_HIGH 0x00
#define MAX77851_PIN_ACTIVE_LOW 0x01
#define MAX77851_INPUT_VDD 0x00
#define MAX77851_INPUT_VIO 0x01
#define MAX77851_INPUT_BAT 0x01
#define MAX77851_VOUT_RNG_LOW 0x0
#define MAX77851_VOUT_RNG_MID 0x1
#define MAX77851_VOUT_RNG_HIGH 0x2
#endif

1719
include/linux/mfd/max77851.h Normal file
View File

File diff suppressed because it is too large Load Diff