162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * SP7021 Pin Controller Driver.
462306a36Sopenharmony_ci * Copyright (C) Sunplus Tech / Tibbo Tech.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __SPPCTL_H__
862306a36Sopenharmony_ci#define __SPPCTL_H__
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/bits.h>
1162306a36Sopenharmony_ci#include <linux/gpio/driver.h>
1262306a36Sopenharmony_ci#include <linux/kernel.h>
1362306a36Sopenharmony_ci#include <linux/pinctrl/pinctrl.h>
1462306a36Sopenharmony_ci#include <linux/spinlock.h>
1562306a36Sopenharmony_ci#include <linux/types.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define SPPCTL_MODULE_NAME		"sppctl_sp7021"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define SPPCTL_GPIO_OFF_FIRST		0x00
2062306a36Sopenharmony_ci#define SPPCTL_GPIO_OFF_MASTER		0x00
2162306a36Sopenharmony_ci#define SPPCTL_GPIO_OFF_OE		0x20
2262306a36Sopenharmony_ci#define SPPCTL_GPIO_OFF_OUT		0x40
2362306a36Sopenharmony_ci#define SPPCTL_GPIO_OFF_IN		0x60
2462306a36Sopenharmony_ci#define SPPCTL_GPIO_OFF_IINV		0x80
2562306a36Sopenharmony_ci#define SPPCTL_GPIO_OFF_OINV		0xa0
2662306a36Sopenharmony_ci#define SPPCTL_GPIO_OFF_OD		0xc0
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define SPPCTL_FULLY_PINMUX_MASK_MASK	GENMASK(22, 16)
2962306a36Sopenharmony_ci#define SPPCTL_FULLY_PINMUX_SEL_MASK	GENMASK(6, 0)
3062306a36Sopenharmony_ci#define SPPCTL_FULLY_PINMUX_UPPER_SHIFT	8
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/*
3362306a36Sopenharmony_ci * Mask-fields and control-fields of MOON registers of SP7021 are
3462306a36Sopenharmony_ci * arranged as shown below:
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci *  register |  mask-fields | control-fields
3762306a36Sopenharmony_ci * ----------+--------------+----------------
3862306a36Sopenharmony_ci *  base[0]  |  (31 : 16)   |   (15 : 0)
3962306a36Sopenharmony_ci *  base[1]  |  (31 : 24)   |   (15 : 0)
4062306a36Sopenharmony_ci *  base[2]  |  (31 : 24)   |   (15 : 0)
4162306a36Sopenharmony_ci *     :     |      :       |       :
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * where mask-fields are used to protect control-fields from write-in
4462306a36Sopenharmony_ci * accidentally. Set the corresponding bits in the mask-field before
4562306a36Sopenharmony_ci * you write a value into a control-field.
4662306a36Sopenharmony_ci */
4762306a36Sopenharmony_ci#define SPPCTL_MOON_REG_MASK_SHIFT	16
4862306a36Sopenharmony_ci#define SPPCTL_SET_MOON_REG_BIT(bit)	(BIT((bit) + SPPCTL_MOON_REG_MASK_SHIFT) | BIT(bit))
4962306a36Sopenharmony_ci#define SPPCTL_CLR_MOON_REG_BIT(bit)	BIT((bit) + SPPCTL_MOON_REG_MASK_SHIFT)
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci#define SPPCTL_IOP_CONFIGS		0xff
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#define FNCE(n, r, o, bo, bl, g) { \
5462306a36Sopenharmony_ci	.name = n, \
5562306a36Sopenharmony_ci	.type = r, \
5662306a36Sopenharmony_ci	.roff = o, \
5762306a36Sopenharmony_ci	.boff = bo, \
5862306a36Sopenharmony_ci	.blen = bl, \
5962306a36Sopenharmony_ci	.grps = (g), \
6062306a36Sopenharmony_ci	.gnum = ARRAY_SIZE(g), \
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci#define FNCN(n, r, o, bo, bl) { \
6462306a36Sopenharmony_ci	.name = n, \
6562306a36Sopenharmony_ci	.type = r, \
6662306a36Sopenharmony_ci	.roff = o, \
6762306a36Sopenharmony_ci	.boff = bo, \
6862306a36Sopenharmony_ci	.blen = bl, \
6962306a36Sopenharmony_ci	.grps = NULL, \
7062306a36Sopenharmony_ci	.gnum = 0, \
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define EGRP(n, v, p) { \
7462306a36Sopenharmony_ci	.name = n, \
7562306a36Sopenharmony_ci	.gval = (v), \
7662306a36Sopenharmony_ci	.pins = (p), \
7762306a36Sopenharmony_ci	.pnum = ARRAY_SIZE(p), \
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci/**
8162306a36Sopenharmony_ci * enum mux_first_reg - Define modes of access of FIRST register
8262306a36Sopenharmony_ci * @mux_f_mux:  Set the corresponding pin to a fully-pinmux pin
8362306a36Sopenharmony_ci * @mux_f_gpio: Set the corresponding pin to a GPIO or IOP pin
8462306a36Sopenharmony_ci * @mux_f_keep: Don't change (keep intact)
8562306a36Sopenharmony_ci */
8662306a36Sopenharmony_cienum mux_first_reg {
8762306a36Sopenharmony_ci	mux_f_mux = 0,
8862306a36Sopenharmony_ci	mux_f_gpio = 1,
8962306a36Sopenharmony_ci	mux_f_keep = 2,
9062306a36Sopenharmony_ci};
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci/**
9362306a36Sopenharmony_ci * enum mux_master_reg - Define modes of access of MASTER register
9462306a36Sopenharmony_ci * @mux_m_iop:  Set the corresponding pin to an IO processor (IOP) pin
9562306a36Sopenharmony_ci * @mux_m_gpio: Set the corresponding pin to a digital GPIO pin
9662306a36Sopenharmony_ci * @mux_m_keep: Don't change (keep intact)
9762306a36Sopenharmony_ci */
9862306a36Sopenharmony_cienum mux_master_reg {
9962306a36Sopenharmony_ci	mux_m_iop = 0,
10062306a36Sopenharmony_ci	mux_m_gpio = 1,
10162306a36Sopenharmony_ci	mux_m_keep = 2,
10262306a36Sopenharmony_ci};
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci/**
10562306a36Sopenharmony_ci * enum pinmux_type - Define types of pinmux pins
10662306a36Sopenharmony_ci * @pinmux_type_fpmx: A fully-pinmux pin
10762306a36Sopenharmony_ci * @pinmux_type_grp:  A group-pinmux pin
10862306a36Sopenharmony_ci */
10962306a36Sopenharmony_cienum pinmux_type {
11062306a36Sopenharmony_ci	pinmux_type_fpmx,
11162306a36Sopenharmony_ci	pinmux_type_grp,
11262306a36Sopenharmony_ci};
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci/**
11562306a36Sopenharmony_ci * struct grp2fp_map - A map storing indexes
11662306a36Sopenharmony_ci * @f_idx: an index to function table
11762306a36Sopenharmony_ci * @g_idx: an index to group table
11862306a36Sopenharmony_ci */
11962306a36Sopenharmony_cistruct grp2fp_map {
12062306a36Sopenharmony_ci	u16 f_idx;
12162306a36Sopenharmony_ci	u16 g_idx;
12262306a36Sopenharmony_ci};
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistruct sppctl_gpio_chip;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistruct sppctl_pdata {
12762306a36Sopenharmony_ci	void __iomem *moon2_base;	/* MOON2                                 */
12862306a36Sopenharmony_ci	void __iomem *gpioxt_base;	/* MASTER, OE, OUT, IN, I_INV, O_INV, OD */
12962306a36Sopenharmony_ci	void __iomem *first_base;	/* FIRST                                 */
13062306a36Sopenharmony_ci	void __iomem *moon1_base;	/* MOON1               */
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	struct pinctrl_desc pctl_desc;
13362306a36Sopenharmony_ci	struct pinctrl_dev *pctl_dev;
13462306a36Sopenharmony_ci	struct pinctrl_gpio_range pctl_grange;
13562306a36Sopenharmony_ci	struct sppctl_gpio_chip *spp_gchip;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	char const **unq_grps;
13862306a36Sopenharmony_ci	size_t unq_grps_sz;
13962306a36Sopenharmony_ci	struct grp2fp_map *g2fp_maps;
14062306a36Sopenharmony_ci};
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistruct sppctl_grp {
14362306a36Sopenharmony_ci	const char * const name;
14462306a36Sopenharmony_ci	const u8 gval;                  /* group number   */
14562306a36Sopenharmony_ci	const unsigned * const pins;    /* list of pins   */
14662306a36Sopenharmony_ci	const unsigned int pnum;        /* number of pins */
14762306a36Sopenharmony_ci};
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistruct sppctl_func {
15062306a36Sopenharmony_ci	const char * const name;
15162306a36Sopenharmony_ci	const enum pinmux_type type;    /* function type          */
15262306a36Sopenharmony_ci	const u8 roff;                  /* register offset        */
15362306a36Sopenharmony_ci	const u8 boff;                  /* bit offset             */
15462306a36Sopenharmony_ci	const u8 blen;                  /* bit length             */
15562306a36Sopenharmony_ci	const struct sppctl_grp * const grps; /* list of groups   */
15662306a36Sopenharmony_ci	const unsigned int gnum;        /* number of groups       */
15762306a36Sopenharmony_ci};
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ciextern const struct sppctl_func sppctl_list_funcs[];
16062306a36Sopenharmony_ciextern const char * const sppctl_pmux_list_s[];
16162306a36Sopenharmony_ciextern const char * const sppctl_gpio_list_s[];
16262306a36Sopenharmony_ciextern const struct pinctrl_pin_desc sppctl_pins_all[];
16362306a36Sopenharmony_ciextern const unsigned int sppctl_pins_gpio[];
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ciextern const size_t sppctl_list_funcs_sz;
16662306a36Sopenharmony_ciextern const size_t sppctl_pmux_list_sz;
16762306a36Sopenharmony_ciextern const size_t sppctl_gpio_list_sz;
16862306a36Sopenharmony_ciextern const size_t sppctl_pins_all_sz;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci#endif
171