162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2014 MediaTek Inc.
462306a36Sopenharmony_ci * Author: Hongzhou.Yang <hongzhou.yang@mediatek.com>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __PINCTRL_MTK_COMMON_H
862306a36Sopenharmony_ci#define __PINCTRL_MTK_COMMON_H
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/pinctrl/pinctrl.h>
1162306a36Sopenharmony_ci#include <linux/regmap.h>
1262306a36Sopenharmony_ci#include <linux/pinctrl/pinconf-generic.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include "mtk-eint.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define NO_EINT_SUPPORT    255
1762306a36Sopenharmony_ci#define MT_EDGE_SENSITIVE           0
1862306a36Sopenharmony_ci#define MT_LEVEL_SENSITIVE          1
1962306a36Sopenharmony_ci#define EINT_DBNC_SET_DBNC_BITS     4
2062306a36Sopenharmony_ci#define EINT_DBNC_RST_BIT           (0x1 << 1)
2162306a36Sopenharmony_ci#define EINT_DBNC_SET_EN            (0x1 << 0)
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define MTK_PINCTRL_NOT_SUPPORT	(0xffff)
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistruct mtk_desc_function {
2662306a36Sopenharmony_ci	const char *name;
2762306a36Sopenharmony_ci	unsigned char muxval;
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistruct mtk_desc_eint {
3162306a36Sopenharmony_ci	unsigned char eintmux;
3262306a36Sopenharmony_ci	unsigned char eintnum;
3362306a36Sopenharmony_ci};
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistruct mtk_desc_pin {
3662306a36Sopenharmony_ci	struct pinctrl_pin_desc	pin;
3762306a36Sopenharmony_ci	const struct mtk_desc_eint eint;
3862306a36Sopenharmony_ci	const struct mtk_desc_function	*functions;
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#define MTK_PIN(_pin, _pad, _chip, _eint, ...)		\
4262306a36Sopenharmony_ci	{							\
4362306a36Sopenharmony_ci		.pin = _pin,					\
4462306a36Sopenharmony_ci		.eint = _eint,					\
4562306a36Sopenharmony_ci		.functions = (struct mtk_desc_function[]){	\
4662306a36Sopenharmony_ci			__VA_ARGS__, { } },			\
4762306a36Sopenharmony_ci	}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#define MTK_EINT_FUNCTION(_eintmux, _eintnum)				\
5062306a36Sopenharmony_ci	{							\
5162306a36Sopenharmony_ci		.eintmux = _eintmux,					\
5262306a36Sopenharmony_ci		.eintnum = _eintnum,					\
5362306a36Sopenharmony_ci	}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#define MTK_FUNCTION(_val, _name)				\
5662306a36Sopenharmony_ci	{							\
5762306a36Sopenharmony_ci		.muxval = _val,					\
5862306a36Sopenharmony_ci		.name = _name,					\
5962306a36Sopenharmony_ci	}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#define SET_ADDR(x, y)  (x + (y->devdata->port_align))
6262306a36Sopenharmony_ci#define CLR_ADDR(x, y)  (x + (y->devdata->port_align << 1))
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistruct mtk_pinctrl_group {
6562306a36Sopenharmony_ci	const char	*name;
6662306a36Sopenharmony_ci	unsigned long	config;
6762306a36Sopenharmony_ci	unsigned	pin;
6862306a36Sopenharmony_ci};
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/**
7162306a36Sopenharmony_ci * struct mtk_drv_group_desc - Provide driving group data.
7262306a36Sopenharmony_ci * @max_drv: The maximum current of this group.
7362306a36Sopenharmony_ci * @min_drv: The minimum current of this group.
7462306a36Sopenharmony_ci * @low_bit: The lowest bit of this group.
7562306a36Sopenharmony_ci * @high_bit: The highest bit of this group.
7662306a36Sopenharmony_ci * @step: The step current of this group.
7762306a36Sopenharmony_ci */
7862306a36Sopenharmony_cistruct mtk_drv_group_desc {
7962306a36Sopenharmony_ci	unsigned char min_drv;
8062306a36Sopenharmony_ci	unsigned char max_drv;
8162306a36Sopenharmony_ci	unsigned char low_bit;
8262306a36Sopenharmony_ci	unsigned char high_bit;
8362306a36Sopenharmony_ci	unsigned char step;
8462306a36Sopenharmony_ci};
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci#define MTK_DRV_GRP(_min, _max, _low, _high, _step)	\
8762306a36Sopenharmony_ci	{	\
8862306a36Sopenharmony_ci		.min_drv = _min,	\
8962306a36Sopenharmony_ci		.max_drv = _max,	\
9062306a36Sopenharmony_ci		.low_bit = _low,	\
9162306a36Sopenharmony_ci		.high_bit = _high,	\
9262306a36Sopenharmony_ci		.step = _step,		\
9362306a36Sopenharmony_ci	}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/**
9662306a36Sopenharmony_ci * struct mtk_pin_drv_grp - Provide each pin driving info.
9762306a36Sopenharmony_ci * @pin: The pin number.
9862306a36Sopenharmony_ci * @offset: The offset of driving register for this pin.
9962306a36Sopenharmony_ci * @bit: The bit of driving register for this pin.
10062306a36Sopenharmony_ci * @grp: The group for this pin belongs to.
10162306a36Sopenharmony_ci */
10262306a36Sopenharmony_cistruct mtk_pin_drv_grp {
10362306a36Sopenharmony_ci	unsigned short pin;
10462306a36Sopenharmony_ci	unsigned short offset;
10562306a36Sopenharmony_ci	unsigned char bit;
10662306a36Sopenharmony_ci	unsigned char grp;
10762306a36Sopenharmony_ci};
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci#define MTK_PIN_DRV_GRP(_pin, _offset, _bit, _grp)	\
11062306a36Sopenharmony_ci	{	\
11162306a36Sopenharmony_ci		.pin = _pin,	\
11262306a36Sopenharmony_ci		.offset = _offset,	\
11362306a36Sopenharmony_ci		.bit = _bit,	\
11462306a36Sopenharmony_ci		.grp = _grp,	\
11562306a36Sopenharmony_ci	}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci/**
11862306a36Sopenharmony_ci * struct mtk_pin_spec_pupd_set_samereg
11962306a36Sopenharmony_ci * - For special pins' pull up/down setting which resides in same register
12062306a36Sopenharmony_ci * @pin: The pin number.
12162306a36Sopenharmony_ci * @offset: The offset of special pull up/down setting register.
12262306a36Sopenharmony_ci * @pupd_bit: The pull up/down bit in this register.
12362306a36Sopenharmony_ci * @r0_bit: The r0 bit of pull resistor.
12462306a36Sopenharmony_ci * @r1_bit: The r1 bit of pull resistor.
12562306a36Sopenharmony_ci */
12662306a36Sopenharmony_cistruct mtk_pin_spec_pupd_set_samereg {
12762306a36Sopenharmony_ci	unsigned short pin;
12862306a36Sopenharmony_ci	unsigned short offset;
12962306a36Sopenharmony_ci	unsigned char pupd_bit;
13062306a36Sopenharmony_ci	unsigned char r1_bit;
13162306a36Sopenharmony_ci	unsigned char r0_bit;
13262306a36Sopenharmony_ci};
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci#define MTK_PIN_PUPD_SPEC_SR(_pin, _offset, _pupd, _r1, _r0)	\
13562306a36Sopenharmony_ci	{	\
13662306a36Sopenharmony_ci		.pin = _pin,	\
13762306a36Sopenharmony_ci		.offset = _offset,	\
13862306a36Sopenharmony_ci		.pupd_bit = _pupd,	\
13962306a36Sopenharmony_ci		.r1_bit = _r1,		\
14062306a36Sopenharmony_ci		.r0_bit = _r0,		\
14162306a36Sopenharmony_ci	}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci/**
14462306a36Sopenharmony_ci * struct mtk_pin_ies_set - For special pins' ies and smt setting.
14562306a36Sopenharmony_ci * @start: The start pin number of those special pins.
14662306a36Sopenharmony_ci * @end: The end pin number of those special pins.
14762306a36Sopenharmony_ci * @offset: The offset of special setting register.
14862306a36Sopenharmony_ci * @bit: The bit of special setting register.
14962306a36Sopenharmony_ci */
15062306a36Sopenharmony_cistruct mtk_pin_ies_smt_set {
15162306a36Sopenharmony_ci	unsigned short start;
15262306a36Sopenharmony_ci	unsigned short end;
15362306a36Sopenharmony_ci	unsigned short offset;
15462306a36Sopenharmony_ci	unsigned char bit;
15562306a36Sopenharmony_ci};
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci#define MTK_PIN_IES_SMT_SPEC(_start, _end, _offset, _bit)	\
15862306a36Sopenharmony_ci	{	\
15962306a36Sopenharmony_ci		.start = _start,	\
16062306a36Sopenharmony_ci		.end = _end,	\
16162306a36Sopenharmony_ci		.bit = _bit,	\
16262306a36Sopenharmony_ci		.offset = _offset,	\
16362306a36Sopenharmony_ci	}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistruct mtk_eint_offsets {
16662306a36Sopenharmony_ci	const char *name;
16762306a36Sopenharmony_ci	unsigned int  stat;
16862306a36Sopenharmony_ci	unsigned int  ack;
16962306a36Sopenharmony_ci	unsigned int  mask;
17062306a36Sopenharmony_ci	unsigned int  mask_set;
17162306a36Sopenharmony_ci	unsigned int  mask_clr;
17262306a36Sopenharmony_ci	unsigned int  sens;
17362306a36Sopenharmony_ci	unsigned int  sens_set;
17462306a36Sopenharmony_ci	unsigned int  sens_clr;
17562306a36Sopenharmony_ci	unsigned int  soft;
17662306a36Sopenharmony_ci	unsigned int  soft_set;
17762306a36Sopenharmony_ci	unsigned int  soft_clr;
17862306a36Sopenharmony_ci	unsigned int  pol;
17962306a36Sopenharmony_ci	unsigned int  pol_set;
18062306a36Sopenharmony_ci	unsigned int  pol_clr;
18162306a36Sopenharmony_ci	unsigned int  dom_en;
18262306a36Sopenharmony_ci	unsigned int  dbnc_ctrl;
18362306a36Sopenharmony_ci	unsigned int  dbnc_set;
18462306a36Sopenharmony_ci	unsigned int  dbnc_clr;
18562306a36Sopenharmony_ci	u8  port_mask;
18662306a36Sopenharmony_ci	u8  ports;
18762306a36Sopenharmony_ci};
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci/**
19062306a36Sopenharmony_ci * struct mtk_pinctrl_devdata - Provide HW GPIO related data.
19162306a36Sopenharmony_ci * @pins: An array describing all pins the pin controller affects.
19262306a36Sopenharmony_ci * @npins: The number of entries in @pins.
19362306a36Sopenharmony_ci *
19462306a36Sopenharmony_ci * @grp_desc: The driving group info.
19562306a36Sopenharmony_ci * @pin_drv_grp: The driving group for all pins.
19662306a36Sopenharmony_ci * @spec_ies: Special pin setting for input enable
19762306a36Sopenharmony_ci * @n_spec_ies: Number of entries in spec_ies
19862306a36Sopenharmony_ci * @spec_pupd: Special pull up/down setting
19962306a36Sopenharmony_ci * @n_spec_pupd: Number of entries in spec_pupd
20062306a36Sopenharmony_ci * @spec_smt: Special pin setting for schmitt
20162306a36Sopenharmony_ci * @n_spec_smt: Number of entries in spec_smt
20262306a36Sopenharmony_ci * @spec_pull_set: Each SoC may have special pins for pull up/down setting,
20362306a36Sopenharmony_ci *  these pins' pull setting are very different, they have separate pull
20462306a36Sopenharmony_ci *  up/down bit, R0 and R1 resistor bit, so they need special pull setting.
20562306a36Sopenharmony_ci *  If special setting is success, this should return 0, otherwise it should
20662306a36Sopenharmony_ci *  return non-zero value.
20762306a36Sopenharmony_ci * @spec_ies_smt_set: Some pins are irregular, their input enable and smt
20862306a36Sopenharmony_ci * control register are discontinuous, but they are mapping together. That
20962306a36Sopenharmony_ci * means when user set smt, input enable is set at the same time. So they
21062306a36Sopenharmony_ci * also need special control. If special control is success, this should
21162306a36Sopenharmony_ci * return 0, otherwise return non-zero value.
21262306a36Sopenharmony_ci * @spec_pinmux_set: In some cases, there are two pinmux functions share
21362306a36Sopenharmony_ci * the same value in the same segment of pinmux control register. If user
21462306a36Sopenharmony_ci * want to use one of the two functions, they need an extra bit setting to
21562306a36Sopenharmony_ci * select the right one.
21662306a36Sopenharmony_ci * @spec_dir_set: In very few SoCs, direction control registers are not
21762306a36Sopenharmony_ci * arranged continuously, they may be cut to parts. So they need special
21862306a36Sopenharmony_ci * dir setting.
21962306a36Sopenharmony_ci * @mt8365_set_clr_mode: In mt8365, some pins won't set correcty because they
22062306a36Sopenharmony_ci * need to use the main R/W register to read/update/write the modes instead of
22162306a36Sopenharmony_ci * the SET/CLR register.
22262306a36Sopenharmony_ci *
22362306a36Sopenharmony_ci * @dir_offset: The direction register offset.
22462306a36Sopenharmony_ci * @pullen_offset: The pull-up/pull-down enable register offset.
22562306a36Sopenharmony_ci * @pinmux_offset: The pinmux register offset.
22662306a36Sopenharmony_ci *
22762306a36Sopenharmony_ci * @type1_start: Some chips have two base addresses for pull select register,
22862306a36Sopenharmony_ci *  that means some pins use the first address and others use the second. This
22962306a36Sopenharmony_ci *  member record the start of pin number to use the second address.
23062306a36Sopenharmony_ci * @type1_end: The end of pin number to use the second address.
23162306a36Sopenharmony_ci *
23262306a36Sopenharmony_ci * @port_shf: The shift between two registers.
23362306a36Sopenharmony_ci * @port_mask: The mask of register.
23462306a36Sopenharmony_ci * @port_align: Provide clear register and set register step.
23562306a36Sopenharmony_ci */
23662306a36Sopenharmony_cistruct mtk_pinctrl_devdata {
23762306a36Sopenharmony_ci	const struct mtk_desc_pin	*pins;
23862306a36Sopenharmony_ci	unsigned int				npins;
23962306a36Sopenharmony_ci	const struct mtk_drv_group_desc	*grp_desc;
24062306a36Sopenharmony_ci	unsigned int	n_grp_cls;
24162306a36Sopenharmony_ci	const struct mtk_pin_drv_grp	*pin_drv_grp;
24262306a36Sopenharmony_ci	unsigned int	n_pin_drv_grps;
24362306a36Sopenharmony_ci	const struct mtk_pin_ies_smt_set *spec_ies;
24462306a36Sopenharmony_ci	unsigned int n_spec_ies;
24562306a36Sopenharmony_ci	const struct mtk_pin_spec_pupd_set_samereg *spec_pupd;
24662306a36Sopenharmony_ci	unsigned int n_spec_pupd;
24762306a36Sopenharmony_ci	const struct mtk_pin_ies_smt_set *spec_smt;
24862306a36Sopenharmony_ci	unsigned int n_spec_smt;
24962306a36Sopenharmony_ci	int (*spec_pull_set)(struct regmap *regmap,
25062306a36Sopenharmony_ci			const struct mtk_pinctrl_devdata *devdata,
25162306a36Sopenharmony_ci			unsigned int pin, bool isup, unsigned int r1r0);
25262306a36Sopenharmony_ci	int (*spec_ies_smt_set)(struct regmap *reg,
25362306a36Sopenharmony_ci			const struct mtk_pinctrl_devdata *devdata,
25462306a36Sopenharmony_ci			unsigned int pin, int value, enum pin_config_param arg);
25562306a36Sopenharmony_ci	void (*spec_pinmux_set)(struct regmap *reg, unsigned int pin,
25662306a36Sopenharmony_ci			unsigned int mode);
25762306a36Sopenharmony_ci	void (*spec_dir_set)(unsigned int *reg_addr, unsigned int pin);
25862306a36Sopenharmony_ci	int (*mt8365_set_clr_mode)(struct regmap *regmap,
25962306a36Sopenharmony_ci			unsigned int bit, unsigned int reg_pullen, unsigned int reg_pullsel,
26062306a36Sopenharmony_ci			bool enable, bool isup);
26162306a36Sopenharmony_ci	unsigned int dir_offset;
26262306a36Sopenharmony_ci	unsigned int ies_offset;
26362306a36Sopenharmony_ci	unsigned int smt_offset;
26462306a36Sopenharmony_ci	unsigned int pullen_offset;
26562306a36Sopenharmony_ci	unsigned int pullsel_offset;
26662306a36Sopenharmony_ci	unsigned int drv_offset;
26762306a36Sopenharmony_ci	unsigned int dout_offset;
26862306a36Sopenharmony_ci	unsigned int din_offset;
26962306a36Sopenharmony_ci	unsigned int pinmux_offset;
27062306a36Sopenharmony_ci	unsigned short type1_start;
27162306a36Sopenharmony_ci	unsigned short type1_end;
27262306a36Sopenharmony_ci	unsigned char  port_shf;
27362306a36Sopenharmony_ci	unsigned char  port_mask;
27462306a36Sopenharmony_ci	unsigned char  port_align;
27562306a36Sopenharmony_ci	struct mtk_eint_hw eint_hw;
27662306a36Sopenharmony_ci	struct mtk_eint_regs *eint_regs;
27762306a36Sopenharmony_ci	unsigned int mode_mask;
27862306a36Sopenharmony_ci	unsigned int mode_per_reg;
27962306a36Sopenharmony_ci	unsigned int mode_shf;
28062306a36Sopenharmony_ci};
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_cistruct mtk_pinctrl {
28362306a36Sopenharmony_ci	struct regmap	*regmap1;
28462306a36Sopenharmony_ci	struct regmap	*regmap2;
28562306a36Sopenharmony_ci	struct pinctrl_desc pctl_desc;
28662306a36Sopenharmony_ci	struct device           *dev;
28762306a36Sopenharmony_ci	struct gpio_chip	*chip;
28862306a36Sopenharmony_ci	struct mtk_pinctrl_group	*groups;
28962306a36Sopenharmony_ci	unsigned			ngroups;
29062306a36Sopenharmony_ci	const char          **grp_names;
29162306a36Sopenharmony_ci	struct pinctrl_dev      *pctl_dev;
29262306a36Sopenharmony_ci	const struct mtk_pinctrl_devdata  *devdata;
29362306a36Sopenharmony_ci	struct mtk_eint *eint;
29462306a36Sopenharmony_ci};
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ciint mtk_pctrl_init(struct platform_device *pdev,
29762306a36Sopenharmony_ci		const struct mtk_pinctrl_devdata *data,
29862306a36Sopenharmony_ci		struct regmap *regmap);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ciint mtk_pctrl_common_probe(struct platform_device *pdev);
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ciint mtk_pctrl_spec_pull_set_samereg(struct regmap *regmap,
30362306a36Sopenharmony_ci		const struct mtk_pinctrl_devdata *devdata,
30462306a36Sopenharmony_ci		unsigned int pin, bool isup, unsigned int r1r0);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ciint mtk_pconf_spec_set_ies_smt_range(struct regmap *regmap,
30762306a36Sopenharmony_ci		const struct mtk_pinctrl_devdata *devdata,
30862306a36Sopenharmony_ci		unsigned int pin, int value, enum pin_config_param arg);
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ciextern const struct dev_pm_ops mtk_eint_pm_ops;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci#endif /* __PINCTRL_MTK_COMMON_H */
313