162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Marvell MVEBU pinctrl driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> 662306a36Sopenharmony_ci * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#ifndef __PINCTRL_MVEBU_H__ 1062306a36Sopenharmony_ci#define __PINCTRL_MVEBU_H__ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/** 1362306a36Sopenharmony_ci * struct mvebu_mpp_ctrl_data - private data for the mpp ctrl operations 1462306a36Sopenharmony_ci * @base: base address of pinctrl hardware 1562306a36Sopenharmony_ci * @regmap.map: regmap structure 1662306a36Sopenharmony_ci * @regmap.offset: regmap offset 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_cistruct mvebu_mpp_ctrl_data { 1962306a36Sopenharmony_ci union { 2062306a36Sopenharmony_ci void __iomem *base; 2162306a36Sopenharmony_ci struct { 2262306a36Sopenharmony_ci struct regmap *map; 2362306a36Sopenharmony_ci u32 offset; 2462306a36Sopenharmony_ci } regmap; 2562306a36Sopenharmony_ci }; 2662306a36Sopenharmony_ci}; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/** 2962306a36Sopenharmony_ci * struct mvebu_mpp_ctrl - describe a mpp control 3062306a36Sopenharmony_ci * @name: name of the control group 3162306a36Sopenharmony_ci * @pid: first pin id handled by this control 3262306a36Sopenharmony_ci * @npins: number of pins controlled by this control 3362306a36Sopenharmony_ci * @mpp_get: (optional) special function to get mpp setting 3462306a36Sopenharmony_ci * @mpp_set: (optional) special function to set mpp setting 3562306a36Sopenharmony_ci * @mpp_gpio_req: (optional) special function to request gpio 3662306a36Sopenharmony_ci * @mpp_gpio_dir: (optional) special function to set gpio direction 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * A mpp_ctrl describes a muxable unit, e.g. pin, group of pins, or 3962306a36Sopenharmony_ci * internal function, inside the SoC. Each muxable unit can be switched 4062306a36Sopenharmony_ci * between two or more different settings, e.g. assign mpp pin 13 to 4162306a36Sopenharmony_ci * uart1 or sata. 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * The mpp_get/_set functions are mandatory and are used to get/set a 4462306a36Sopenharmony_ci * specific mode. The optional mpp_gpio_req/_dir functions can be used 4562306a36Sopenharmony_ci * to allow pin settings with varying gpio pins. 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_cistruct mvebu_mpp_ctrl { 4862306a36Sopenharmony_ci const char *name; 4962306a36Sopenharmony_ci u8 pid; 5062306a36Sopenharmony_ci u8 npins; 5162306a36Sopenharmony_ci unsigned *pins; 5262306a36Sopenharmony_ci int (*mpp_get)(struct mvebu_mpp_ctrl_data *data, unsigned pid, 5362306a36Sopenharmony_ci unsigned long *config); 5462306a36Sopenharmony_ci int (*mpp_set)(struct mvebu_mpp_ctrl_data *data, unsigned pid, 5562306a36Sopenharmony_ci unsigned long config); 5662306a36Sopenharmony_ci int (*mpp_gpio_req)(struct mvebu_mpp_ctrl_data *data, unsigned pid); 5762306a36Sopenharmony_ci int (*mpp_gpio_dir)(struct mvebu_mpp_ctrl_data *data, unsigned pid, 5862306a36Sopenharmony_ci bool input); 5962306a36Sopenharmony_ci}; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/** 6262306a36Sopenharmony_ci * struct mvebu_mpp_ctrl_setting - describe a mpp ctrl setting 6362306a36Sopenharmony_ci * @val: ctrl setting value 6462306a36Sopenharmony_ci * @name: ctrl setting name, e.g. uart2, spi0 - unique per mpp_mode 6562306a36Sopenharmony_ci * @subname: (optional) additional ctrl setting name, e.g. rts, cts 6662306a36Sopenharmony_ci * @variant: (optional) variant identifier mask 6762306a36Sopenharmony_ci * @flags: (private) flags to store gpi/gpo/gpio capabilities 6862306a36Sopenharmony_ci * 6962306a36Sopenharmony_ci * A ctrl_setting describes a specific internal mux function that a mpp pin 7062306a36Sopenharmony_ci * can be switched to. The value (val) will be written in the corresponding 7162306a36Sopenharmony_ci * register for common mpp pin configuration registers on MVEBU. SoC specific 7262306a36Sopenharmony_ci * mpp_get/_set function may use val to distinguish between different settings. 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci * The name will be used to switch to this setting in DT description, e.g. 7562306a36Sopenharmony_ci * marvell,function = "uart2". subname is only for debugging purposes. 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci * If name is one of "gpi", "gpo", "gpio" gpio capabilities are 7862306a36Sopenharmony_ci * parsed during initialization and stored in flags. 7962306a36Sopenharmony_ci * 8062306a36Sopenharmony_ci * The variant can be used to combine different revisions of one SoC to a 8162306a36Sopenharmony_ci * common pinctrl driver. It is matched (AND) with variant of soc_info to 8262306a36Sopenharmony_ci * determine if a setting is available on the current SoC revision. 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_cistruct mvebu_mpp_ctrl_setting { 8562306a36Sopenharmony_ci u8 val; 8662306a36Sopenharmony_ci const char *name; 8762306a36Sopenharmony_ci const char *subname; 8862306a36Sopenharmony_ci u8 variant; 8962306a36Sopenharmony_ci u8 flags; 9062306a36Sopenharmony_ci#define MVEBU_SETTING_GPO (1 << 0) 9162306a36Sopenharmony_ci#define MVEBU_SETTING_GPI (1 << 1) 9262306a36Sopenharmony_ci}; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci/** 9562306a36Sopenharmony_ci * struct mvebu_mpp_mode - link ctrl and settings 9662306a36Sopenharmony_ci * @pid: first pin id handled by this mode 9762306a36Sopenharmony_ci * @settings: list of settings available for this mode 9862306a36Sopenharmony_ci * 9962306a36Sopenharmony_ci * A mode connects all available settings with the corresponding mpp_ctrl 10062306a36Sopenharmony_ci * given by pid. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_cistruct mvebu_mpp_mode { 10362306a36Sopenharmony_ci u8 pid; 10462306a36Sopenharmony_ci struct mvebu_mpp_ctrl_setting *settings; 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci/** 10862306a36Sopenharmony_ci * struct mvebu_pinctrl_soc_info - SoC specific info passed to pinctrl-mvebu 10962306a36Sopenharmony_ci * @variant: variant mask of soc_info 11062306a36Sopenharmony_ci * @controls: list of available mvebu_mpp_ctrls 11162306a36Sopenharmony_ci * @control_data: optional array, one entry for each control 11262306a36Sopenharmony_ci * @ncontrols: number of available mvebu_mpp_ctrls 11362306a36Sopenharmony_ci * @modes: list of available mvebu_mpp_modes 11462306a36Sopenharmony_ci * @nmodes: number of available mvebu_mpp_modes 11562306a36Sopenharmony_ci * @gpioranges: list of pinctrl_gpio_ranges 11662306a36Sopenharmony_ci * @ngpioranges: number of available pinctrl_gpio_ranges 11762306a36Sopenharmony_ci * 11862306a36Sopenharmony_ci * This struct describes all pinctrl related information for a specific SoC. 11962306a36Sopenharmony_ci * If variant is unequal 0 it will be matched (AND) with variant of each 12062306a36Sopenharmony_ci * setting and allows to distinguish between different revisions of one SoC. 12162306a36Sopenharmony_ci */ 12262306a36Sopenharmony_cistruct mvebu_pinctrl_soc_info { 12362306a36Sopenharmony_ci u8 variant; 12462306a36Sopenharmony_ci const struct mvebu_mpp_ctrl *controls; 12562306a36Sopenharmony_ci struct mvebu_mpp_ctrl_data *control_data; 12662306a36Sopenharmony_ci int ncontrols; 12762306a36Sopenharmony_ci struct mvebu_mpp_mode *modes; 12862306a36Sopenharmony_ci int nmodes; 12962306a36Sopenharmony_ci struct pinctrl_gpio_range *gpioranges; 13062306a36Sopenharmony_ci int ngpioranges; 13162306a36Sopenharmony_ci}; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci#define MPP_FUNC_CTRL(_idl, _idh, _name, _func) \ 13462306a36Sopenharmony_ci { \ 13562306a36Sopenharmony_ci .name = _name, \ 13662306a36Sopenharmony_ci .pid = _idl, \ 13762306a36Sopenharmony_ci .npins = _idh - _idl + 1, \ 13862306a36Sopenharmony_ci .pins = (unsigned[_idh - _idl + 1]) { }, \ 13962306a36Sopenharmony_ci .mpp_get = _func ## _get, \ 14062306a36Sopenharmony_ci .mpp_set = _func ## _set, \ 14162306a36Sopenharmony_ci .mpp_gpio_req = NULL, \ 14262306a36Sopenharmony_ci .mpp_gpio_dir = NULL, \ 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci#define MPP_FUNC_GPIO_CTRL(_idl, _idh, _name, _func) \ 14662306a36Sopenharmony_ci { \ 14762306a36Sopenharmony_ci .name = _name, \ 14862306a36Sopenharmony_ci .pid = _idl, \ 14962306a36Sopenharmony_ci .npins = _idh - _idl + 1, \ 15062306a36Sopenharmony_ci .pins = (unsigned[_idh - _idl + 1]) { }, \ 15162306a36Sopenharmony_ci .mpp_get = _func ## _get, \ 15262306a36Sopenharmony_ci .mpp_set = _func ## _set, \ 15362306a36Sopenharmony_ci .mpp_gpio_req = _func ## _gpio_req, \ 15462306a36Sopenharmony_ci .mpp_gpio_dir = _func ## _gpio_dir, \ 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci#define _MPP_VAR_FUNCTION(_val, _name, _subname, _mask) \ 15862306a36Sopenharmony_ci { \ 15962306a36Sopenharmony_ci .val = _val, \ 16062306a36Sopenharmony_ci .name = _name, \ 16162306a36Sopenharmony_ci .subname = _subname, \ 16262306a36Sopenharmony_ci .variant = _mask, \ 16362306a36Sopenharmony_ci .flags = 0, \ 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 16762306a36Sopenharmony_ci#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask) \ 16862306a36Sopenharmony_ci _MPP_VAR_FUNCTION(_val, _name, _subname, _mask) 16962306a36Sopenharmony_ci#else 17062306a36Sopenharmony_ci#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask) \ 17162306a36Sopenharmony_ci _MPP_VAR_FUNCTION(_val, _name, NULL, _mask) 17262306a36Sopenharmony_ci#endif 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci#define MPP_FUNCTION(_val, _name, _subname) \ 17562306a36Sopenharmony_ci MPP_VAR_FUNCTION(_val, _name, _subname, (u8)-1) 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci#define MPP_MODE(_id, ...) \ 17862306a36Sopenharmony_ci { \ 17962306a36Sopenharmony_ci .pid = _id, \ 18062306a36Sopenharmony_ci .settings = (struct mvebu_mpp_ctrl_setting[]){ \ 18162306a36Sopenharmony_ci __VA_ARGS__, { } }, \ 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci#define MPP_GPIO_RANGE(_id, _pinbase, _gpiobase, _npins) \ 18562306a36Sopenharmony_ci { \ 18662306a36Sopenharmony_ci .name = "mvebu-gpio", \ 18762306a36Sopenharmony_ci .id = _id, \ 18862306a36Sopenharmony_ci .pin_base = _pinbase, \ 18962306a36Sopenharmony_ci .base = _gpiobase, \ 19062306a36Sopenharmony_ci .npins = _npins, \ 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci#define MVEBU_MPPS_PER_REG 8 19462306a36Sopenharmony_ci#define MVEBU_MPP_BITS 4 19562306a36Sopenharmony_ci#define MVEBU_MPP_MASK 0xf 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ciint mvebu_mmio_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid, 19862306a36Sopenharmony_ci unsigned long *config); 19962306a36Sopenharmony_ciint mvebu_mmio_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid, 20062306a36Sopenharmony_ci unsigned long config); 20162306a36Sopenharmony_ciint mvebu_regmap_mpp_ctrl_get(struct mvebu_mpp_ctrl_data *data, unsigned pid, 20262306a36Sopenharmony_ci unsigned long *config); 20362306a36Sopenharmony_ciint mvebu_regmap_mpp_ctrl_set(struct mvebu_mpp_ctrl_data *data, unsigned pid, 20462306a36Sopenharmony_ci unsigned long config); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ciint mvebu_pinctrl_probe(struct platform_device *pdev); 20762306a36Sopenharmony_ciint mvebu_pinctrl_simple_mmio_probe(struct platform_device *pdev); 20862306a36Sopenharmony_ciint mvebu_pinctrl_simple_regmap_probe(struct platform_device *pdev, 20962306a36Sopenharmony_ci struct device *syscon_dev, u32 offset); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci#endif 212