diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-max77851.yaml b/Documentation/devicetree/bindings/pinctrl/pinctrl-max77851.yaml new file mode 100644 index 00000000..4bf3ef46 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-max77851.yaml @@ -0,0 +1,144 @@ +# 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/pinctrl/pinctrl-max77851.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +maintainers: + - Joan Na + - Shubhi Garg + +description: | + Pincontrol driver for MAX77851 Power management IC from Maxim Semiconductor. + + Device has 8 GPIO pins & 4 FPSO pins which can be configured as GPIO as well as the + special IO functions. + + Please refer file + for details of the common pinctrl bindings used by client devices, + including the meaning of the phrase "pin configuration node". + +properties: +# Optional Pinmux properties: +# -------------------------- +# Following properties are required if default setting of pins are required +# at boot. + + pinctrl-names: + description: + A pinctrl state named per . + +patternProperties: + pinctrl-[0...n]: + description: + Properties to contain the phandle for pinctrl states per + . + +The pin configurations are defined as child of the pinctrl states node. Each +sub-node have following properties: + +required: +- pins: List of pins. Valid values of pins properties are: + gpio0, gpio1, gpio2, gpio3, gpio4, gpio5, gpio6, gpio7, fpso0, fpso1, fpso2, fpso3. + +additionalProperties: +Following are optional properties defined as pinmux DT binding document +. Absence of properties will leave the configuration +on default. + function, + drive-push-pull, + drive-open-drain, + bias-pull-up, + bias-pull-down. + +Valid values for function properties are: + gpio-high-z + gpio-input + gpio-output + gpio-fps-digital-input + gpio-fps-digital-output + src-enable-digital-input + src-boot-dvs-digital-input + src-clock-digital-input + src-fpwm-digital-input + src-pok-gpio-digital-output + clk-32k-out + lb-alarm-output + o-type-reset + test-digital-input + test-digital-output + test-analog-in-out + + fpso-high-z + fpso-digital-output + fpso-fps-digital-output + fpso-buck-sense + + nrstio-high-z + nrstio-digital-input + nrstio-digital-output + nrstio-fps-digital-output + nrstio-lb-digital-output + +Theres is also customised properties for the GPIO1, GPIO2 and GPIO3. These +customised properties are required to configure FPS configuration parameters +of these GPIOs. Please refer for more +detail of Flexible Power Sequence (FPS). + +- maxim,pd-slpy-master-slot: FPS Master Power-Up / Sleep Exit +- maxim,pu-slpx-master-slot: FPS Master Power-Down / Sleep Entry. + Valid values are: + - MAX77851_FPS_MASTER_SLOT_0 + FPS Mater is FPS0. + - MAX77851_FPS_MASTER_SLOT_1 + FPS Mater is FPS1 + - MAX77851_FPS_MASTER_SLOT_2 + FPS Mater is FPS2 + - MAX77851_FPS_MASTER_SLOT_3. + FPS Mater is FPS2 + +- maxim,pu-slot: FPS Power-Up Slot +- maxim,pd-slot: FPS Power-Down Slot +- maxim,slpx-slot: FPS Sleep Exit Slot +- maxim,slpy-slot: FPS Sleep Enter Slot + Valid values are 0 to F. + +examples: + - | + #include + ... + max77851@3c { + + pinctrl-names = "default"; + pinctrl-0 = <&max77851_default>; + + max77851_default: pinmux@0 { + pin_gpio0 { + pins = "gpio0"; + function = "clk-32k-out"; + drive-push-pull = <1>; + + maxim,polarity = ; + maxim,input_debounce_filter = ; + maxim,input_suppy = ; + }; + pin_gpio1 { + pins = "gpio1"; + function = "gpio-fps-digital-output"; + drive-open-drain = <1>; + + maxim,polarity = ; + maxim,input_debounce_filter = ; + maxim,input_suppy = ; + + maxim,pu-slpx-master-slot = ; + maxim,pd-slpy-master-slot = ; + maxim,pu-slot = ; + maxim,pd-slot = ; + maxim,slpx-slot = ; + maxim,slpy-slot = ; + }; + }; + }; + ... diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 8cb3bb24..9d80c7d1 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -1,5 +1,6 @@ # 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 += pinctrl-tegra194-pexclk-padctrl.o obj-m += pinctrl-tegra234-dpaux.o +obj-m += pinctrl-max77851.o diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h new file mode 100644 index 00000000..483fd806 --- /dev/null +++ b/drivers/pinctrl/core.h @@ -0,0 +1,244 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Core private header for the pin control subsystem + * + * Copyright (C) 2011 ST-Ericsson SA + * Written on behalf of Linaro for ST-Ericsson + * + * Author: Linus Walleij + */ + +#include +#include +#include +#include +#include + +struct pinctrl_gpio_range; + +/** + * struct pinctrl_dev - pin control class device + * @node: node to include this pin controller in the global pin controller list + * @desc: the pin controller descriptor supplied when initializing this pin + * controller + * @pin_desc_tree: each pin descriptor for this pin controller is stored in + * this radix tree + * @pin_group_tree: optionally each pin group can be stored in this radix tree + * @num_groups: optionally number of groups can be kept here + * @pin_function_tree: optionally each function can be stored in this radix tree + * @num_functions: optionally number of functions can be kept here + * @gpio_ranges: a list of GPIO ranges that is handled by this pin controller, + * ranges are added to this list at runtime + * @dev: the device entry for this pin controller + * @owner: module providing the pin controller, used for refcounting + * @driver_data: driver data for drivers registering to the pin controller + * subsystem + * @p: result of pinctrl_get() for this device + * @hog_default: default state for pins hogged by this device + * @hog_sleep: sleep state for pins hogged by this device + * @mutex: mutex taken on each pin controller specific action + * @device_root: debugfs root for this device + */ +struct pinctrl_dev { + struct list_head node; + struct pinctrl_desc *desc; + struct radix_tree_root pin_desc_tree; +#ifdef CONFIG_GENERIC_PINCTRL_GROUPS + struct radix_tree_root pin_group_tree; + unsigned int num_groups; +#endif +#ifdef CONFIG_GENERIC_PINMUX_FUNCTIONS + struct radix_tree_root pin_function_tree; + unsigned int num_functions; +#endif + struct list_head gpio_ranges; + struct device *dev; + struct module *owner; + void *driver_data; + struct pinctrl *p; + struct pinctrl_state *hog_default; + struct pinctrl_state *hog_sleep; + struct mutex mutex; +#ifdef CONFIG_DEBUG_FS + struct dentry *device_root; +#endif +}; + +/** + * struct pinctrl - per-device pin control state holder + * @node: global list node + * @dev: the device using this pin control handle + * @states: a list of states for this device + * @state: the current state + * @dt_maps: the mapping table chunks dynamically parsed from device tree for + * this device, if any + * @users: reference count + */ +struct pinctrl { + struct list_head node; + struct device *dev; + struct list_head states; + struct pinctrl_state *state; + struct list_head dt_maps; + struct kref users; +}; + +/** + * struct pinctrl_state - a pinctrl state for a device + * @node: list node for struct pinctrl's @states field + * @name: the name of this state + * @settings: a list of settings for this state + */ +struct pinctrl_state { + struct list_head node; + const char *name; + struct list_head settings; +}; + +/** + * struct pinctrl_setting_mux - setting data for MAP_TYPE_MUX_GROUP + * @group: the group selector to program + * @func: the function selector to program + */ +struct pinctrl_setting_mux { + unsigned group; + unsigned func; +}; + +/** + * struct pinctrl_setting_configs - setting data for MAP_TYPE_CONFIGS_* + * @group_or_pin: the group selector or pin ID to program + * @configs: a pointer to an array of config parameters/values to program into + * hardware. Each individual pin controller defines the format and meaning + * of config parameters. + * @num_configs: the number of entries in array @configs + */ +struct pinctrl_setting_configs { + unsigned group_or_pin; + unsigned long *configs; + unsigned num_configs; +}; + +/** + * struct pinctrl_setting - an individual mux or config setting + * @node: list node for struct pinctrl_settings's @settings field + * @type: the type of setting + * @pctldev: pin control device handling to be programmed. Not used for + * PIN_MAP_TYPE_DUMMY_STATE. + * @dev_name: the name of the device using this state + * @data: Data specific to the setting type + */ +struct pinctrl_setting { + struct list_head node; + enum pinctrl_map_type type; + struct pinctrl_dev *pctldev; + const char *dev_name; + union { + struct pinctrl_setting_mux mux; + struct pinctrl_setting_configs configs; + } data; +}; + +/** + * struct pin_desc - pin descriptor for each physical pin in the arch + * @pctldev: corresponding pin control device + * @name: a name for the pin, e.g. the name of the pin/pad/finger on a + * datasheet or such + * @dynamic_name: if the name of this pin was dynamically allocated + * @drv_data: driver-defined per-pin data. pinctrl core does not touch this + * @mux_usecount: If zero, the pin is not claimed, and @owner should be NULL. + * If non-zero, this pin is claimed by @owner. This field is an integer + * rather than a boolean, since pinctrl_get() might process multiple + * mapping table entries that refer to, and hence claim, the same group + * or pin, and each of these will increment the @usecount. + * @mux_owner: The name of device that called pinctrl_get(). + * @mux_setting: The most recent selected mux setting for this pin, if any. + * @gpio_owner: If pinctrl_gpio_request() was called for this pin, this is + * the name of the GPIO that "owns" this pin. + */ +struct pin_desc { + struct pinctrl_dev *pctldev; + const char *name; + bool dynamic_name; + void *drv_data; + /* These fields only added when supporting pinmux drivers */ +#ifdef CONFIG_PINMUX + unsigned mux_usecount; + const char *mux_owner; + const struct pinctrl_setting_mux *mux_setting; + const char *gpio_owner; +#endif +}; + +/** + * struct pinctrl_maps - a list item containing part of the mapping table + * @node: mapping table list node + * @maps: array of mapping table entries + * @num_maps: the number of entries in @maps + */ +struct pinctrl_maps { + struct list_head node; + const struct pinctrl_map *maps; + unsigned num_maps; +}; + +#ifdef CONFIG_GENERIC_PINCTRL_GROUPS + +/** + * struct group_desc - generic pin group descriptor + * @name: name of the pin group + * @pins: array of pins that belong to the group + * @num_pins: number of pins in the group + * @data: pin controller driver specific data + */ +struct group_desc { + const char *name; + int *pins; + int num_pins; + void *data; +}; + +int pinctrl_generic_get_group_count(struct pinctrl_dev *pctldev); + +const char *pinctrl_generic_get_group_name(struct pinctrl_dev *pctldev, + unsigned int group_selector); + +int pinctrl_generic_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int group_selector, + const unsigned int **pins, + unsigned int *npins); + +struct group_desc *pinctrl_generic_get_group(struct pinctrl_dev *pctldev, + unsigned int group_selector); + +int pinctrl_generic_add_group(struct pinctrl_dev *pctldev, const char *name, + int *gpins, int ngpins, void *data); + +int pinctrl_generic_remove_group(struct pinctrl_dev *pctldev, + unsigned int group_selector); + +#endif /* CONFIG_GENERIC_PINCTRL_GROUPS */ + +struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name); +struct pinctrl_dev *get_pinctrl_dev_from_of_node(struct device_node *np); +int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name); +const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin); +int pinctrl_get_group_selector(struct pinctrl_dev *pctldev, + const char *pin_group); + +static inline struct pin_desc *pin_desc_get(struct pinctrl_dev *pctldev, + unsigned int pin) +{ + return radix_tree_lookup(&pctldev->pin_desc_tree, pin); +} + +extern struct pinctrl_gpio_range * +pinctrl_find_gpio_range_from_pin_nolock(struct pinctrl_dev *pctldev, + unsigned int pin); + +extern int pinctrl_force_sleep(struct pinctrl_dev *pctldev); +extern int pinctrl_force_default(struct pinctrl_dev *pctldev); + +extern struct mutex pinctrl_maps_mutex; +extern struct list_head pinctrl_maps; + diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h new file mode 100644 index 00000000..be731137 --- /dev/null +++ b/drivers/pinctrl/pinconf.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Internal interface between the core pin control system and the + * pin config portions + * + * Copyright (C) 2011 ST-Ericsson SA + * Written on behalf of Linaro for ST-Ericsson + * Based on bits of regulator core, gpio core and clk core + * + * Author: Linus Walleij + */ + +#ifdef CONFIG_PINCONF + +int pinconf_check_ops(struct pinctrl_dev *pctldev); +int pinconf_validate_map(const struct pinctrl_map *map, int i); +int pinconf_map_to_setting(const struct pinctrl_map *map, + struct pinctrl_setting *setting); +void pinconf_free_setting(const struct pinctrl_setting *setting); +int pinconf_apply_setting(const struct pinctrl_setting *setting); + +int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *configs, size_t nconfigs); + +/* + * You will only be interested in these if you're using PINCONF + * so don't supply any stubs for these. + */ +int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *config); +int pin_config_group_get(const char *dev_name, const char *pin_group, + unsigned long *config); + +#else + +static inline int pinconf_check_ops(struct pinctrl_dev *pctldev) +{ + return 0; +} + +static inline int pinconf_validate_map(const struct pinctrl_map *map, int i) +{ + return 0; +} + +static inline int pinconf_map_to_setting(const struct pinctrl_map *map, + struct pinctrl_setting *setting) +{ + return 0; +} + +static inline void pinconf_free_setting(const struct pinctrl_setting *setting) +{ +} + +static inline int pinconf_apply_setting(const struct pinctrl_setting *setting) +{ + return 0; +} + +static inline int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *configs, size_t nconfigs) +{ + return -ENOTSUPP; +} + +#endif + +#if defined(CONFIG_PINCONF) && defined(CONFIG_DEBUG_FS) + +void pinconf_show_map(struct seq_file *s, const struct pinctrl_map *map); +void pinconf_show_setting(struct seq_file *s, + const struct pinctrl_setting *setting); +void pinconf_init_device_debugfs(struct dentry *devroot, + struct pinctrl_dev *pctldev); + +#else + +static inline void pinconf_show_map(struct seq_file *s, + const struct pinctrl_map *map) +{ +} + +static inline void pinconf_show_setting(struct seq_file *s, + const struct pinctrl_setting *setting) +{ +} + +static inline void pinconf_init_device_debugfs(struct dentry *devroot, + struct pinctrl_dev *pctldev) +{ +} + +#endif + +/* + * The following functions are available if the driver uses the generic + * pin config. + */ + +#if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_DEBUG_FS) + +void pinconf_generic_dump_pins(struct pinctrl_dev *pctldev, + struct seq_file *s, const char *gname, + unsigned pin); + +void pinconf_generic_dump_config(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned long config); +#else + +static inline void pinconf_generic_dump_pins(struct pinctrl_dev *pctldev, + struct seq_file *s, + const char *gname, unsigned pin) +{ + return; +} + +static inline void pinconf_generic_dump_config(struct pinctrl_dev *pctldev, + struct seq_file *s, + unsigned long config) +{ + return; +} +#endif + +#if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_OF) +int pinconf_generic_parse_dt_config(struct device_node *np, + struct pinctrl_dev *pctldev, + unsigned long **configs, + unsigned int *nconfigs); +#endif diff --git a/drivers/pinctrl/pinctrl-max77851.c b/drivers/pinctrl/pinctrl-max77851.c new file mode 100644 index 00000000..e692b86d --- /dev/null +++ b/drivers/pinctrl/pinctrl-max77851.c @@ -0,0 +1,833 @@ +// SPDX-License-Identifier: GPL-2.0 +// SPDX-FileCopyrightText: Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +/* + * MAX77851 pin control driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "core.h" +#include "pinconf.h" +#include "pinctrl-utils.h" + +#define MAX77851_PIN_NUM 12 + +enum max77851_pin_ppdrv { + MAX77851_PIN_OD_DRV, + MAX77851_PIN_PP_DRV, +}; + +enum max77851_pin_polarity { + MAX77851_PIN_ACTIVE_HIGH, + MAX77851_PIN_ACTIVE_LOW, +}; + +enum max77851_input_supply { + MAX77851_INPUT_VDD = 0, + MAX77851_INPUT_VIO = 1, + MAX77851_INPUT_BAT = 1, +}; + +#define MAX77851_POLARITY (PIN_CONFIG_END + 1) +#define MAX77851_INPUT_DEB_FILTER (PIN_CONFIG_END + 2) +#define MAX77851_INPUT_SUPPLY (PIN_CONFIG_END + 3) + +#define MAX77851_PU_SLPX_MASTER_SLOT (PIN_CONFIG_END + 4) +#define MAX77851_PD_SLPY_MASTER_SLOT (PIN_CONFIG_END + 5) +#define MAX77851_PU_SLOT (PIN_CONFIG_END + 6) +#define MAX77851_PD_SLOT (PIN_CONFIG_END + 7) +#define MAX77851_SLPX_SLOT (PIN_CONFIG_END + 8) +#define MAX77851_SLPY_SLOT (PIN_CONFIG_END + 9) + +#define IS_GPIO_REG_SET_HIGH(pin) ((pin >= MAX77851_GPIO4) && (pin <= MAX77851_GPIO7)) +#define IS_FPSO_REG_SET_HIGH(pin) ((pin >= MAX77851_FPSO2) && (pin <= MAX77851_FPSO3)) + +#define IS_GPIO(pin) ((pin >= MAX77851_GPIO0) && (pin <= MAX77851_GPIO7)) +#define IS_FPSO(pin) ((pin >= MAX77851_FPSO0) && (pin <= MAX77851_FPSO3)) +#define IS_NRSTIO(pin) (pin == MAX77851_NRSTIO) + +struct max77851_pin_function { + const char *name; + const char * const *groups; + unsigned int ngroups; + int mux_option; +}; + +static const struct pinconf_generic_params max77851_cfg_params[] = { + /* IO Configuration */ + { + .property = "maxim,polarity", + .param = MAX77851_POLARITY, + }, + { + .property = "maxim,input_debounce_filter", + .param = MAX77851_INPUT_DEB_FILTER, + }, + { + .property = "maxim,input_suppy", + .param = MAX77851_INPUT_SUPPLY, + }, + /* FPS Configuration */ + { + .property = "maxim,pu-slpx-master-slot", + .param = MAX77851_PU_SLPX_MASTER_SLOT, + }, + { + .property = "maxim,pd-slpy-master-slot", + .param = MAX77851_PD_SLPY_MASTER_SLOT, + }, + { + .property = "maxim,pu-slot", + .param = MAX77851_PU_SLOT, + }, + { + .property = "maxim,pd-slot", + .param = MAX77851_PD_SLOT, + }, + { + .property = "maxim,slpx-slot", + .param = MAX77851_SLPX_SLOT, + }, + { + .property = "maxim,slpy-slot", + .param = MAX77851_SLPY_SLOT, + } +}; + +struct max77851_pingroup { + const char *name; + const unsigned int pins[1]; + unsigned int npins; + unsigned int polarity; + enum max77851_alternate_pinmux_option alt_option; + + /* For FPSO, use the same address */ + u8 pin_cfg0_addr; + u8 pin_cfg1_addr; +}; + +struct max77851_pin_info { + enum max77851_pin_ppdrv drv_type; + int pull_config; +}; + +struct max77851_pctrl_info { + struct device *dev; + struct pinctrl_dev *pctl; + struct regmap *rmap; + + int pins_current_opt[MAX77851_GPIO_NR]; + + const struct max77851_pin_function *functions; + unsigned int num_functions; + + const struct max77851_pingroup *pin_groups; + int num_pin_groups; + + const struct pinctrl_pin_desc *pins; + unsigned int num_pins; + + struct max77851_fps_data *fps_reg; + unsigned int num_fps_regs; + + struct max77851_pin_info pin_info[MAX77851_PIN_NUM]; + struct max77851_fps_data fps_data[MAX77851_PIN_NUM]; +}; + +static const struct pinctrl_pin_desc max77851_pins_desc[] = { + /* GPIO 0-7 */ + PINCTRL_PIN(MAX77851_GPIO0, "gpio0"), + PINCTRL_PIN(MAX77851_GPIO1, "gpio1"), + PINCTRL_PIN(MAX77851_GPIO2, "gpio2"), + PINCTRL_PIN(MAX77851_GPIO3, "gpio3"), + PINCTRL_PIN(MAX77851_GPIO4, "gpio4"), + PINCTRL_PIN(MAX77851_GPIO5, "gpio5"), + PINCTRL_PIN(MAX77851_GPIO6, "gpio6"), + PINCTRL_PIN(MAX77851_GPIO7, "gpio7"), + /* FPSO 0-3 */ + PINCTRL_PIN(MAX77851_FPSO0, "fpso0"), + PINCTRL_PIN(MAX77851_FPSO1, "fpso1"), + PINCTRL_PIN(MAX77851_FPSO2, "fpso2"), + PINCTRL_PIN(MAX77851_FPSO3, "fpso3"), + PINCTRL_PIN(MAX77851_NRSTIO, "nrstio"), +}; + +static const char * const gpio_groups[] = { + /* GPIO 0-7 */ + "gpio0", + "gpio1", + "gpio2", + "gpio3", + "gpio4", + "gpio5", + "gpio6", + "gpio7", + /* FPSO 0-3 */ + "fpso0", + "fpso1", + "fpso2", + "fpso3", + /* nrstio */ + "nrstio" +}; + +#define FUNCTION_GPIO_GROUP(fname, mux) \ + { \ + .name = fname, \ + .groups = gpio_groups, \ + .ngroups = ARRAY_SIZE(gpio_groups), \ + .mux_option = GPIO_PINMUX_##mux, \ + } + +#define FUNCTION_FPSO_GROUP(fname, mux) \ + { \ + .name = fname, \ + .groups = gpio_groups, \ + .ngroups = ARRAY_SIZE(gpio_groups), \ + .mux_option = FPSO_PINMUX_##mux, \ + } + +#define FUNCTION_NRSTIO_GROUP(fname, mux) \ + { \ + .name = fname, \ + .groups = gpio_groups, \ + .ngroups = ARRAY_SIZE(gpio_groups), \ + .mux_option = NRSTIO_PINMUX_##mux, \ + } + +static const struct max77851_pin_function max77851_pin_function[] = { + /* GPIO */ + FUNCTION_GPIO_GROUP("gpio-high-z", HIGH_Z), + FUNCTION_GPIO_GROUP("gpio-input", GPIO_INPUT), + FUNCTION_GPIO_GROUP("gpio-output", GPIO_OUTPUT), + FUNCTION_GPIO_GROUP("gpio-fps-digital-input", FPS_DIGITAL_INPUT), + FUNCTION_GPIO_GROUP("gpio-fps-digital-output", FPS_DIGITAL_OUTPUT), + FUNCTION_GPIO_GROUP("src-enable-digital-input", SRC_ENABLE_DIGITAL_INPUT), + FUNCTION_GPIO_GROUP("src-boot-dvs-digital-input", SRC_BOOT_DVS_DIGITAL_INPUT), + FUNCTION_GPIO_GROUP("src-clock-digital-input", SRC_CLOCK_DIGITAL_INPUT), + FUNCTION_GPIO_GROUP("src-fpwm-digital-input", SRC_FPWM_DIGITAL_INPUT), + FUNCTION_GPIO_GROUP("src-pok-gpio-digital-output", SRC_POK_GPIO_DIGITAL_OUTPUT), + FUNCTION_GPIO_GROUP("clk-32k-out", CLK_32K_OUT), + FUNCTION_GPIO_GROUP("lb-alarm-output", LB_ALARM_OUTPUT), + FUNCTION_GPIO_GROUP("o-type-reset", O_TYPE_RESET), + FUNCTION_GPIO_GROUP("test-digital-input", TEST_DIGITAL_INPUT), + FUNCTION_GPIO_GROUP("test-digital-output", TEST_DIGITAL_OUTPUT), + FUNCTION_GPIO_GROUP("test-analog-in-out", TEST_ANALOG_IN_OUT), + + /* FPSO */ + FUNCTION_FPSO_GROUP("fpso-high-z", HIGH_Z), + FUNCTION_FPSO_GROUP("fpso-digital-output", DIGITAL_OUTPUT), + FUNCTION_FPSO_GROUP("fpso-fps-digital-output", FPS_DIGITAL_OUTPUT), + FUNCTION_FPSO_GROUP("fpso-buck-sense", BUCK_SENSE), + + /* NRSTIO */ + FUNCTION_NRSTIO_GROUP("nrstio-high-z", HIGH_Z), + FUNCTION_NRSTIO_GROUP("nrstio-digital-input", DIGITAL_INPUT), + FUNCTION_NRSTIO_GROUP("nrstio-digital-output", DIGITAL_OUTPUT), + FUNCTION_NRSTIO_GROUP("nrstio-fps-digital-output", FPS_DIGITAL_OUTPUT), + FUNCTION_NRSTIO_GROUP("nrstio-lb-digital-output", LB_DIGITAL_OUTPUT), +}; + +#define MAX77851_GPIO_PINGROUP(_pg_name, _pin_id, _option, _polarity) \ +{ \ + .name = #_pg_name, \ + .pins = {MAX77851_##_pin_id}, \ + .npins = 1, \ + .alt_option = GPIO_PINMUX_##_option, \ + .polarity = MAX77851_PIN_##_polarity, \ + .pin_cfg0_addr = _pin_id##_CFG0_REG, \ + .pin_cfg1_addr = _pin_id##_CFG1_REG, \ +} + +#define MAX77851_FPSO_PINGROUP(_pg_name, _pin_id, _option, _polarity) \ +{ \ + .name = #_pg_name, \ + .pins = {MAX77851_##_pin_id}, \ + .npins = 1, \ + .alt_option = FPSO_PINMUX_##_option, \ + .polarity = MAX77851_PIN_##_polarity, \ + .pin_cfg0_addr = _pin_id##_CFG_REG, \ + .pin_cfg1_addr = _pin_id##_CFG_REG, \ +} + +#define MAX77851_NRSTIO_PINGROUP(_pg_name, _pin_id, _option, _polarity) \ +{ \ + .name = #_pg_name, \ + .pins = {MAX77851_##_pin_id}, \ + .npins = 1, \ + .alt_option = NRSTIO_PINMUX_##_option, \ + .polarity = MAX77851_PIN_##_polarity, \ + .pin_cfg0_addr = _pin_id##_CFG0_REG, \ + .pin_cfg1_addr = _pin_id##_CFG1_REG, \ +} + +static const struct max77851_pingroup max77851_pingroups[] = { + MAX77851_GPIO_PINGROUP(gpio0, GPIO0, CLK_32K_OUT, ACTIVE_HIGH), + MAX77851_GPIO_PINGROUP(gpio1, GPIO1, FPS_DIGITAL_OUTPUT, ACTIVE_LOW), + MAX77851_GPIO_PINGROUP(gpio2, GPIO2, LB_ALARM_OUTPUT, ACTIVE_HIGH), + MAX77851_GPIO_PINGROUP(gpio3, GPIO3, FPS_DIGITAL_INPUT, ACTIVE_HIGH), + MAX77851_GPIO_PINGROUP(gpio4, GPIO4, SRC_BOOT_DVS_DIGITAL_INPUT, ACTIVE_HIGH), + MAX77851_GPIO_PINGROUP(gpio5, GPIO5, HIGH_Z, ACTIVE_HIGH), + MAX77851_GPIO_PINGROUP(gpio6, GPIO6, HIGH_Z, ACTIVE_HIGH), + MAX77851_GPIO_PINGROUP(gpio7, GPIO7, SRC_BOOT_DVS_DIGITAL_INPUT, ACTIVE_HIGH), + + MAX77851_FPSO_PINGROUP(fpso0, FPSO0, FPS_DIGITAL_OUTPUT, ACTIVE_HIGH), + MAX77851_FPSO_PINGROUP(fpso1, FPSO1, FPS_DIGITAL_OUTPUT, ACTIVE_HIGH), + MAX77851_FPSO_PINGROUP(fpso2, FPSO2, BUCK_SENSE, ACTIVE_HIGH), + MAX77851_FPSO_PINGROUP(fpso3, FPSO3, FPS_DIGITAL_OUTPUT, ACTIVE_HIGH), + + MAX77851_NRSTIO_PINGROUP(nrstio, NRSTIO, FPS_DIGITAL_OUTPUT, ACTIVE_HIGH), +}; + +#define MAX77851_FPS_PINCTRL_REG_GROUP(_fps_name) \ +{ \ + .fps_cfg0_addr = _fps_name##_CFG0_REG, \ + .fps_cfg1_addr = _fps_name##_CFG1_REG, \ + .fps_cfg2_addr = _fps_name##_CFG2_REG, \ +} + +static struct max77851_fps_data max77851_fps_reg_groups[] = { + MAX77851_FPS_PINCTRL_REG_GROUP(FPS_GPIO04), + MAX77851_FPS_PINCTRL_REG_GROUP(FPS_GPIO15), + MAX77851_FPS_PINCTRL_REG_GROUP(FPS_GPIO26), + MAX77851_FPS_PINCTRL_REG_GROUP(FPS_GPIO37), + MAX77851_FPS_PINCTRL_REG_GROUP(FPS_GPIO04), + MAX77851_FPS_PINCTRL_REG_GROUP(FPS_GPIO15), + MAX77851_FPS_PINCTRL_REG_GROUP(FPS_GPIO26), + MAX77851_FPS_PINCTRL_REG_GROUP(FPS_GPIO37), + + MAX77851_FPS_PINCTRL_REG_GROUP(FPS_FPSO02), + MAX77851_FPS_PINCTRL_REG_GROUP(FPS_FPSO13), + MAX77851_FPS_PINCTRL_REG_GROUP(FPS_FPSO02), + MAX77851_FPS_PINCTRL_REG_GROUP(FPS_FPSO13), + + MAX77851_FPS_PINCTRL_REG_GROUP(FPS_NRSTIO), +}; + + +/* + * 0 : GPIO 0 + GPIO 1 + GPIO 3 + GPIO 3 + * 1 : GPIO 4 + GPIO 5 + GPIO 6 + GPIO 7 + */ +static int max77851_pinctrl_register_rw_set(struct regmap *rmap, unsigned int pin) +{ + int ret; + unsigned int val = 0; + unsigned int mask = (FPS_CFG_GPIOX_RW | FPS_CFG_FPSOX_RW); + + if (IS_GPIO(pin)) { + if (IS_GPIO_REG_SET_HIGH(pin)) + val |= FPS_CFG_GPIOX_RW; + } + + if (IS_FPSO(pin)) { + if (IS_FPSO_REG_SET_HIGH(pin)) + val |= FPS_CFG_FPSOX_RW; + } + + ret = regmap_update_bits(rmap, FPS_CFG_REG, mask, val); + + return ret; +} + +static int max77851_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct max77851_pctrl_info *pcntl = pinctrl_dev_get_drvdata(pctldev); + + return pcntl->num_pin_groups; +} + +static const char *max77851_pinctrl_get_group_name( + struct pinctrl_dev *pctldev, unsigned int group) +{ + struct max77851_pctrl_info *pcntl = pinctrl_dev_get_drvdata(pctldev); + + return pcntl->pin_groups[group].name; +} + +static int max77851_pinctrl_get_group_pins( + struct pinctrl_dev *pctldev, unsigned int group, + const unsigned int **pins, unsigned int *num_pins) +{ + struct max77851_pctrl_info *pcntl = pinctrl_dev_get_drvdata(pctldev); + + *pins = pcntl->pin_groups[group].pins; + *num_pins = pcntl->pin_groups[group].npins; + + return 0; +} + +static const struct pinctrl_ops max77851_pinctrl_ops = { + .get_groups_count = max77851_pinctrl_get_groups_count, + .get_group_name = max77851_pinctrl_get_group_name, + .get_group_pins = max77851_pinctrl_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, + .dt_free_map = pinctrl_utils_free_map, +}; + +static int max77851_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev) +{ + struct max77851_pctrl_info *pcntl = pinctrl_dev_get_drvdata(pctldev); + + return pcntl->num_functions; +} + +static const char *max77851_pinctrl_get_func_name(struct pinctrl_dev *pctldev, + unsigned int function) +{ + struct max77851_pctrl_info *pcntl = pinctrl_dev_get_drvdata(pctldev); + + return pcntl->functions[function].name; +} + +static int max77851_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, + unsigned int function, + const char * const **groups, + unsigned int * const num_groups) +{ + struct max77851_pctrl_info *pcntl = pinctrl_dev_get_drvdata(pctldev); + + *groups = pcntl->functions[function].groups; + *num_groups = pcntl->functions[function].ngroups; + + return 0; +} + +static int max77851_pinctrl_enable(struct pinctrl_dev *pctldev, + unsigned int function, unsigned int group) +{ + struct max77851_pctrl_info *pcntl = pinctrl_dev_get_drvdata(pctldev); + u8 reg_addr; + u8 val; + int mask, shift; + int ret; + unsigned int pin; + + pin = pcntl->pin_groups[group].pins[0]; + reg_addr = pcntl->pin_groups[group].pin_cfg1_addr; + + if (IS_GPIO(pin)) { + val = function; + shift = FFS(GPIO_CFG1_MODE); + mask = GPIO_CFG1_MODE; + } else if (IS_FPSO(pin)) { + val = function - FPSO_PINMUX_OFFSET; + shift = FFS(FPSO_MODE_MASK); + mask = FPSO_MODE_MASK; + } else if (IS_NRSTIO(pin)) { + val = function - NRSTIO_PINMUX_OFFSET; + shift = FFS(NRSTIO_CFG1_MODE); + mask = NRSTIO_CFG1_MODE; + } + + if (!(IS_GPIO(pin) || IS_FPSO(pin) || IS_NRSTIO(pin))) { + dev_err(pcntl->dev, "GPIO %u doesn't have function %u\n", group, function); + return -EINVAL; + } + + ret = regmap_update_bits(pcntl->rmap, reg_addr, mask, val << shift); + if (ret < 0) + dev_err(pcntl->dev, "Pin Control failed: %d\n", ret); + + return ret; +} + +static const struct pinmux_ops max77851_pinmux_ops = { + .get_functions_count = max77851_pinctrl_get_funcs_count, + .get_function_name = max77851_pinctrl_get_func_name, + .get_function_groups = max77851_pinctrl_get_func_groups, + .set_mux = max77851_pinctrl_enable, +}; + +static int max77851_pinconf_get(struct pinctrl_dev *pctldev, + unsigned int pin, unsigned long *config) +{ + struct max77851_pctrl_info *pcntl = pinctrl_dev_get_drvdata(pctldev); + struct device *dev = pcntl->dev; + enum pin_config_param param = pinconf_to_config_param(*config); + unsigned int val; + int arg = 0; + int ret; + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (pcntl->pin_info[pin].drv_type == MAX77851_PIN_OD_DRV) + arg = 1; + break; + + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (pcntl->pin_info[pin].drv_type == MAX77851_PIN_PP_DRV) + arg = 1; + break; + + case PIN_CONFIG_BIAS_PULL_UP: + ret = regmap_read(pcntl->rmap, pcntl->pin_groups[pin].pin_cfg0_addr, &val); + if (ret < 0) { + dev_err(dev, "Reg PUE_GPIO read failed: %d\n", ret); + return ret; + } + if (val & GPIO_CFG0_PU) + arg = 1; + break; + + case PIN_CONFIG_BIAS_PULL_DOWN: + ret = regmap_read(pcntl->rmap, pcntl->pin_groups[pin].pin_cfg0_addr, &val); + if (ret < 0) { + dev_err(dev, "Reg PDE_GPIO read failed: %d\n", ret); + return ret; + } + if (val & GPIO_CFG0_PD) + arg = 1; + break; + + default: + dev_err(dev, "Properties not supported\n"); + return -ENOTSUPP; + } + + *config = pinconf_to_config_packed(param, (u16)arg); + + return 0; +} + +static int max77851_pinconf_set(struct pinctrl_dev *pctldev, + unsigned int pin, unsigned long *configs, + unsigned int num_configs) +{ + struct max77851_pctrl_info *pcntl = pinctrl_dev_get_drvdata(pctldev); + struct device *dev = pcntl->dev; + struct max77851_fps_data *fps_data = &pcntl->fps_data[pin]; + + int param; + u16 param_val; + u8 reg_addr; + u8 reg_addr0; + u8 reg_addr1; + unsigned int val; + unsigned int pu_val; + unsigned int pd_val; + int ret; + int i; + + int mask, shift; + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + param_val = pinconf_to_config_argument(configs[i]); + + reg_addr0 = pcntl->pin_groups[pin].pin_cfg0_addr; + reg_addr1 = pcntl->pin_groups[pin].pin_cfg1_addr; + + /* The register set should be set first before setting the FPS */ + switch (param) { + case MAX77851_PU_SLPX_MASTER_SLOT: + case MAX77851_PD_SLPY_MASTER_SLOT: + case MAX77851_PU_SLOT: + case MAX77851_PD_SLOT: + case MAX77851_SLPX_SLOT: + case MAX77851_SLPY_SLOT: + ret = max77851_pinctrl_register_rw_set(pcntl->rmap, pin); + if (ret < 0) { + dev_err(dev, "Pin Control Register Set failed: %d\n", ret); + return ret; + } + break; + default: + break; + } + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + mask = GPIO_CFG1_DRV; + val = param_val ? 0 : 1; + shift = FFS(GPIO_CFG1_DRV); + reg_addr = pcntl->pin_groups[pin].pin_cfg1_addr; + + ret = regmap_update_bits(pcntl->rmap, reg_addr, mask, val << shift); + if (ret < 0) { + dev_err(dev, "Reg 0x%02x update failed %d\n", reg_addr1, ret); + return ret; + } + pcntl->pin_info[pin].drv_type = val ? MAX77851_PIN_PP_DRV : MAX77851_PIN_OD_DRV; + break; + + case PIN_CONFIG_DRIVE_PUSH_PULL: + mask = GPIO_CFG1_DRV; + val = param_val ? 1 : 0; + shift = FFS(GPIO_CFG1_DRV); + reg_addr = pcntl->pin_groups[pin].pin_cfg1_addr; + + ret = regmap_update_bits(pcntl->rmap, reg_addr, mask, val << shift); + if (ret < 0) { + dev_err(dev, "Reg 0x%02x update failed %d\n", reg_addr1, ret); + return ret; + } + pcntl->pin_info[pin].drv_type = val ? MAX77851_PIN_PP_DRV : MAX77851_PIN_OD_DRV; + break; + + case PIN_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_BIAS_PULL_DOWN: + pu_val = (param == PIN_CONFIG_BIAS_PULL_UP) ? 1 : 0; + pd_val = (param == PIN_CONFIG_BIAS_PULL_DOWN) ? 1 : 0; + mask = GPIO_CFG0_PU | GPIO_CFG0_PD; + val = ((pu_val << FFS(GPIO_CFG0_PU)) | (pd_val << FFS(GPIO_CFG0_PD))); + shift = 0; + reg_addr = pcntl->pin_groups[pin].pin_cfg0_addr; + + ret = regmap_update_bits(pcntl->rmap, reg_addr, mask, val << shift); + if (ret < 0) { + dev_err(dev, "PULL Up/Down GPIO update failed: %d\n", ret); + return ret; + } + break; + + case MAX77851_POLARITY: + if (IS_FPSO(pin)) { + mask = FPSO_CFG_POL; + shift = FFS(FPSO_CFG_POL); + } else { + mask = GPIO_CFG0_POL; + shift = FFS(GPIO_CFG0_POL); + } + + val = param_val; + reg_addr = pcntl->pin_groups[pin].pin_cfg0_addr; + + ret = regmap_update_bits(pcntl->rmap, reg_addr, mask, val << shift); + if (ret < 0) { + dev_err(dev, "PDE_GPIO update failed: %d\n", ret); + return ret; + } + break; + + case MAX77851_INPUT_DEB_FILTER: + if (IS_GPIO(pin) || IS_NRSTIO(pin)) { + mask = GPIO_CFG0_IFILTER; + shift = FFS(GPIO_CFG0_IFILTER); + val = param_val; + reg_addr = pcntl->pin_groups[pin].pin_cfg0_addr; + + ret = regmap_update_bits(pcntl->rmap, reg_addr, mask, val << shift); + if (ret < 0) { + dev_err(dev, "Input Deb Filter update failed: %d\n", ret); + return ret; + } + } + break; + + case MAX77851_INPUT_SUPPLY: + if (IS_GPIO(pin) || IS_NRSTIO(pin)) { + mask = GPIO_CFG0_SUP; + shift = FFS(GPIO_CFG0_SUP); + } + + val = param_val; + reg_addr = pcntl->pin_groups[pin].pin_cfg0_addr; + + ret = regmap_update_bits(pcntl->rmap, reg_addr, mask, val << shift); + if (ret < 0) { + dev_err(dev, "Input Supply GPIO update failed: %d\n", ret); + return ret; + } + break; + + case MAX77851_PU_SLPX_MASTER_SLOT: + mask = MAX77851_FPS_PU_SLPX_SLOT_MASK; + shift = FFS(MAX77851_FPS_PU_SLPX_SLOT_MASK); + + val = param_val; + reg_addr = fps_data->fps_cfg0_addr; + + ret = regmap_update_bits(pcntl->rmap, reg_addr, mask, val << shift); + if (ret < 0) { + dev_err(dev, "SLPX MASTER SLOT update failed: %d\n", ret); + return ret; + } + break; + + case MAX77851_PD_SLPY_MASTER_SLOT: + mask = MAX77851_FPS_PD_SLPY_SLOT_MASK; + shift = FFS(MAX77851_FPS_PD_SLPY_SLOT_MASK); + + val = param_val; + reg_addr = fps_data->fps_cfg0_addr; + + ret = regmap_update_bits(pcntl->rmap, reg_addr, mask, val << shift); + if (ret < 0) { + dev_err(dev, "SLPY MASTER SLOT update failed: %d\n", ret); + return ret; + } + break; + + case MAX77851_PU_SLOT: + mask = MAX77851_FPS_PU_SLOT_MASK; + shift = FFS(MAX77851_FPS_PU_SLOT_MASK); + + val = param_val; + reg_addr = fps_data->fps_cfg1_addr; + + ret = regmap_update_bits(pcntl->rmap, reg_addr, mask, val << shift); + if (ret < 0) { + dev_err(dev, "PU SLOT update failed: %d\n", ret); + return ret; + } + break; + + case MAX77851_PD_SLOT: + mask = MAX77851_FPS_PD_SLOT_MASK; + shift = FFS(MAX77851_FPS_PD_SLOT_MASK); + + val = param_val; + reg_addr = fps_data->fps_cfg1_addr; + + ret = regmap_update_bits(pcntl->rmap, reg_addr, mask, val << shift); + if (ret < 0) { + dev_err(dev, "PD SLOT update failed: %d\n", ret); + return ret; + } + break; + + case MAX77851_SLPX_SLOT: + mask = MAX77851_FPS_SLPX_SLOT_MASK; + shift = FFS(MAX77851_FPS_SLPX_SLOT_MASK); + + val = param_val; + reg_addr = fps_data->fps_cfg2_addr; + + ret = regmap_update_bits(pcntl->rmap, reg_addr, mask, val << shift); + if (ret < 0) { + dev_err(dev, "SLPX SLOT update failed: %d\n", ret); + return ret; + } + break; + + case MAX77851_SLPY_SLOT: + mask = MAX77851_FPS_SLPY_SLOT_MASK; + shift = FFS(MAX77851_FPS_SLPY_SLOT_MASK); + + val = param_val; + reg_addr = fps_data->fps_cfg2_addr; + + ret = regmap_update_bits(pcntl->rmap, reg_addr, mask, val << shift); + if (ret < 0) { + dev_err(dev, "SLPY SLOT update failed: %d\n", ret); + return ret; + } + break; + default: + dev_err(dev, "Properties not supported\n"); + return -ENOTSUPP; + } + } + + return 0; +} + +static const struct pinconf_ops max77851_pinconf_ops = { + .pin_config_get = max77851_pinconf_get, + .pin_config_set = max77851_pinconf_set, +}; + +static struct pinctrl_desc max77851_pinctrl_desc = { + .pctlops = &max77851_pinctrl_ops, + .pmxops = &max77851_pinmux_ops, + .confops = &max77851_pinconf_ops, +}; + +static int max77851_pinctrl_probe(struct platform_device *pdev) +{ + struct max77851_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct max77851_pctrl_info *pcntl; + int i; + + pcntl = devm_kzalloc(&pdev->dev, sizeof(*pcntl), GFP_KERNEL); + if (!pcntl) + return -ENOMEM; + + pcntl->dev = &pdev->dev; + pcntl->dev->of_node = pdev->dev.parent->of_node; + pcntl->rmap = chip->rmap; + + pcntl->pins = max77851_pins_desc; + pcntl->num_pins = ARRAY_SIZE(max77851_pins_desc); + pcntl->functions = max77851_pin_function; + pcntl->num_functions = ARRAY_SIZE(max77851_pin_function); + pcntl->pin_groups = max77851_pingroups; + pcntl->num_pin_groups = ARRAY_SIZE(max77851_pingroups); + pcntl->fps_reg = max77851_fps_reg_groups; + pcntl->num_fps_regs = ARRAY_SIZE(max77851_fps_reg_groups); + platform_set_drvdata(pdev, pcntl); + + max77851_pinctrl_desc.name = dev_name(&pdev->dev); + max77851_pinctrl_desc.pins = max77851_pins_desc; + max77851_pinctrl_desc.npins = ARRAY_SIZE(max77851_pins_desc); + max77851_pinctrl_desc.num_custom_params = ARRAY_SIZE(max77851_cfg_params); + max77851_pinctrl_desc.custom_params = max77851_cfg_params; + + for (i = 0; i < MAX77851_PIN_NUM; ++i) { + pcntl->fps_data[i].pu_slpx_master_slot = -1; + pcntl->fps_data[i].pd_slpy_master_slot = -1; + pcntl->fps_data[i].pd_slot = -1; + pcntl->fps_data[i].pd_slot = -1; + pcntl->fps_data[i].slpy_slot = -1; + pcntl->fps_data[i].slpx_slot = -1; + } + + devm_pinctrl_register_and_init(&pdev->dev, &max77851_pinctrl_desc, pcntl, &pcntl->pctl); + if (IS_ERR(pcntl->pctl)) { + dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); + return PTR_ERR(pcntl->pctl); + } + + pinctrl_enable(pcntl->pctl); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int max77851_pinctrl_suspend(struct device *dev) +{ + return 0; +}; + +static int max77851_pinctrl_resume(struct device *dev) +{ + return 0; +} +#endif + +static const struct dev_pm_ops max77851_pinctrl_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS( + max77851_pinctrl_suspend, max77851_pinctrl_resume) +}; + +static const struct platform_device_id max77851_pinctrl_devtype[] = { + { .name = "max77851-pinctrl", }, + {}, +}; +MODULE_DEVICE_TABLE(platform, max77851_pinctrl_devtype); + +static struct platform_driver max77851_pinctrl_driver = { + .driver = { + .name = "max77851-pinctrl", + .pm = &max77851_pinctrl_pm_ops, + }, + .probe = max77851_pinctrl_probe, + .id_table = max77851_pinctrl_devtype, +}; + +module_platform_driver(max77851_pinctrl_driver); + +MODULE_DESCRIPTION("MAX77851 pin control driver"); +MODULE_AUTHOR("Shubhi Garg"); +MODULE_AUTHOR("Joan Na"); +MODULE_ALIAS("platform:max77851-pinctrl"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pinctrl/pinctrl-utils.h b/drivers/pinctrl/pinctrl-utils.h new file mode 100644 index 00000000..ac02826f --- /dev/null +++ b/drivers/pinctrl/pinctrl-utils.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* SPDX-FileCopyrightText: Copyright (c) 2013-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ +/* + * Utils functions to implement the pincontrol driver. + * Author: Laxman Dewangan + */ +#ifndef __PINCTRL_UTILS_H__ +#define __PINCTRL_UTILS_H__ + +int pinctrl_utils_reserve_map(struct pinctrl_dev *pctldev, + struct pinctrl_map **map, unsigned *reserved_maps, + unsigned *num_maps, unsigned reserve); +int pinctrl_utils_add_map_mux(struct pinctrl_dev *pctldev, + struct pinctrl_map **map, unsigned *reserved_maps, + unsigned *num_maps, const char *group, + const char *function); +int pinctrl_utils_add_map_configs(struct pinctrl_dev *pctldev, + struct pinctrl_map **map, unsigned *reserved_maps, + unsigned *num_maps, const char *group, + unsigned long *configs, unsigned num_configs, + enum pinctrl_map_type type); +int pinctrl_utils_add_config(struct pinctrl_dev *pctldev, + unsigned long **configs, unsigned *num_configs, + unsigned long config); +void pinctrl_utils_free_map(struct pinctrl_dev *pctldev, + struct pinctrl_map *map, unsigned num_maps); + +#endif /* __PINCTRL_UTILS_H__ */