root/drivers/pinctrl/sunplus/sppctl.h
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * SP7021 Pin Controller Driver.
 * Copyright (C) Sunplus Tech / Tibbo Tech.
 */

#ifndef __SPPCTL_H__
#define __SPPCTL_H__

#include <linux/bits.h>
#include <linux/gpio/driver.h>
#include <linux/kernel.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/spinlock.h>
#include <linux/types.h>

#define SPPCTL_MODULE_NAME              "sppctl_sp7021"

#define SPPCTL_GPIO_OFF_FIRST           0x00
#define SPPCTL_GPIO_OFF_MASTER          0x00
#define SPPCTL_GPIO_OFF_OE              0x20
#define SPPCTL_GPIO_OFF_OUT             0x40
#define SPPCTL_GPIO_OFF_IN              0x60
#define SPPCTL_GPIO_OFF_IINV            0x80
#define SPPCTL_GPIO_OFF_OINV            0xa0
#define SPPCTL_GPIO_OFF_OD              0xc0

#define SPPCTL_FULLY_PINMUX_MASK_MASK   GENMASK(22, 16)
#define SPPCTL_FULLY_PINMUX_SEL_MASK    GENMASK(6, 0)
#define SPPCTL_FULLY_PINMUX_UPPER_SHIFT 8

/*
 * Mask-fields and control-fields of MOON registers of SP7021 are
 * arranged as shown below:
 *
 *  register |  mask-fields | control-fields
 * ----------+--------------+----------------
 *  base[0]  |  (31 : 16)   |   (15 : 0)
 *  base[1]  |  (31 : 24)   |   (15 : 0)
 *  base[2]  |  (31 : 24)   |   (15 : 0)
 *     :     |      :       |       :
 *
 * where mask-fields are used to protect control-fields from write-in
 * accidentally. Set the corresponding bits in the mask-field before
 * you write a value into a control-field.
 */
#define SPPCTL_MOON_REG_MASK_SHIFT      16
#define SPPCTL_SET_MOON_REG_BIT(bit)    (BIT((bit) + SPPCTL_MOON_REG_MASK_SHIFT) | BIT(bit))
#define SPPCTL_CLR_MOON_REG_BIT(bit)    BIT((bit) + SPPCTL_MOON_REG_MASK_SHIFT)

#define SPPCTL_IOP_CONFIGS              0xff

#define FNCE(n, r, o, bo, bl, g) { \
        .name = n, \
        .type = r, \
        .roff = o, \
        .boff = bo, \
        .blen = bl, \
        .grps = (g), \
        .gnum = ARRAY_SIZE(g), \
}

#define FNCN(n, r, o, bo, bl) { \
        .name = n, \
        .type = r, \
        .roff = o, \
        .boff = bo, \
        .blen = bl, \
        .grps = NULL, \
        .gnum = 0, \
}

#define EGRP(n, v, p) { \
        .name = n, \
        .gval = (v), \
        .pins = (p), \
        .pnum = ARRAY_SIZE(p), \
}

/**
 * enum mux_first_reg - Define modes of access of FIRST register
 * @mux_f_mux:  Set the corresponding pin to a fully-pinmux pin
 * @mux_f_gpio: Set the corresponding pin to a GPIO or IOP pin
 * @mux_f_keep: Don't change (keep intact)
 */
enum mux_first_reg {
        mux_f_mux = 0,
        mux_f_gpio = 1,
        mux_f_keep = 2,
};

/**
 * enum mux_master_reg - Define modes of access of MASTER register
 * @mux_m_iop:  Set the corresponding pin to an IO processor (IOP) pin
 * @mux_m_gpio: Set the corresponding pin to a digital GPIO pin
 * @mux_m_keep: Don't change (keep intact)
 */
enum mux_master_reg {
        mux_m_iop = 0,
        mux_m_gpio = 1,
        mux_m_keep = 2,
};

/**
 * enum pinmux_type - Define types of pinmux pins
 * @pinmux_type_fpmx: A fully-pinmux pin
 * @pinmux_type_grp:  A group-pinmux pin
 */
enum pinmux_type {
        pinmux_type_fpmx,
        pinmux_type_grp,
};

/**
 * struct grp2fp_map - A map storing indexes
 * @f_idx: an index to function table
 * @g_idx: an index to group table
 */
struct grp2fp_map {
        u16 f_idx;
        u16 g_idx;
};

struct sppctl_gpio_chip;

struct sppctl_pdata {
        void __iomem *moon2_base;       /* MOON2                                 */
        void __iomem *gpioxt_base;      /* MASTER, OE, OUT, IN, I_INV, O_INV, OD */
        void __iomem *first_base;       /* FIRST                                 */
        void __iomem *moon1_base;       /* MOON1               */

        struct pinctrl_desc pctl_desc;
        struct pinctrl_dev *pctl_dev;
        struct pinctrl_gpio_range pctl_grange;
        struct sppctl_gpio_chip *spp_gchip;

        char const **unq_grps;
        size_t unq_grps_sz;
        struct grp2fp_map *g2fp_maps;
};

struct sppctl_grp {
        const char * const name;
        const u8 gval;                  /* group number   */
        const unsigned * const pins;    /* list of pins   */
        const unsigned int pnum;        /* number of pins */
};

struct sppctl_func {
        const char * const name;
        const enum pinmux_type type;    /* function type          */
        const u8 roff;                  /* register offset        */
        const u8 boff;                  /* bit offset             */
        const u8 blen;                  /* bit length             */
        const struct sppctl_grp * const grps; /* list of groups   */
        const unsigned int gnum;        /* number of groups       */
};

extern const struct sppctl_func sppctl_list_funcs[];
extern const char * const sppctl_pmux_list_s[];
extern const char * const sppctl_gpio_list_s[];
extern const struct pinctrl_pin_desc sppctl_pins_all[];
extern const unsigned int sppctl_pins_gpio[];

extern const size_t sppctl_list_funcs_sz;
extern const size_t sppctl_pmux_list_sz;
extern const size_t sppctl_gpio_list_sz;
extern const size_t sppctl_pins_all_sz;

#endif