firmware/br-ext-chip-ingenic/board/t40/kernel/patches/00000-drivers_pinctrl_pinct...

282 lines
11 KiB
Diff

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 <chen.li@inegnic.com>
+ *
+ * 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 <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/irqdomain.h>
+#include <linux/gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <dt-bindings/pinctrl/ingenic-pinctrl.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#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__*/