// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2012-2014, 2016-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/spmi.h>
#include <linux/types.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinmux.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
#include "../core.h"
#include "../pinctrl-utils.h"
#define PMIC_GPIO_ADDRESS_RANGE 0x100
/* type and subtype registers base address offsets */
#define PMIC_GPIO_REG_TYPE 0x4
#define PMIC_GPIO_REG_SUBTYPE 0x5
/* GPIO peripheral type and subtype out_values */
#define PMIC_GPIO_TYPE 0x10
#define PMIC_GPIO_SUBTYPE_GPIO_4CH 0x1
#define PMIC_GPIO_SUBTYPE_GPIOC_4CH 0x5
#define PMIC_GPIO_SUBTYPE_GPIO_8CH 0x9
#define PMIC_GPIO_SUBTYPE_GPIOC_8CH 0xd
#define PMIC_GPIO_SUBTYPE_GPIO_LV 0x10
#define PMIC_GPIO_SUBTYPE_GPIO_MV 0x11
#define PMIC_GPIO_SUBTYPE_GPIO_LV_VIN2 0x12
#define PMIC_GPIO_SUBTYPE_GPIO_MV_VIN3 0x13
#define PMIC_MPP_REG_RT_STS 0x10
#define PMIC_MPP_REG_RT_STS_VAL_MASK 0x1
/* control register base address offsets */
#define PMIC_GPIO_REG_MODE_CTL 0x40
#define PMIC_GPIO_REG_DIG_VIN_CTL 0x41
#define PMIC_GPIO_REG_DIG_PULL_CTL 0x42
#define PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL 0x44
#define PMIC_GPIO_REG_DIG_IN_CTL 0x43
#define PMIC_GPIO_REG_DIG_OUT_CTL 0x45
#define PMIC_GPIO_REG_EN_CTL 0x46
#define PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL 0x4A
/* PMIC_GPIO_REG_MODE_CTL */
#define PMIC_GPIO_REG_MODE_VALUE_SHIFT 0x1
#define PMIC_GPIO_REG_MODE_FUNCTION_SHIFT 1
#define PMIC_GPIO_REG_MODE_FUNCTION_MASK 0x7
#define PMIC_GPIO_REG_MODE_DIR_SHIFT 4
#define PMIC_GPIO_REG_MODE_DIR_MASK 0x7
#define PMIC_GPIO_MODE_DIGITAL_INPUT 0
#define PMIC_GPIO_MODE_DIGITAL_OUTPUT 1
#define PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT 2
#define PMIC_GPIO_MODE_ANALOG_PASS_THRU 3
#define PMIC_GPIO_REG_LV_MV_MODE_DIR_MASK 0x3
/* PMIC_GPIO_REG_DIG_VIN_CTL */
#define PMIC_GPIO_REG_VIN_SHIFT 0
#define PMIC_GPIO_REG_VIN_MASK 0x7
/* PMIC_GPIO_REG_DIG_PULL_CTL */
#define PMIC_GPIO_REG_PULL_SHIFT 0
#define PMIC_GPIO_REG_PULL_MASK 0x7
#define PMIC_GPIO_PULL_DOWN 4
#define PMIC_GPIO_PULL_DISABLE 5
/* PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL for LV/MV */
#define PMIC_GPIO_LV_MV_OUTPUT_INVERT 0x80
#define PMIC_GPIO_LV_MV_OUTPUT_INVERT_SHIFT 7
#define PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK 0xF
/* PMIC_GPIO_REG_DIG_IN_CTL */
#define PMIC_GPIO_LV_MV_DIG_IN_DTEST_EN 0x80
#define PMIC_GPIO_LV_MV_DIG_IN_DTEST_SEL_MASK 0x7
#define PMIC_GPIO_DIG_IN_DTEST_SEL_MASK 0xf
/* PMIC_GPIO_REG_DIG_OUT_CTL */
#define PMIC_GPIO_REG_OUT_STRENGTH_SHIFT 0
#define PMIC_GPIO_REG_OUT_STRENGTH_MASK 0x3
#define PMIC_GPIO_REG_OUT_TYPE_SHIFT 4
#define PMIC_GPIO_REG_OUT_TYPE_MASK 0x3
/*
* Output type - indicates pin should be configured as push-pull,
* open drain or open source.
*/
#define PMIC_GPIO_OUT_BUF_CMOS 0
#define PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS 1
#define PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS 2
#define PMIC_GPIO_OUT_STRENGTH_LOW 1
#define PMIC_GPIO_OUT_STRENGTH_HIGH 3
/* PMIC_GPIO_REG_EN_CTL */
#define PMIC_GPIO_REG_MASTER_EN_SHIFT 7
#define PMIC_GPIO_PHYSICAL_OFFSET 1
/* PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL */
#define PMIC_GPIO_LV_MV_ANA_MUX_SEL_MASK 0x3
/* Qualcomm specific pin configurations */
#define PMIC_GPIO_CONF_PULL_UP (PIN_CONFIG_END + 1)
#define PMIC_GPIO_CONF_STRENGTH (PIN_CONFIG_END + 2)
#define PMIC_GPIO_CONF_ATEST (PIN_CONFIG_END + 3)
#define PMIC_GPIO_CONF_ANALOG_PASS (PIN_CONFIG_END + 4)
#define PMIC_GPIO_CONF_DTEST_BUFFER (PIN_CONFIG_END + 5)
/* The index of each function in pmic_gpio_functions[] array */
enum pmic_gpio_func_index {
PMIC_GPIO_FUNC_INDEX_NORMAL,
PMIC_GPIO_FUNC_INDEX_PAIRED,
PMIC_GPIO_FUNC_INDEX_FUNC1,
PMIC_GPIO_FUNC_INDEX_FUNC2,
PMIC_GPIO_FUNC_INDEX_FUNC3,
PMIC_GPIO_FUNC_INDEX_FUNC4,
PMIC_GPIO_FUNC_INDEX_DTEST1,
PMIC_GPIO_FUNC_INDEX_DTEST2,
PMIC_GPIO_FUNC_INDEX_DTEST3,
PMIC_GPIO_FUNC_INDEX_DTEST4,
};
/**
* struct pmic_gpio_pad - keep current GPIO settings
* @base: Address base in SPMI device.
* @is_enabled: Set to false when GPIO should be put in high Z state.
* @out_value: Cached pin output value
* @have_buffer: Set to true if GPIO output could be configured in push-pull,
* open-drain or open-source mode.
* @output_enabled: Set to true if GPIO output logic is enabled.
* @input_enabled: Set to true if GPIO input buffer logic is enabled.
* @analog_pass: Set to true if GPIO is in analog-pass-through mode.
* @lv_mv_type: Set to true if GPIO subtype is GPIO_LV(0x10) or GPIO_MV(0x11).
* @num_sources: Number of power-sources supported by this GPIO.
* @power_source: Current power-source used.
* @buffer_type: Push-pull, open-drain or open-source.
* @pullup: Constant current which flow trough GPIO output buffer.
* @strength: No, Low, Medium, High
* @function: See pmic_gpio_functions[]
* @atest: the ATEST selection for GPIO analog-pass-through mode
* @dtest_buffer: the DTEST buffer selection for digital input mode.
*/
struct pmic_gpio_pad {
u16 base;
bool is_enabled;
bool out_value;
bool have_buffer;
bool output_enabled;
bool input_enabled;
bool analog_pass;
bool lv_mv_type;
unsigned int num_sources;
unsigned int power_source;
unsigned int buffer_type;
unsigned int pullup;
unsigned int strength;
unsigned int function;
unsigned int atest;
unsigned int dtest_buffer;
};
struct pmic_gpio_state {
struct device *dev;
struct regmap *map;
struct pinctrl_dev *ctrl;
struct gpio_chip chip;
u8 usid;
u8 pid_base;
};
static const struct