diff -drupN a/drivers/pinctrl/pinctrl-ingenic.h b/drivers/pinctrl/pinctrl-ingenic.h --- a/drivers/pinctrl/pinctrl-ingenic.h 1970-01-01 03:00:00.000000000 +0300 +++ b/drivers/pinctrl/pinctrl-ingenic.h 2022-06-09 05:02:33.000000000 +0300 @@ -0,0 +1,277 @@ +/* + * pinctrl/ingenic/pinctrl-ingenic.c + * + * Copyright 2015 Ingenic Semiconductor Co.,Ltd + * + * Author: cli + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __PINCTRL_INGENIC_H__ +#define __PINCTRL_INGENIC_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "core.h" + +enum gpio_function { + GPIO_FUNC_0 = 0x00, //0000, GPIO as function 0 / device 0 + GPIO_FUNC_1 = 0x01, //0001, GPIO as function 1 / device 1 + GPIO_FUNC_2 = 0x02, //0010, GPIO as function 2 / device 2 + GPIO_FUNC_3 = 0x03, //0011, GPIO as function 3 / device 3 + GPIO_OUTPUT0 = 0x04, //0100, GPIO output low level + GPIO_OUTPUT1 = 0x05, //0101, GPIO output high level + GPIO_INPUT = 0x06, //0110, GPIO as input + GPIO_INT_LO = 0x0c, //1100, Low Level trigger interrupt + GPIO_INT_HI = 0x0d, //1101, High Level trigger interrupt + GPIO_INT_FE = 0x0e, //1110, Fall Edge trigger interrupt + GPIO_INT_RE = 0x0f, //1111, Rise Edge trigger interrupt + GPIO_INT_RE_FE = 0x10, //Fall&Rise Edge trigger interrupt +}; + +#define PxOFFSET 0x1000 +#define PxPIN 0x00 /* PIN Level Register */ +#define PxINT 0x10 /* Port Interrupt Register */ +#define PxINTS 0x14 /* Port Interrupt Set Register */ +#define PxINTC 0x18 /* Port Interrupt Clear Register */ +#define PxMSK 0x20 /* Port Interrupt Mask Reg */ +#define PxMSKS 0x24 /* Port Interrupt Mask Set Reg */ +#define PxMSKC 0x28 /* Port Interrupt Mask Clear Reg */ +#define PxPAT1 0x30 /* Port Pattern 1 Set Reg. */ +#define PxPAT1S 0x34 /* Port Pattern 1 Set Reg. */ +#define PxPAT1C 0x38 /* Port Pattern 1 Clear Reg. */ +#define PxPAT0 0x40 /* Port Pattern 0 Register */ +#define PxPAT0S 0x44 /* Port Pattern 0 Set Register */ +#define PxPAT0C 0x48 /* Port Pattern 0 Clear Register */ +#define PxFLG 0x50 /* Port Flag Register */ +#define PxFLGC 0x58 /* Port Flag clear Register */ +//#define PxPEN 0x60 /* Port Pull Disable Register */ +//#define PxPENS 0x64 /* Port Pull Disable Set Register */ +//#define PxPENC 0x68 /* Port Pull Disable Clear Register */ + + +#define PxGFCFG0 0x70 /* Port Glitch Filter Configure 0 Register */ +#define PxGFCFG0S 0x74 /* Port Glitch Filter Configure 0 Set Register */ +#define PxGFCFG0C 0x78 /* Port Glitch Filter Configure 0 Clear Register */ +#define PxGFCFG1 0x80 /* Port Glitch Filter Configure 1 Register */ +#define PxGFCFG1S 0x84 /* Port Glitch Filter Configure 1 Set Register */ +#define PxGFCFG1C 0x88 /* Port Glitch Filter Configure 1 Clear Register */ +#define PxGFCFG2 0x90 /* Port Glitch Filter Configure 2 Register */ +#define PxGFCFG2S 0x94 /* Port Glitch Filter Configure 2 Set Register */ +#define PxGFCFG2C 0x98 /* Port Glitch Filter Configure 2 Clear Register */ +#define PxGFCFG3 0xa0 /* Port Glitch Filter Configure 3 Register */ +#define PxGFCFG3S 0xa4 /* Port Glitch Filter Configure 3 Set Register */ +#define PxGFCFG3C 0xa8 /* Port Glitch Filter Configure 3 Clear Register */ + + +#define PxGPDCR 0x100 /* Port IO Power Domain control Register */ +#define PxGPDCRS 0x104 /* Port IO Power Domain control Set Register */ +#define PxGPDCRC 0x108 /* Port IO Power Domain control Clear Register */ +#define PxPUEN 0x110 /* Port Pull-up status Register */ +#define PxPUENS 0x114 /* Port Pull-up status Set Register */ +#define PxPUENC 0x118 /* Port Pull-up status Clear Register */ +#define PxPDEN 0x120 /* Port Pull-down status Register */ +#define PxPDENS 0x124 /* Port Pull-down status Set Register */ +#define PxPDENC 0x128 /* Port Pull-down status Clear Register */ +#define PxPDS0 0x130 /* Port Driver-strength 0 Register */ +#define PxPDS0S 0x134 /* Port Driver-strength 0 Set Register */ +#define PxPDS0C 0x138 /* Port Driver-strength 0 Clear Register */ +#define PxPDS1 0x140 /* Port Driver-strength 1 Register */ +#define PxPDS1S 0x144 /* Port Driver-strength 1 Set Register */ +#define PxPDS1C 0x148 /* Port Driver-strength 1 Clear Register */ +#define PxPDS2 0x150 /* Port Driver-strength 2 Register */ +#define PxPDS2S 0x154 /* Port Driver-strength 2 Set Register */ +#define PxPDS2C 0x158 /* Port Driver-strength 2 Clear Register */ +#define PxPSLW 0x160 /* Port Slew Rate Register */ +#define PxPSLWS 0x164 /* Port Slew Rate Set Register */ +#define PxPSLWC 0x168 /* Port Slew Rate Clear Register */ +#define PxPSMT 0x170 /* Port Schmitt Trigger Register */ +#define PxPSMTS 0x174 /* Port Schmitt Trigger Set Register */ +#define PxPSMTC 0x178 /* Port Schmitt Trigger Clear Register */ + +/* Only PC use */ +#define PxPSMT1 0x180 /* Port Schmitt 1 Trigger Register */ +#define PxPSMT1S 0x184 /* Port Schmitt 1 Trigger Set Register */ +#define PxPSMT1C 0x188 /* Port Schmitt 1 Trigger Clear Register */ +#define PxPHE 0x190 /* Port Hold Enable Register */ +#define PxPHES 0x194 /* Port Hold Enable Set Register */ +#define PxPHEC 0x198 /* Port Hold Enable Clear Register */ + +#define PSHADOW_OFF 0x7000 +#define PZGIDLD 0xF0 /* GPIOZ Group ID to load */ + +#define PIN_NAMES_LEN 10 +#define MAX_GPIOS_ON_CHIP 32 +#define MAX_FUNCTIONS_ON_GPIO 4 +#define PIN_ARGS_FROM_INDEX 0 +#define PIN_ARGS_TO_INDEX 1 +#define PIN_ARGS_CFG_INDEX 2 + +static inline u32 pin_bitmap(u32 from, u32 to) +{ + if (to == 31) + return ~((1<<(from))-1); + return ((~((1<<(from))-1))&((1 << ((to)+1))-1)); +} + +static inline unsigned bit_count(unsigned v) +{ + unsigned int c; + for (c = 0; v; c++) + v &= v - 1; + return c; +} + +typedef enum ingenic_gpio_pm_arr { + PM_SLEEP_PULL = 0, /*sleep state*/ /*input pull*/ + PM_SLEEP_NOPULL, /*input no pull*/ + PM_SLEEP_PULL_UP, /*input pull*/ + PM_SLEEP_PULL_DOWN, /*input pull*/ + PM_SLEEP_HIZ, /*input hiz*/ + PM_SLEEP_HIGH, /*output high*/ + PM_SLEEP_LOW, /*output low*/ + PM_RESUME_INT, /*keep register for resume*/ + PM_RESUME_MSK, + PM_RESUME_PAT0, + PM_RESUME_PAT1, + PM_RESUME_PULL_UP, + PM_RESUME_PULL_DOWN, + PM_STATE_CNT, +} ingenic_gpio_pm_arr_t; + +/*ingenic gpio chip*/ +struct ingenic_gpio_chip { + struct gpio_chip gc; + char name[4]; /*name format "GPX"(X = 'A' + idx)*/ + u8 idx; /*gpio index of this chip*/ + const struct device_node *of_node; /*gpio chip device node*/ + int irq; /*gpio chip irq*/ + struct irq_domain *irq_domain; + struct pinctrl_gpio_range grange; + struct ingenic_pinctrl *pctl; + spinlock_t lock; /*gpio func write lock*/ + u32 *mcu_gpio_reg; /*used for gpio irq to mcu + mcu's pending register*/ + u32 used_pins_bitmap; /*bitmap of pins for been had requested*/ + u32 resume_pending; /*bitmap of pins wakeup pending when sleep*/ + u32 sleep_level; /*bitmap of pins level when sleep*/ + u32 filter_bitmap; /*bitmap of pins filter support*/ + u32 pull_bitmap; /*bitmap of pins pill support*/ + u32 wakeup_bitmap; /*bitmap of pins wakeup pins*/ + u32 pm_irq_bitmap; /*bitmap of pins used for irq sleep&resume*/ + u32 pm_bitmap[PM_STATE_CNT]; /*bitmap of pins used for sleep&resume*/ +}; + +#define gc_to_ingenic_gc(gpiochip) container_of(gpiochip, struct ingenic_gpio_chip, gc) + +/*function information*/ +struct ingenic_pinctrl_func { + const char *name; + struct device_node *of_node; /* function device node */ + const char **groups; /* all sub groups name*/ + u8 num_groups; /* num groups of this function */ +}; + +/*group information*/ +struct ingenic_pinctrl_group { + const char *name; + struct device_node *of_node; /* group device node */ + struct gpio_chip *gc; /* corresponding gpio chip*/ + unsigned *pins; /* Contained pins software gpio num*/ + u8 num_pins; /* num gpios of the set group*/ + u32 pinmux_bitmap; /* pins bitmap of this group*/ + enum gpio_function pinmux_func; /* pins function select of this group*/ +}; + +/*soc private data*/ +struct ingenic_priv { + bool have_shadow; /*support shadow register or not*/ + bool have_filter; /*support input pin filter of nor*/ + bool pull_tristate; /*support pullup/pulldown/hiz settable.*/ + int (*set_filter)(struct ingenic_gpio_chip *jzgc, /*set input pin filter function*/ + unsigned pin, + u16 filter); + ssize_t (*dump_filter)(struct ingenic_pinctrl *pctl, + char *buf, + ssize_t size); +}; + +struct ingenic_pinctrl { + void __iomem *io_base; + struct device_node *of_node; /*pinctrl device_node*/ + struct device *dev; + + spinlock_t shadow_lock; /*shadow register access lock*/ + struct ingenic_gpio_chip *gpio_chips; /*gpio chips of this pinctrl*/ + unsigned num_chips; /*num gpio chips*/ + unsigned total_pins; /*total pins of this pinctrl*/ + u32 *bitmap_priv; /*******private*******/ + + struct pinctrl_desc pctl_desc; + struct pinctrl_dev *pctl_dev; + + struct ingenic_pinctrl_group *groups; + unsigned num_groups; + + struct ingenic_pinctrl_func *functions; + unsigned num_funs; + + const struct ingenic_priv *priv; /*soc data*/ +}; + +static inline struct ingenic_pinctrl_group *find_group_by_of_node( + struct ingenic_pinctrl *pctl, struct device_node *np) +{ + int i; + for (i = 0; i < pctl->num_groups; i++) { + if (pctl->groups[i].of_node == np) + return &pctl->groups[i]; + } + return NULL; +} + +static inline struct ingenic_pinctrl_func *find_func_by_of_node( + struct ingenic_pinctrl *pctl, struct device_node *np) +{ + int i; + for (i = 0; i < pctl->num_funs; i++) { + if (pctl->functions[i].of_node == np) + return &pctl->functions[i]; + } + return NULL; +} + +static inline u32 ingenic_gpio_readl(struct ingenic_gpio_chip *chip, int offset) +{ + struct ingenic_pinctrl *pctl = chip->pctl; + return readl(pctl->io_base + (chip->idx * PxOFFSET) + offset); +} + +static inline void ingenic_gpio_writel(struct ingenic_gpio_chip *chip, int offset, int value) +{ + struct ingenic_pinctrl *pctl = chip->pctl; + writel(value , pctl->io_base + (chip->idx * PxOFFSET) + offset); +} + +static inline void ingenic_gpio_shadow_fill(struct ingenic_gpio_chip *chip, int offset, int value) +{ + struct ingenic_pinctrl *pctl = chip->pctl; + writel(value, pctl->io_base + PSHADOW_OFF + offset); +} + +static inline void ingenic_gpio_shadow_writel(struct ingenic_gpio_chip *chip) +{ + struct ingenic_pinctrl *pctl = chip->pctl; + writel(chip->idx, pctl->io_base + PSHADOW_OFF + PZGIDLD); +} +#endif /*__PINCTRL_INGENIC_H__*/