mirror of https://github.com/OpenIPC/firmware.git
282 lines
11 KiB
Diff
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__*/
|