diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/qcom/clock-sm8650.c | 1 | ||||
-rw-r--r-- | drivers/core/ofnode.c | 12 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 2 | ||||
-rw-r--r-- | drivers/gpio/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpio/qcom_pmic_gpio.c | 20 | ||||
-rw-r--r-- | drivers/gpio/qcom_spmi_gpio.c | 1035 | ||||
-rw-r--r-- | drivers/misc/cros_ec_sandbox.c | 4 | ||||
-rw-r--r-- | drivers/pci/pci-uclass.c | 28 | ||||
-rw-r--r-- | drivers/pinctrl/pinctrl-uclass.c | 3 | ||||
-rw-r--r-- | drivers/scsi/scsi.c | 47 | ||||
-rw-r--r-- | drivers/watchdog/qcom-wdt.c | 5 |
11 files changed, 1092 insertions, 67 deletions
diff --git a/drivers/clk/qcom/clock-sm8650.c b/drivers/clk/qcom/clock-sm8650.c index 364454644a6..7c49e99c005 100644 --- a/drivers/clk/qcom/clock-sm8650.c +++ b/drivers/clk/qcom/clock-sm8650.c @@ -193,6 +193,7 @@ static const struct gate_clk sm8650_clks[] = { GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0x39060, BIT(0)), GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0x39064, BIT(0)), GATE_CLK(GCC_USB3_PRIM_PHY_PIPE_CLK, 0x39068, BIT(0)), + GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0x39088, BIT(0)), }; static int sm8650_enable(struct clk *clk) diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 26e014d5c53..e040e3f2806 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -1961,6 +1961,12 @@ int ofnode_read_bootscript_flash(u64 *bootscr_flash_offset, ofnode uboot; *bootscr_flash_offset = 0; + + if (!bootscr_flash_size) { + dm_warn("bootscr-flash-size is zero. Ignoring properties!\n"); + return -EINVAL; + } + *bootscr_flash_size = 0; uboot = ofnode_path("/options/u-boot"); @@ -1979,12 +1985,6 @@ int ofnode_read_bootscript_flash(u64 *bootscr_flash_offset, if (ret) return -EINVAL; - if (!bootscr_flash_size) { - dm_warn("bootscr-flash-size is zero. Ignoring properties!\n"); - *bootscr_flash_offset = 0; - return -EINVAL; - } - return 0; } diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index fd227d46f5a..c7da1f8a52a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -88,7 +88,7 @@ config DM_GPIO_LOOKUP_LABEL for the same functionality in board code. config SPL_DM_GPIO_LOOKUP_LABEL - bool "Enable searching for gpio labelnames" + bool "Enable searching for gpio labelnames in SPL" depends on SPL_DM_GPIO help This option enables searching for gpio names in diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index e8422b94f53..a5ef1c9e0d8 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -64,7 +64,7 @@ obj-$(CONFIG_OCTEON_GPIO) += octeon_gpio.o obj-$(CONFIG_MVEBU_GPIO) += mvebu_gpio.o obj-$(CONFIG_MSM_GPIO) += msm_gpio.o obj-$(CONFIG_$(PHASE_)PCF8575_GPIO) += pcf8575_gpio.o -obj-$(CONFIG_$(PHASE_)QCOM_PMIC_GPIO) += qcom_pmic_gpio.o +obj-$(CONFIG_$(PHASE_)QCOM_PMIC_GPIO) += qcom_pmic_gpio.o qcom_spmi_gpio.o obj-$(CONFIG_MT7620_GPIO) += mt7620_gpio.o obj-$(CONFIG_MT7621_GPIO) += mt7621_gpio.o obj-$(CONFIG_MSCC_SGPIO) += mscc_sgpio.o diff --git a/drivers/gpio/qcom_pmic_gpio.c b/drivers/gpio/qcom_pmic_gpio.c index cd9f3926ac4..4458c55cd3d 100644 --- a/drivers/gpio/qcom_pmic_gpio.c +++ b/drivers/gpio/qcom_pmic_gpio.c @@ -69,17 +69,6 @@ #define REG_EN_CTL 0x46 #define REG_EN_CTL_ENABLE (1 << 7) -/** - * pmic_gpio_match_data - platform specific configuration - * - * @PMIC_MATCH_READONLY: treat all GPIOs as readonly, don't attempt to configure them. - * This is a workaround for an unknown bug on some platforms where trying to write the - * GPIO configuration registers causes the board to hang. - */ -enum pmic_gpio_quirks { - QCOM_PMIC_QUIRK_READONLY = (1 << 0), -}; - struct qcom_pmic_gpio_data { uint32_t pid; /* Peripheral ID on SPMI bus */ bool lv_mv_type; /* If subtype is GPIO_LV(0x10) or GPIO_MV(0x11) */ @@ -128,13 +117,8 @@ static int qcom_gpio_set_direction(struct udevice *dev, unsigned int offset, { struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); uint32_t gpio_base = plat->pid + REG_OFFSET(offset); - ulong quirks = dev_get_driver_data(dev); int ret = 0; - /* Some PMICs don't like their GPIOs being configured */ - if (quirks & QCOM_PMIC_QUIRK_READONLY) - return 0; - /* Disable the GPIO */ ret = pmic_clrsetbits(dev->parent, gpio_base + REG_EN_CTL, REG_EN_CTL_ENABLE, 0); @@ -278,7 +262,6 @@ static int qcom_gpio_bind(struct udevice *dev) { struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); - ulong quirks = dev_get_driver_data(dev); struct udevice *child; struct driver *drv; int ret; @@ -292,7 +275,7 @@ static int qcom_gpio_bind(struct udevice *dev) /* Bind the GPIO driver as a child of the PMIC. */ ret = device_bind_with_driver_data(dev, drv, dev->name, - quirks, dev_ofnode(dev), &child); + 0, dev_ofnode(dev), &child); if (ret) return log_msg_ret("bind", ret); @@ -365,7 +348,6 @@ static const struct udevice_id qcom_gpio_ids[] = { { .compatible = "qcom,pms405-gpio" }, { .compatible = "qcom,pm6125-gpio" }, { .compatible = "qcom,pm8150-gpio" }, - { .compatible = "qcom,pm8550-gpio", .data = QCOM_PMIC_QUIRK_READONLY }, { } }; diff --git a/drivers/gpio/qcom_spmi_gpio.c b/drivers/gpio/qcom_spmi_gpio.c new file mode 100644 index 00000000000..22c8072534e --- /dev/null +++ b/drivers/gpio/qcom_spmi_gpio.c @@ -0,0 +1,1035 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Qualcomm generic pmic gpio driver + * + * Based on the original qcom_spmi_pmic_gpio driver from: + * Copyright (c) 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com> + * + * Updated from the Linux pinctrl-spmi-gpio driver from: + * Copyright (c) 2012-2014, 2016-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/pinctrl.h> +#include <dm/device_compat.h> +#include <log.h> +#include <power/pmic.h> +#include <spmi/spmi.h> +#include <asm/io.h> +#include <stdlib.h> +#include <asm/gpio.h> +#include <linux/bitops.h> +#include <dt-bindings/pinctrl/qcom,pmic-gpio.h> + +#define PMIC_MAX_GPIOS 36 + +#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 + +/* The index of each function in spmi_pmic_gpio_functions[] array */ +enum spmi_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, +}; + +static const char *const spmi_pmic_gpio_functions[] = { + [PMIC_GPIO_FUNC_INDEX_NORMAL] = PMIC_GPIO_FUNC_NORMAL, + [PMIC_GPIO_FUNC_INDEX_PAIRED] = PMIC_GPIO_FUNC_PAIRED, + [PMIC_GPIO_FUNC_INDEX_FUNC1] = PMIC_GPIO_FUNC_FUNC1, + [PMIC_GPIO_FUNC_INDEX_FUNC2] = PMIC_GPIO_FUNC_FUNC2, + [PMIC_GPIO_FUNC_INDEX_FUNC3] = PMIC_GPIO_FUNC_FUNC3, + [PMIC_GPIO_FUNC_INDEX_FUNC4] = PMIC_GPIO_FUNC_FUNC4, + [PMIC_GPIO_FUNC_INDEX_DTEST1] = PMIC_GPIO_FUNC_DTEST1, + [PMIC_GPIO_FUNC_INDEX_DTEST2] = PMIC_GPIO_FUNC_DTEST2, + [PMIC_GPIO_FUNC_INDEX_DTEST3] = PMIC_GPIO_FUNC_DTEST3, + [PMIC_GPIO_FUNC_INDEX_DTEST4] = PMIC_GPIO_FUNC_DTEST4, +}; + +/** + * struct spmi_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 spmi_pmic_gpio_functions[] + * @atest: the ATEST selection for GPIO analog-pass-through mode + * @dtest_buffer: the DTEST buffer selection for digital input mode. + */ +struct spmi_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 qcom_spmi_pmic_gpio_data { + struct udevice *dev; + u32 pid; /* Peripheral ID on SPMI bus */ + struct udevice *pmic; /* Reference to pmic device for read/write */ + u32 pin_count; + struct spmi_pmic_gpio_pad *pads; +}; + +static int qcom_spmi_pmic_pinctrl_pinconf_set(struct udevice *dev, unsigned int selector, + unsigned int param, unsigned int arg); + +static int spmi_pmic_gpio_read(struct qcom_spmi_pmic_gpio_data *plat, + struct spmi_pmic_gpio_pad *pad, + unsigned int addr) +{ + return pmic_reg_read(plat->pmic, pad->base + addr); +} + +static int spmi_pmic_gpio_write(struct qcom_spmi_pmic_gpio_data *plat, + struct spmi_pmic_gpio_pad *pad, + unsigned int addr, unsigned int val) +{ + return pmic_reg_write(plat->pmic, pad->base + addr, val); +} + +static void spmi_pmic_gpio_get_state(struct qcom_spmi_pmic_gpio_data *plat, + struct spmi_pmic_gpio_pad *pad, + char *buf, int size) +{ + int ret, val, function, cnt; + + static const char *const biases[] = { + "pull-up 30uA", "pull-up 1.5uA", "pull-up 31.5uA", + "pull-up 1.5uA + 30uA boost", "pull-down 10uA", "no pull" + }; + static const char *const buffer_types[] = { + "push-pull", "open-drain", "open-source" + }; + static const char *const strengths[] = { + "no", "low", "medium", "high" + }; + + val = spmi_pmic_gpio_read(plat, pad, PMIC_GPIO_REG_EN_CTL); + + if (val < 0 || !(val >> PMIC_GPIO_REG_MASTER_EN_SHIFT)) { + cnt = snprintf(buf, size, "disabled"); + } else { + if (pad->input_enabled) { + ret = spmi_pmic_gpio_read(plat, pad, PMIC_MPP_REG_RT_STS); + if (ret < 0) + return; + + ret &= PMIC_MPP_REG_RT_STS_VAL_MASK; + pad->out_value = ret; + } + /* + * For the non-LV/MV subtypes only 2 special functions are + * available, offsetting the dtest function values by 2. + */ + function = pad->function; + if (!pad->lv_mv_type && + pad->function >= PMIC_GPIO_FUNC_INDEX_FUNC3) + function += PMIC_GPIO_FUNC_INDEX_DTEST1 - + PMIC_GPIO_FUNC_INDEX_FUNC3; + + if (pad->analog_pass) + cnt = snprintf(buf, size, "analog-pass"); + else + cnt = snprintf(buf, size, "%-4s", + pad->output_enabled ? "out" : "in"); + buf += cnt; + size -= cnt; + + snprintf(buf, size, " %-4s %-7s vin-%d %-27s %-10s %-7s atest-%d dtest-%d", + pad->out_value ? "high" : "low", + spmi_pmic_gpio_functions[function], + pad->power_source, + biases[pad->pullup], + buffer_types[pad->buffer_type], + strengths[pad->strength], + pad->atest, + pad->dtest_buffer); + } +} + +static int qcom_spmi_pmic_gpio_set(struct qcom_spmi_pmic_gpio_data *plat, + struct spmi_pmic_gpio_pad *pad) +{ + unsigned int val; + int ret; + + val = pad->power_source << PMIC_GPIO_REG_VIN_SHIFT; + + ret = spmi_pmic_gpio_write(plat, pad, PMIC_GPIO_REG_DIG_VIN_CTL, val); + if (ret < 0) + return ret; + + val = pad->pullup << PMIC_GPIO_REG_PULL_SHIFT; + + ret = spmi_pmic_gpio_write(plat, pad, PMIC_GPIO_REG_DIG_PULL_CTL, val); + if (ret < 0) + return ret; + + val = pad->buffer_type << PMIC_GPIO_REG_OUT_TYPE_SHIFT; + val |= pad->strength << PMIC_GPIO_REG_OUT_STRENGTH_SHIFT; + + ret = spmi_pmic_gpio_write(plat, pad, PMIC_GPIO_REG_DIG_OUT_CTL, val); + if (ret < 0) + return ret; + + if (pad->dtest_buffer == 0) { + val = 0; + } else { + if (pad->lv_mv_type) { + val = pad->dtest_buffer - 1; + val |= PMIC_GPIO_LV_MV_DIG_IN_DTEST_EN; + } else { + val = BIT(pad->dtest_buffer - 1); + } + } + ret = spmi_pmic_gpio_write(plat, pad, PMIC_GPIO_REG_DIG_IN_CTL, val); + if (ret < 0) + return ret; + + if (pad->analog_pass) + val = PMIC_GPIO_MODE_ANALOG_PASS_THRU; + else if (pad->output_enabled && pad->input_enabled) + val = PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT; + else if (pad->output_enabled) + val = PMIC_GPIO_MODE_DIGITAL_OUTPUT; + else + val = PMIC_GPIO_MODE_DIGITAL_INPUT; + + if (pad->lv_mv_type) { + ret = spmi_pmic_gpio_write(plat, pad, + PMIC_GPIO_REG_MODE_CTL, val); + if (ret < 0) + return ret; + + val = pad->atest - 1; + ret = spmi_pmic_gpio_write(plat, pad, + PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL, + val); + if (ret < 0) + return ret; + + val = pad->out_value + << PMIC_GPIO_LV_MV_OUTPUT_INVERT_SHIFT; + val |= pad->function + & PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK; + ret = spmi_pmic_gpio_write(plat, pad, + PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL, + val); + if (ret < 0) + return ret; + } else { + val = val << PMIC_GPIO_REG_MODE_DIR_SHIFT; + val |= pad->function << PMIC_GPIO_REG_MODE_FUNCTION_SHIFT; + val |= pad->out_value & PMIC_GPIO_REG_MODE_VALUE_SHIFT; + + ret = spmi_pmic_gpio_write(plat, pad, PMIC_GPIO_REG_MODE_CTL, val); + if (ret < 0) + return ret; + } + + val = pad->is_enabled << PMIC_GPIO_REG_MASTER_EN_SHIFT; + + ret = spmi_pmic_gpio_write(plat, pad, PMIC_GPIO_REG_EN_CTL, val); + if (ret) + return ret; + + return 0; +} + +static int spmi_pmic_gpio_populate(struct qcom_spmi_pmic_gpio_data *plat, + struct spmi_pmic_gpio_pad *pad) +{ + int type, subtype, val, dir; + + type = spmi_pmic_gpio_read(plat, pad, PMIC_GPIO_REG_TYPE); + if (type < 0) + return type; + + if (type != PMIC_GPIO_TYPE) { + dev_err(plat->dev, "incorrect block type 0x%x at 0x%x\n", + type, pad->base); + return -ENODEV; + } + + subtype = spmi_pmic_gpio_read(plat, pad, PMIC_GPIO_REG_SUBTYPE); + if (subtype < 0) + return subtype; + + switch (subtype) { + case PMIC_GPIO_SUBTYPE_GPIO_4CH: + pad->have_buffer = true; + fallthrough; + case PMIC_GPIO_SUBTYPE_GPIOC_4CH: + pad->num_sources = 4; + break; + case PMIC_GPIO_SUBTYPE_GPIO_8CH: + pad->have_buffer = true; + fallthrough; + case PMIC_GPIO_SUBTYPE_GPIOC_8CH: + pad->num_sources = 8; + break; + case PMIC_GPIO_SUBTYPE_GPIO_LV: + pad->num_sources = 1; + pad->have_buffer = true; + pad->lv_mv_type = true; + break; + case PMIC_GPIO_SUBTYPE_GPIO_MV: + pad->num_sources = 2; + pad->have_buffer = true; + pad->lv_mv_type = true; + break; + case PMIC_GPIO_SUBTYPE_GPIO_LV_VIN2: + pad->num_sources = 2; + pad->have_buffer = true; + pad->lv_mv_type = true; + break; + case PMIC_GPIO_SUBTYPE_GPIO_MV_VIN3: + pad->num_sources = 3; + pad->have_buffer = true; + pad->lv_mv_type = true; + break; + default: + dev_err(plat->dev, "unknown GPIO type 0x%x\n", subtype); + return -ENODEV; + } + + if (pad->lv_mv_type) { + val = spmi_pmic_gpio_read(plat, pad, + PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL); + if (val < 0) + return val; + + pad->out_value = !!(val & PMIC_GPIO_LV_MV_OUTPUT_INVERT); + pad->function = val & PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK; + + val = spmi_pmic_gpio_read(plat, pad, PMIC_GPIO_REG_MODE_CTL); + if (val < 0) + return val; + + dir = val & PMIC_GPIO_REG_LV_MV_MODE_DIR_MASK; + } else { + val = spmi_pmic_gpio_read(plat, pad, PMIC_GPIO_REG_MODE_CTL); + if (val < 0) + return val; + + pad->out_value = val & PMIC_GPIO_REG_MODE_VALUE_SHIFT; + + dir = val >> PMIC_GPIO_REG_MODE_DIR_SHIFT; + dir &= PMIC_GPIO_REG_MODE_DIR_MASK; + pad->function = val >> PMIC_GPIO_REG_MODE_FUNCTION_SHIFT; + pad->function &= PMIC_GPIO_REG_MODE_FUNCTION_MASK; + } + + switch (dir) { + case PMIC_GPIO_MODE_DIGITAL_INPUT: + pad->input_enabled = true; + pad->output_enabled = false; + break; + case PMIC_GPIO_MODE_DIGITAL_OUTPUT: + pad->input_enabled = false; + pad->output_enabled = true; + break; + case PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT: + pad->input_enabled = true; + pad->output_enabled = true; + break; + case PMIC_GPIO_MODE_ANALOG_PASS_THRU: + if (!pad->lv_mv_type) + return -ENODEV; + pad->analog_pass = true; + break; + default: + dev_err(plat->dev, "unknown GPIO direction\n"); + return -ENODEV; + } + + val = spmi_pmic_gpio_read(plat, pad, PMIC_GPIO_REG_DIG_VIN_CTL); + if (val < 0) + return val; + + pad->power_source = val >> PMIC_GPIO_REG_VIN_SHIFT; + pad->power_source &= PMIC_GPIO_REG_VIN_MASK; + + val = spmi_pmic_gpio_read(plat, pad, PMIC_GPIO_REG_DIG_PULL_CTL); + if (val < 0) + return val; + + pad->pullup = val >> PMIC_GPIO_REG_PULL_SHIFT; + pad->pullup &= PMIC_GPIO_REG_PULL_MASK; + + val = spmi_pmic_gpio_read(plat, pad, PMIC_GPIO_REG_DIG_IN_CTL); + if (val < 0) + return val; + + if (pad->lv_mv_type && (val & PMIC_GPIO_LV_MV_DIG_IN_DTEST_EN)) + pad->dtest_buffer = + (val & PMIC_GPIO_LV_MV_DIG_IN_DTEST_SEL_MASK) + 1; + else if (!pad->lv_mv_type) + pad->dtest_buffer = ffs(val); + else + pad->dtest_buffer = 0; + + val = spmi_pmic_gpio_read(plat, pad, PMIC_GPIO_REG_DIG_OUT_CTL); + if (val < 0) + return val; + + pad->strength = val >> PMIC_GPIO_REG_OUT_STRENGTH_SHIFT; + pad->strength &= PMIC_GPIO_REG_OUT_STRENGTH_MASK; + + pad->buffer_type = val >> PMIC_GPIO_REG_OUT_TYPE_SHIFT; + pad->buffer_type &= PMIC_GPIO_REG_OUT_TYPE_MASK; + + if (pad->lv_mv_type) { + val = spmi_pmic_gpio_read(plat, pad, + PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL); + if (val < 0) + return val; + + pad->atest = (val & PMIC_GPIO_LV_MV_ANA_MUX_SEL_MASK) + 1; + } + + /* Pin could be disabled with PIN_CONFIG_BIAS_HIGH_IMPEDANCE */ + pad->is_enabled = true; + return 0; +} + +static int qcom_spmi_pmic_gpio_set_flags(struct udevice *dev, unsigned int offset, ulong flags) +{ + struct qcom_spmi_pmic_gpio_data *plat = dev_get_plat(dev); + struct spmi_pmic_gpio_pad *pad; + + if (offset >= plat->pin_count) + return -EINVAL; + + pad = &plat->pads[offset]; + + pad->input_enabled = flags & GPIOD_IS_IN; + pad->output_enabled = flags & GPIOD_IS_OUT; + + if (pad->output_enabled) { + pad->out_value = flags & GPIOD_IS_OUT_ACTIVE; + + if ((flags & GPIOD_OPEN_DRAIN) && pad->have_buffer) + pad->buffer_type = PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS; + else if ((flags & GPIOD_OPEN_SOURCE) && pad->have_buffer) + pad->buffer_type = PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS; + else + pad->buffer_type = PMIC_GPIO_OUT_BUF_CMOS; + } + + if (flags & GPIOD_PULL_UP) + pad->pullup = PMIC_GPIO_PULL_UP_30; + else if (flags & GPIOD_PULL_DOWN) + pad->pullup = PMIC_GPIO_PULL_DOWN; + + return qcom_spmi_pmic_gpio_set(plat, pad); +} + +static int qcom_spmi_pmic_gpio_get_flags(struct udevice *dev, unsigned int offset, + ulong *flagsp) +{ + struct qcom_spmi_pmic_gpio_data *plat = dev_get_plat(dev); + struct spmi_pmic_gpio_pad *pad; + ulong flags = 0; + + if (offset >= plat->pin_count) + return -EINVAL; + + pad = &plat->pads[offset]; + + if (pad->input_enabled) + flags |= GPIOD_IS_IN; + + if (pad->output_enabled) { + flags |= GPIOD_IS_OUT; + + if (pad->out_value) + flags |= GPIOD_IS_OUT_ACTIVE; + + switch (pad->buffer_type) { + case PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS: + flags |= GPIOD_OPEN_DRAIN; + break; + case PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS: + flags |= GPIOD_OPEN_SOURCE; + break; + } + } + + if (pad->pullup == PMIC_GPIO_PULL_DOWN) + flags |= GPIOD_PULL_DOWN; + else if (pad->pullup != PMIC_GPIO_PULL_DISABLE) + flags |= GPIOD_PULL_UP; + + if (pad->analog_pass) + flags |= GPIOD_IS_AF; + + *flagsp = flags; + + return 0; +} + +static int qcom_spmi_pmic_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + struct qcom_spmi_pmic_gpio_data *plat = dev_get_plat(dev); + struct spmi_pmic_gpio_pad *pad; + int ret; + + if (offset >= plat->pin_count) + return -EINVAL; + + pad = &plat->pads[offset]; + + if (!pad->is_enabled) + return -EINVAL; + + if (pad->input_enabled) { + ret = spmi_pmic_gpio_read(plat, pad, PMIC_MPP_REG_RT_STS); + if (ret < 0) + return ret; + + pad->out_value = ret & PMIC_MPP_REG_RT_STS_VAL_MASK; + } + + return !!pad->out_value; +} + +static int qcom_spmi_pmic_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + struct qcom_spmi_pmic_gpio_data *plat = dev_get_plat(dev); + struct spmi_pmic_gpio_pad *pad; + int val; + + if (offset >= plat->pin_count) + return GPIOF_UNKNOWN; + + pad = &plat->pads[offset]; + + val = spmi_pmic_gpio_read(plat, pad, PMIC_GPIO_REG_EN_CTL); + if (!(val >> PMIC_GPIO_REG_MASTER_EN_SHIFT)) + return GPIOF_UNKNOWN; + else if (pad->analog_pass) + return GPIOF_FUNC; + else if (pad->output_enabled) + return GPIOF_OUTPUT; + + return GPIOF_INPUT; +} + +static int qcom_spmi_pmic_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, + struct ofnode_phandle_args *args) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + if (args->args_count < 1) + return -EINVAL; + + /* GPIOs in DT are 1-based */ + desc->offset = args->args[0] - 1; + if (desc->offset >= uc_priv->gpio_count) + return -EINVAL; + + if (args->args_count < 2) + return 0; + + desc->flags = gpio_flags_xlate(args->args[1]); + + return 0; +} + +static const struct dm_gpio_ops qcom_spmi_pmic_gpio_ops = { + .set_flags = qcom_spmi_pmic_gpio_set_flags, + .get_flags = qcom_spmi_pmic_gpio_get_flags, + .get_value = qcom_spmi_pmic_gpio_get_value, + .get_function = qcom_spmi_pmic_gpio_get_function, + .xlate = qcom_spmi_pmic_gpio_xlate, +}; + +static int qcom_spmi_pmic_gpio_bind(struct udevice *dev) +{ + struct qcom_spmi_pmic_gpio_data *plat = dev_get_plat(dev); + struct udevice *child; + struct driver *drv; + int ret; + + drv = lists_driver_lookup_name("qcom_spmi_pmic_pinctrl"); + if (!drv) { + log_warning("Cannot find driver '%s'\n", "qcom_spmi_pmic_pinctrl"); + return -ENOENT; + } + + /* Bind the GPIO driver as a child of the PMIC. */ + ret = device_bind_with_driver_data(dev, drv, + dev->name, + 0, dev_ofnode(dev), &child); + if (ret) + return log_msg_ret("bind", ret); + + dev_set_plat(child, plat); + + return 0; +} + +static int qcom_spmi_pmic_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct qcom_spmi_pmic_gpio_data *plat = dev_get_plat(dev); + struct ofnode_phandle_args args; + int i, ret; + u64 pid; + + plat->dev = dev; + plat->pmic = dev->parent; + + pid = dev_read_addr(dev); + if (pid == FDT_ADDR_T_NONE) + return log_msg_ret("bad address", -EINVAL); + + plat->pid = pid; + + /* + * Parse basic GPIO count specified via the gpio-ranges property + * as specified in upstream devicetrees + */ + ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "gpio-ranges", + NULL, 3, 0, &args); + if (ret) + return log_msg_ret("gpio-ranges", ret); + + plat->pin_count = min_t(u32, args.args[2], PMIC_MAX_GPIOS); + + uc_priv->gpio_count = plat->pin_count; + + uc_priv->bank_name = strchr(dev_read_string(dev, "compatible"), ','); + if (uc_priv->bank_name) + uc_priv->bank_name += 1; /* skip the , */ + else + uc_priv->bank_name = dev->name; + + plat->pads = calloc(plat->pin_count, sizeof(struct spmi_pmic_gpio_pad)); + if (!plat->pads) + return -ENOMEM; + + for (i = 0; i < plat->pin_count; ++i) { + struct spmi_pmic_gpio_pad *pad = &plat->pads[i]; + + pad->base = plat->pid + i * PMIC_GPIO_ADDRESS_RANGE; + + ret = spmi_pmic_gpio_populate(plat, pad); + if (ret < 0) + return ret; + } + + return 0; +} + +static const struct udevice_id qcom_spmi_pmic_gpio_ids[] = { + { .compatible = "qcom,pm8550-gpio" }, + { .compatible = "qcom,pm8550b-gpio" }, + { .compatible = "qcom,pm8550ve-gpio" }, + { .compatible = "qcom,pm8550vs-gpio" }, + { .compatible = "qcom,pmk8550-gpio" }, + { .compatible = "qcom,pmr735d-gpio" }, + { } +}; + +U_BOOT_DRIVER(qcom_spmi_pmic_gpio) = { + .name = "qcom_spmi_pmic_gpio", + .id = UCLASS_GPIO, + .of_match = qcom_spmi_pmic_gpio_ids, + .bind = qcom_spmi_pmic_gpio_bind, + .probe = qcom_spmi_pmic_gpio_probe, + .ops = &qcom_spmi_pmic_gpio_ops, + .plat_auto = sizeof(struct qcom_spmi_pmic_gpio_data), + .flags = DM_FLAG_ALLOC_PDATA, +}; + +/* 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) + +static const struct pinconf_param qcom_spmi_pmic_pinctrl_conf_params[] = { + { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 }, + { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 }, + { "drive-open-source", PIN_CONFIG_DRIVE_OPEN_SOURCE, 0 }, + { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, PMIC_GPIO_PULL_UP_30 }, + { "bias-pull-down", PIN_CONFIG_BIAS_PULL_UP, 0 }, + { "bias-high-impedance", PIN_CONFIG_BIAS_HIGH_IMPEDANCE, 0 }, + { "power-source", PIN_CONFIG_POWER_SOURCE, 0 }, + { "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 }, + { "input-enable", PIN_CONFIG_INPUT_ENABLE, 1 }, + { "output-disable", PIN_CONFIG_OUTPUT_ENABLE, 0 }, + { "output-enable", PIN_CONFIG_OUTPUT_ENABLE, 1 }, + { "output-high", PIN_CONFIG_OUTPUT, 1 }, + { "output-low", PIN_CONFIG_OUTPUT, 0 }, + { "qcom,pull-up-strength", PMIC_GPIO_CONF_PULL_UP, 0}, + { "qcom,drive-strength", PMIC_GPIO_CONF_STRENGTH, 0}, + { "qcom,atest", PMIC_GPIO_CONF_ATEST, 0}, + { "qcom,analog-pass", PMIC_GPIO_CONF_ANALOG_PASS, 0}, + { "qcom,dtest-buffer", PMIC_GPIO_CONF_DTEST_BUFFER, 0}, +}; + +static int qcom_spmi_pmic_pinctrl_get_pins_count(struct udevice *dev) +{ + struct qcom_spmi_pmic_gpio_data *plat = dev_get_plat(dev); + + return plat->pin_count; +} + +static const char *qcom_spmi_pmic_pinctrl_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + static char name[8]; + + /* DT indexes from 1 */ + snprintf(name, sizeof(name), "gpio%u", selector + 1); + + return name; +} + +static int qcom_spmi_pmic_pinctrl_get_pin_muxing(struct udevice *dev, + unsigned int selector, + char *buf, int size) +{ + struct qcom_spmi_pmic_gpio_data *plat = dev_get_plat(dev); + struct spmi_pmic_gpio_pad *pad; + + if (selector >= plat->pin_count) + return -EINVAL; + + pad = &plat->pads[selector]; + + spmi_pmic_gpio_get_state(plat, pad, buf, size); + + return 0; +} + +static int qcom_spmi_pmic_pinctrl_pinconf_set(struct udevice *dev, unsigned int selector, + unsigned int param, unsigned int arg) +{ + struct qcom_spmi_pmic_gpio_data *plat = dev_get_plat(dev); + struct spmi_pmic_gpio_pad *pad; + + if (selector >= plat->pin_count) + return -EINVAL; + + pad = &plat->pads[selector]; + pad->is_enabled = true; + + switch (param) { + case PIN_CONFIG_DRIVE_PUSH_PULL: + pad->buffer_type = PMIC_GPIO_OUT_BUF_CMOS; + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (!pad->have_buffer) + return -EINVAL; + pad->buffer_type = PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS; + break; + case PIN_CONFIG_DRIVE_OPEN_SOURCE: + if (!pad->have_buffer) + return -EINVAL; + pad->buffer_type = PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS; + break; + case PIN_CONFIG_BIAS_DISABLE: + pad->pullup = PMIC_GPIO_PULL_DISABLE; + break; + case PIN_CONFIG_BIAS_PULL_UP: + pad->pullup = PMIC_GPIO_PULL_UP_30; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + if (arg) + pad->pullup = PMIC_GPIO_PULL_DOWN; + else + pad->pullup = PMIC_GPIO_PULL_DISABLE; + break; + case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: + pad->is_enabled = false; + break; + case PIN_CONFIG_POWER_SOURCE: + if (arg >= pad->num_sources) + return -EINVAL; + pad->power_source = arg; + break; + case PIN_CONFIG_INPUT_ENABLE: + pad->input_enabled = arg ? true : false; + break; + case PIN_CONFIG_OUTPUT_ENABLE: + pad->output_enabled = arg ? true : false; + break; + case PIN_CONFIG_OUTPUT: + pad->output_enabled = true; + pad->out_value = arg; + break; + case PMIC_GPIO_CONF_PULL_UP: + if (arg > PMIC_GPIO_PULL_UP_1P5_30) + return -EINVAL; + pad->pullup = arg; + break; + case PMIC_GPIO_CONF_STRENGTH: + if (arg > PMIC_GPIO_STRENGTH_LOW) + return -EINVAL; + switch (arg) { + case PMIC_GPIO_STRENGTH_HIGH: + pad->strength = PMIC_GPIO_OUT_STRENGTH_HIGH; + break; + case PMIC_GPIO_STRENGTH_LOW: + pad->strength = PMIC_GPIO_OUT_STRENGTH_LOW; + break; + default: + pad->strength = arg; + break; + } + break; + case PMIC_GPIO_CONF_ATEST: + if (!pad->lv_mv_type || arg > 4) + return -EINVAL; + pad->atest = arg; + break; + case PMIC_GPIO_CONF_ANALOG_PASS: + if (!pad->lv_mv_type) + return -EINVAL; + pad->analog_pass = true; + break; + case PMIC_GPIO_CONF_DTEST_BUFFER: + if (arg > 4) + return -EINVAL; + pad->dtest_buffer = arg; + break; + default: + return -EINVAL; + } + + return qcom_spmi_pmic_gpio_set(plat, pad); +} + +static const char *qcom_spmi_pmic_pinctrl_get_function_name(struct udevice *dev, + unsigned int selector) +{ + if (selector >= ARRAY_SIZE(spmi_pmic_gpio_functions)) + return NULL; + + return spmi_pmic_gpio_functions[selector]; +} + +static int qcom_spmi_pmic_pinctrl_get_functions_count(struct udevice *dev) +{ + return ARRAY_SIZE(spmi_pmic_gpio_functions); +} + +static int qcom_spmi_pmic_pinctrl_pinmux_set_mux(struct udevice *dev, unsigned int selector, + unsigned int function) +{ + struct qcom_spmi_pmic_gpio_data *plat = dev_get_plat(dev); + struct spmi_pmic_gpio_pad *pad; + unsigned int val; + int ret; + + if (selector >= plat->pin_count) + return -EINVAL; + + pad = &plat->pads[selector]; + + /* + * Non-LV/MV subtypes only support 2 special functions, + * offsetting the dtestx function values by 2 + */ + if (!pad->lv_mv_type) { + if (function == PMIC_GPIO_FUNC_INDEX_FUNC3 || + function == PMIC_GPIO_FUNC_INDEX_FUNC4) { + pr_err("LV/MV subtype doesn't have func3/func4\n"); + return -EINVAL; + } + if (function >= PMIC_GPIO_FUNC_INDEX_DTEST1) + function -= (PMIC_GPIO_FUNC_INDEX_DTEST1 - + PMIC_GPIO_FUNC_INDEX_FUNC3); + } + + pad->function = function; + + if (pad->analog_pass) + val = PMIC_GPIO_MODE_ANALOG_PASS_THRU; + else if (pad->output_enabled && pad->input_enabled) + val = PMIC_GPIO_MODE_DIGITAL_INPUT_OUTPUT; + else if (pad->output_enabled) + val = PMIC_GPIO_MODE_DIGITAL_OUTPUT; + else + val = PMIC_GPIO_MODE_DIGITAL_INPUT; + + if (pad->lv_mv_type) { + ret = spmi_pmic_gpio_write(plat, pad, + PMIC_GPIO_REG_MODE_CTL, val); + if (ret < 0) + return ret; + + val = pad->atest - 1; + ret = spmi_pmic_gpio_write(plat, pad, + PMIC_GPIO_REG_LV_MV_ANA_PASS_THRU_SEL, + val); + if (ret < 0) + return ret; + + val = pad->out_value + << PMIC_GPIO_LV_MV_OUTPUT_INVERT_SHIFT; + val |= pad->function + & PMIC_GPIO_LV_MV_OUTPUT_SOURCE_SEL_MASK; + ret = spmi_pmic_gpio_write(plat, pad, + PMIC_GPIO_REG_LV_MV_DIG_OUT_SOURCE_CTL, + val); + if (ret < 0) + return ret; + } else { + val = val << PMIC_GPIO_REG_MODE_DIR_SHIFT; + val |= pad->function << PMIC_GPIO_REG_MODE_FUNCTION_SHIFT; + val |= pad->out_value & PMIC_GPIO_REG_MODE_VALUE_SHIFT; + + ret = spmi_pmic_gpio_write(plat, pad, PMIC_GPIO_REG_MODE_CTL, val); + if (ret < 0) + return ret; + } + + val = pad->is_enabled << PMIC_GPIO_REG_MASTER_EN_SHIFT; + + return spmi_pmic_gpio_write(plat, pad, PMIC_GPIO_REG_EN_CTL, val); +} + +struct pinctrl_ops qcom_spmi_pmic_pinctrl_ops = { + .get_pins_count = qcom_spmi_pmic_pinctrl_get_pins_count, + .get_pin_name = qcom_spmi_pmic_pinctrl_get_pin_name, + .set_state = pinctrl_generic_set_state, + .pinconf_num_params = ARRAY_SIZE(qcom_spmi_pmic_pinctrl_conf_params), + .pinconf_params = qcom_spmi_pmic_pinctrl_conf_params, + .pinconf_set = qcom_spmi_pmic_pinctrl_pinconf_set, + .get_function_name = qcom_spmi_pmic_pinctrl_get_function_name, + .get_functions_count = qcom_spmi_pmic_pinctrl_get_functions_count, + .pinmux_set = qcom_spmi_pmic_pinctrl_pinmux_set_mux, + .get_pin_muxing = qcom_spmi_pmic_pinctrl_get_pin_muxing, +}; + +U_BOOT_DRIVER(qcom_spmi_pmic_pinctrl) = { + .name = "qcom_spmi_pmic_pinctrl", + .id = UCLASS_PINCTRL, + .ops = &qcom_spmi_pmic_pinctrl_ops, +}; diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index 3ac690a3733..432b1fbb0c4 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -540,7 +540,7 @@ static int process_cmd(struct ec_state *ec, const struct ec_params_vstore_write *req = req_data; struct vstore_slot *slot; - if (req->slot >= EC_VSTORE_SLOT_MAX) + if (req->slot >= VSTORE_SLOT_COUNT) return -EINVAL; slot = &ec->slot[req->slot]; slot->locked = true; @@ -553,7 +553,7 @@ static int process_cmd(struct ec_state *ec, struct ec_response_vstore_read *resp = resp_data; struct vstore_slot *slot; - if (req->slot >= EC_VSTORE_SLOT_MAX) + if (req->slot >= VSTORE_SLOT_COUNT) return -EINVAL; slot = &ec->slot[req->slot]; memcpy(resp->data, slot->data, EC_VSTORE_SLOT_SIZE); diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 59894d2430b..c370f8c6400 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -385,8 +385,10 @@ static int pci_read_config(pci_dev_t bdf, int offset, unsigned long *valuep, int ret; ret = pci_get_bus(PCI_BUS(bdf), &bus); - if (ret) + if (ret) { + *valuep = 0xffffffff; return ret; + } return pci_bus_read_config(bus, bdf, offset, valuep, size); } @@ -408,8 +410,10 @@ int pci_read_config32(pci_dev_t bdf, int offset, u32 *valuep) int ret; ret = pci_read_config(bdf, offset, &value, PCI_SIZE_32); - if (ret) + if (ret) { + *valuep = 0xffffffff; return ret; + } *valuep = value; return 0; @@ -421,8 +425,10 @@ int pci_read_config16(pci_dev_t bdf, int offset, u16 *valuep) int ret; ret = pci_read_config(bdf, offset, &value, PCI_SIZE_16); - if (ret) + if (ret) { + *valuep = 0xffff; return ret; + } *valuep = value; return 0; @@ -434,8 +440,10 @@ int pci_read_config8(pci_dev_t bdf, int offset, u8 *valuep) int ret; ret = pci_read_config(bdf, offset, &value, PCI_SIZE_8); - if (ret) + if (ret) { + *valuep = 0xff; return ret; + } *valuep = value; return 0; @@ -447,8 +455,10 @@ int dm_pci_read_config8(const struct udevice *dev, int offset, u8 *valuep) int ret; ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_8); - if (ret) + if (ret) { + *valuep = 0xff; return ret; + } *valuep = value; return 0; @@ -460,8 +470,10 @@ int dm_pci_read_config16(const struct udevice *dev, int offset, u16 *valuep) int ret; ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_16); - if (ret) + if (ret) { + *valuep = 0xffff; return ret; + } *valuep = value; return 0; @@ -473,8 +485,10 @@ int dm_pci_read_config32(const struct udevice *dev, int offset, u32 *valuep) int ret; ret = dm_pci_read_config(dev, offset, &value, PCI_SIZE_32); - if (ret) + if (ret) { + *valuep = 0xffffffff; return ret; + } *valuep = value; return 0; diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index d9c76898a96..58e070bfe1e 100644 --- a/drivers/pinctrl/pinctrl-uclass.c +++ b/drivers/pinctrl/pinctrl-uclass.c @@ -317,8 +317,7 @@ int pinctrl_select_state(struct udevice *dev, const char *statename) if (!dev_has_ofnode(dev)) return 0; /* - * Try full-implemented pinctrl first. - * If it fails or is not implemented, try simple one. + * If full-implemented pinctrl is not implemented, try simple one. */ if (CONFIG_IS_ENABLED(PINCTRL_FULL)) return pinctrl_select_state_full(dev, statename); diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 7d022ce718a..78efed6b66a 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -39,7 +39,7 @@ static void scsi_print_error(struct scsi_cmd *pccb) #ifdef CONFIG_SYS_64BIT_LBA void scsi_setup_read16(struct scsi_cmd *pccb, lbaint_t start, - unsigned long blocks) + lbaint_t blocks) { pccb->cmd[0] = SCSI_READ16; pccb->cmd[1] = 0; @@ -83,7 +83,7 @@ static void scsi_setup_inquiry(struct scsi_cmd *pccb) } static void scsi_setup_sync_cache(struct scsi_cmd *pccb, lbaint_t start, - unsigned short blocks) + lbaint_t blocks) { pccb->cmd[0] = SCSI_SYNC_CACHE; pccb->cmd[1] = 0; @@ -100,7 +100,7 @@ static void scsi_setup_sync_cache(struct scsi_cmd *pccb, lbaint_t start, } static void scsi_setup_read_ext(struct scsi_cmd *pccb, lbaint_t start, - unsigned short blocks) + lbaint_t blocks) { pccb->cmd[0] = SCSI_READ10; pccb->cmd[1] = 0; @@ -121,7 +121,7 @@ static void scsi_setup_read_ext(struct scsi_cmd *pccb, lbaint_t start, } static void scsi_setup_write_ext(struct scsi_cmd *pccb, lbaint_t start, - unsigned short blocks) + lbaint_t blocks) { pccb->cmd[0] = SCSI_WRITE10; pccb->cmd[1] = 0; @@ -143,7 +143,7 @@ static void scsi_setup_write_ext(struct scsi_cmd *pccb, lbaint_t start, } static void scsi_setup_erase_ext(struct scsi_cmd *pccb, lbaint_t start, - unsigned short blocks) + lbaint_t blocks) { u8 *param = tempbuff; const u8 param_size = 24; @@ -193,9 +193,8 @@ static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, struct blk_desc *block_dev = dev_get_uclass_plat(dev); struct udevice *bdev = dev->parent; struct scsi_plat *uc_plat = dev_get_uclass_plat(bdev); - lbaint_t start, blks, max_blks; + lbaint_t start, blks, max_blks, blocks; uintptr_t buf_addr; - unsigned short smallblks = 0; struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb; /* Setup device */ @@ -217,7 +216,6 @@ static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, pccb->dma_dir = DMA_FROM_DEVICE; #ifdef CONFIG_SYS_64BIT_LBA if (start > SCSI_LBA48_READ) { - unsigned long blocks; blocks = min_t(lbaint_t, blks, max_blks); pccb->datalen = block_dev->blksz * blocks; scsi_setup_read16(pccb, start, blocks); @@ -227,20 +225,20 @@ static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, #endif if (blks > max_blks) { pccb->datalen = block_dev->blksz * max_blks; - smallblks = max_blks; - scsi_setup_read_ext(pccb, start, smallblks); + blocks = max_blks; + scsi_setup_read_ext(pccb, start, blocks); start += max_blks; blks -= max_blks; } else { pccb->datalen = block_dev->blksz * blks; - smallblks = (unsigned short)blks; - scsi_setup_read_ext(pccb, start, smallblks); + blocks = blks; + scsi_setup_read_ext(pccb, start, blocks); start += blks; blks = 0; } debug("scsi_read_ext: startblk " LBAF - ", blccnt %x buffer %lX\n", - start, smallblks, buf_addr); + ", blccnt " LBAF " buffer %lX\n", + start, blocks, buf_addr); if (scsi_exec(bdev, pccb)) { scsi_print_error(pccb); blkcnt -= blks; @@ -249,7 +247,7 @@ static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, buf_addr += pccb->datalen; } while (blks != 0); debug("scsi_read_ext: end startblk " LBAF - ", blccnt %x buffer %lX\n", start, smallblks, buf_addr); + ", blccnt " LBAF " buffer %lX\n", start, blocks, buf_addr); return blkcnt; } @@ -263,9 +261,8 @@ static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, struct blk_desc *block_dev = dev_get_uclass_plat(dev); struct udevice *bdev = dev->parent; struct scsi_plat *uc_plat = dev_get_uclass_plat(bdev); - lbaint_t start, blks, max_blks; + lbaint_t start, blks, max_blks, blocks; uintptr_t buf_addr; - unsigned short smallblks; struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb; /* Setup device */ @@ -286,19 +283,19 @@ static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, pccb->dma_dir = DMA_TO_DEVICE; if (blks > max_blks) { pccb->datalen = block_dev->blksz * max_blks; - smallblks = max_blks; - scsi_setup_write_ext(pccb, start, smallblks); + blocks = max_blks; + scsi_setup_write_ext(pccb, start, blocks); start += max_blks; blks -= max_blks; } else { pccb->datalen = block_dev->blksz * blks; - smallblks = (unsigned short)blks; - scsi_setup_write_ext(pccb, start, smallblks); + blocks = blks; + scsi_setup_write_ext(pccb, start, blocks); start += blks; blks = 0; } - debug("%s: startblk " LBAF ", blccnt %x buffer %lx\n", - __func__, start, smallblks, buf_addr); + debug("%s: startblk " LBAF ", blccnt " LBAF " buffer %lx\n", + __func__, start, blocks, buf_addr); if (scsi_exec(bdev, pccb)) { scsi_print_error(pccb); blkcnt -= blks; @@ -312,8 +309,8 @@ static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, if (scsi_exec(bdev, pccb)) scsi_print_error(pccb); - debug("%s: end startblk " LBAF ", blccnt %x buffer %lX\n", - __func__, start, smallblks, buf_addr); + debug("%s: end startblk " LBAF ", blccnt " LBAF " buffer %lX\n", + __func__, start, blocks, buf_addr); return blkcnt; } diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index adbb5aacdc3..4b972cff72c 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c @@ -63,10 +63,7 @@ int qcom_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) writel(bark_timeout_s, wdt_addr(wdt, WDT_BARK_TIME)); writel(bite_timeout_s, wdt_addr(wdt, WDT_BITE_TIME)); writel(BIT(0), wdt_addr(wdt, WDT_EN)); - if (readl(wdt_addr(wdt, WDT_EN)) != 1) { - dev_err(dev, "Failed to enable Qualcomm watchdog!\n"); - return -EIO; - } + return 0; } |