This is the bulk of pin control changes for v4.18.
No core changes this time! Just a calm all-over-the-place drivers, updates and fixes cycle as it seems. New drivers/subdrivers: - Actions Semiconductor S900 driver with more Actions variants for S700, S500 in the pipe. Also generic GPIO support on top of the same driver and IRQ support is in the pipe. - Renesas r8a77470 PFC support. - Renesas r8a77990 PFC support. - Allwinner Sunxi H6 R_PIO support. - Rockchip PX30 support. - Meson Meson8m2 support. - Remove support for the ill-fated Samsung Exynos 5440 SoC. Improvements: - Context save/restore support in pinctrl-single. - External interrupt support for the Mediatek MT7622. - Qualcomm ACPI HID QCOM8002 supported. Fixes: - Fix up suspend/resume support for Exynos 5433. - Fix Strago DMI fixes on the Intel Cherryview. -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJbGOinAAoJEEEQszewGV1zogcQAIaSUz5bwGhP+FmmIiHpJlGH MxpdIqu5cMg4e4IUA8jjB70xXgA48CLhAv/r6KjUIoF4G5wkDQS3vH+kIesdVbbK pmF1LvyJ0PfB6sWdUx98gevCtI0ok4lSvIr9fSGQjcZt5U6Ln4hrhs34Hz12+e3K BLhW+O1k1BbYEiPPpddgKL0F7cbEabx9wS056VjJKKbUxYMVprzaB4m/pbLHKrjW vgFis/HQyEEC0erdLCRxF4rpzoTYGhE5XaOygZjjjdawU3wa+RyndNAlxhTwSFS4 W7ZJ41QRKM2vedlxUYpZk5hRWxsLF3cAeBfdtJpvavsqJLZutcuhw1vRTo8+WZ0k X1KdtZmYnxOY+qoyg36uHf+kimcMUAHNKGVSoDxpbUEeJ+nSb7BD9YWfBlRikuq8 R0QDZ8+YxhqEt8np+SJx984Gnh2Rhxw9sWNJpJt609Nlp6aqTvmzuQbJPchHNk95 KNeFU/PZc0jPQLQVnrlHKQ/UM7PnnOYpGzloq+LBZpnHOHZJW1S8iOvJcPfay2eA x/zZfj8/IaXELa7Bh8kZrI2UIxvxvVtF+zfRMbupVRr8+CqDOz3m/g9G298NWv5+ SBnJJcLZikxgMvOupH3FKfdgQ7tgfJrXzKynasUm33Ex90cst5REFSlLVhzU0CLb 2TtsB46XFugt3czmKsi9 =6On2 -----END PGP SIGNATURE----- Merge tag 'pinctrl-v4.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl Pull pin control updates from Linus Walleij: "This is the bulk of pin control changes for v4.18. No core changes this time! Just a calm all-over-the-place drivers, updates and fixes cycle as it seems. New drivers/subdrivers: - Actions Semiconductor S900 driver with more Actions variants for S700, S500 in the pipe. Also generic GPIO support on top of the same driver and IRQ support is in the pipe. - Renesas r8a77470 PFC support. - Renesas r8a77990 PFC support. - Allwinner Sunxi H6 R_PIO support. - Rockchip PX30 support. - Meson Meson8m2 support. - Remove support for the ill-fated Samsung Exynos 5440 SoC. Improvements: - Context save/restore support in pinctrl-single. - External interrupt support for the Mediatek MT7622. - Qualcomm ACPI HID QCOM8002 supported. Fixes: - Fix up suspend/resume support for Exynos 5433. - Fix Strago DMI fixes on the Intel Cherryview" * tag 'pinctrl-v4.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (72 commits) pinctrl: cherryview: limit Strago DMI workarounds to version 1.0 pinctrl: at91-pio4: add missing of_node_put pinctrl: armada-37xx: Fix spurious irq management gpiolib: discourage gpiochip_add_pin[group]_range for DT pinctrls pinctrl: msm: fix gpio-hog related boot issues MAINTAINERS: update entry for Mediatek pin controller pinctrl: mediatek: remove unused fields in struct mtk_eint_hw pinctrl: mediatek: use generic EINT register maps for each SoC pinctrl: mediatek: add EINT support to MT7622 SoC pinctrl: mediatek: refactor EINT related code for all MediaTek pinctrl can fit dt-bindings: pinctrl: add external interrupt support to MT7622 pinctrl pinctrl: freescale: Switch to SPDX identifier pinctrl: samsung: Fix suspend/resume for Exynos5433 GPF1..5 banks pinctrl: sh-pfc: rcar-gen3: Fix grammar in static pin comments pinctrl: sh-pfc: r8a77965: Add I2C pin support pinctrl: sh-pfc: r8a77990: Add EthernetAVB pins, groups and functions pinctrl: sh-pfc: r8a77990: Add I2C{1,2,4,5,6,7} pins, groups and functions pinctrl: sh-pfc: r8a77990: Add SCIF pins, groups and functions pinctrl: sh-pfc: r8a77990: Add bias pinconf support pinctrl: sh-pfc: Initial R8A77990 PFC support ...
This commit is contained in:
commit
edb2a385ec
|
@ -8,6 +8,17 @@ Required Properties:
|
|||
- reg: Should contain the register base address and size of
|
||||
the pin controller.
|
||||
- clocks: phandle of the clock feeding the pin controller
|
||||
- gpio-controller: Marks the device node as a GPIO controller.
|
||||
- gpio-ranges: Specifies the mapping between gpio controller and
|
||||
pin-controller pins.
|
||||
- #gpio-cells: Should be two. The first cell is the gpio pin number
|
||||
and the second cell is used for optional parameters.
|
||||
- interrupt-controller: Marks the device node as an interrupt controller.
|
||||
- #interrupt-cells: Specifies the number of cells needed to encode an
|
||||
interrupt. Shall be set to 2. The first cell
|
||||
defines the interrupt number, the second encodes
|
||||
the trigger flags described in
|
||||
bindings/interrupt-controller/interrupts.txt
|
||||
|
||||
Please refer to pinctrl-bindings.txt in this directory for details of the
|
||||
common pinctrl bindings used by client devices, including the meaning of the
|
||||
|
@ -164,6 +175,11 @@ Example:
|
|||
compatible = "actions,s900-pinctrl";
|
||||
reg = <0x0 0xe01b0000 0x0 0x1000>;
|
||||
clocks = <&cmu CLK_GPIO>;
|
||||
gpio-controller;
|
||||
gpio-ranges = <&pinctrl 0 0 146>;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
uart2-default: uart2-default {
|
||||
pinmux {
|
||||
|
|
|
@ -28,6 +28,7 @@ Required properties:
|
|||
"allwinner,sun50i-a64-r-pinctrl"
|
||||
"allwinner,sun50i-h5-pinctrl"
|
||||
"allwinner,sun50i-h6-pinctrl"
|
||||
"allwinner,sun50i-h6-r-pinctrl"
|
||||
"nextthing,gr8-pinctrl"
|
||||
|
||||
- reg: Should contain the register physical address and length for the
|
||||
|
|
|
@ -36,6 +36,24 @@ listed. In other words, a subnode that lists only a mux function implies no
|
|||
information about any pull configuration. Similarly, a subnode that lists only
|
||||
a pul parameter implies no information about the mux function.
|
||||
|
||||
The BCM2835 pin configuration and multiplexing supports the generic bindings.
|
||||
For details on each properties, you can refer to ./pinctrl-bindings.txt.
|
||||
|
||||
Required sub-node properties:
|
||||
- pins
|
||||
- function
|
||||
|
||||
Optional sub-node properties:
|
||||
- bias-disable
|
||||
- bias-pull-up
|
||||
- bias-pull-down
|
||||
- output-high
|
||||
- output-low
|
||||
|
||||
Legacy pin configuration and multiplexing binding:
|
||||
*** (Its use is deprecated, use generic multiplexing and configuration
|
||||
bindings instead)
|
||||
|
||||
Required subnode-properties:
|
||||
- brcm,pins: An array of cells. Each cell contains the ID of a pin. Valid IDs
|
||||
are the integer GPIO IDs; 0==GPIO0, 1==GPIO1, ... 53==GPIO53.
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
Required properties for the root node:
|
||||
- compatible: one of "amlogic,meson8-cbus-pinctrl"
|
||||
"amlogic,meson8b-cbus-pinctrl"
|
||||
"amlogic,meson8m2-cbus-pinctrl"
|
||||
"amlogic,meson8-aobus-pinctrl"
|
||||
"amlogic,meson8b-aobus-pinctrl"
|
||||
"amlogic,meson8m2-aobus-pinctrl"
|
||||
"amlogic,meson-gxbb-periphs-pinctrl"
|
||||
"amlogic,meson-gxbb-aobus-pinctrl"
|
||||
"amlogic,meson-gxl-periphs-pinctrl"
|
||||
|
|
|
@ -18,7 +18,9 @@ Required properties:
|
|||
removed.
|
||||
- #gpio-cells : Should be two.
|
||||
- first cell is the pin number
|
||||
- second cell is used to specify flags. Flags are currently unused.
|
||||
- second cell is used to specify flags as described in
|
||||
'Documentation/devicetree/bindings/gpio/gpio.txt'. Allowed values defined by
|
||||
'include/dt-bindings/gpio/gpio.h' (e.g. GPIO_ACTIVE_LOW).
|
||||
- gpio-controller : Marks the device node as a GPIO controller.
|
||||
- reg : For an address on its bus. I2C uses this a the I2C address of the chip.
|
||||
SPI uses this to specify the chipselect line which the chip is
|
||||
|
|
|
@ -9,6 +9,16 @@ Required properties for the root node:
|
|||
- #gpio-cells: Should be two. The first cell is the pin number and the
|
||||
second is the GPIO flags.
|
||||
|
||||
Optional properties:
|
||||
- interrupt-controller : Marks the device node as an interrupt controller
|
||||
|
||||
If the property interrupt-controller is defined, following property is required
|
||||
- reg-names: A string describing the "reg" entries. Must contain "eint".
|
||||
- interrupts : The interrupt output from the controller.
|
||||
- #interrupt-cells: Should be two.
|
||||
- interrupt-parent: Phandle of the interrupt parent to which the external
|
||||
GPIO interrupts are forwarded to.
|
||||
|
||||
Please refer to pinctrl-bindings.txt in this directory for details of the
|
||||
common pinctrl bindings used by client devices, including the meaning of the
|
||||
phrase "pin configuration node".
|
||||
|
|
|
@ -15,6 +15,7 @@ Required Properties:
|
|||
- "renesas,pfc-r8a7740": for R8A7740 (R-Mobile A1) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7743": for R8A7743 (RZ/G1M) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7745": for R8A7745 (RZ/G1E) compatible pin-controller.
|
||||
- "renesas,pfc-r8a77470": for R8A77470 (RZ/G1C) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7778": for R8A7778 (R-Car M1) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7779": for R8A7779 (R-Car H1) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7790": for R8A7790 (R-Car H2) compatible pin-controller.
|
||||
|
@ -27,6 +28,7 @@ Required Properties:
|
|||
- "renesas,pfc-r8a77965": for R8A77965 (R-Car M3-N) compatible pin-controller.
|
||||
- "renesas,pfc-r8a77970": for R8A77970 (R-Car V3M) compatible pin-controller.
|
||||
- "renesas,pfc-r8a77980": for R8A77980 (R-Car V3H) compatible pin-controller.
|
||||
- "renesas,pfc-r8a77990": for R8A77990 (R-Car E3) compatible pin-controller.
|
||||
- "renesas,pfc-r8a77995": for R8A77995 (R-Car D3) compatible pin-controller.
|
||||
- "renesas,pfc-sh73a0": for SH73A0 (SH-Mobile AG5) compatible pin-controller.
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ defined as gpio sub-nodes of the pinmux controller.
|
|||
|
||||
Required properties for iomux controller:
|
||||
- compatible: should be
|
||||
"rockchip,px30-pinctrl": for Rockchip PX30
|
||||
"rockchip,rv1108-pinctrl": for Rockchip RV1108
|
||||
"rockchip,rk2928-pinctrl": for Rockchip RK2928
|
||||
"rockchip,rk3066a-pinctrl": for Rockchip RK3066a
|
||||
|
|
|
@ -1135,10 +1135,12 @@ F: arch/arm/mach-actions/
|
|||
F: arch/arm/boot/dts/owl-*
|
||||
F: arch/arm64/boot/dts/actions/
|
||||
F: drivers/clocksource/owl-*
|
||||
F: drivers/pinctrl/actions/*
|
||||
F: drivers/soc/actions/
|
||||
F: include/dt-bindings/power/owl-*
|
||||
F: include/linux/soc/actions/
|
||||
F: Documentation/devicetree/bindings/arm/actions.txt
|
||||
F: Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.txt
|
||||
F: Documentation/devicetree/bindings/power/actions,owl-sps.txt
|
||||
F: Documentation/devicetree/bindings/timer/actions,owl-timer.txt
|
||||
|
||||
|
@ -11225,6 +11227,7 @@ L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
|
|||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt
|
||||
F: Documentation/devicetree/bindings/pinctrl/pinctrl-mt7622.txt
|
||||
F: drivers/pinctrl/mediatek/mtk-eint.*
|
||||
F: drivers/pinctrl/mediatek/pinctrl-mtk-common.*
|
||||
F: drivers/pinctrl/mediatek/pinctrl-mt2701.c
|
||||
F: drivers/pinctrl/mediatek/pinctrl-mt7622.c
|
||||
|
|
|
@ -2078,6 +2078,11 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_config);
|
|||
* @pctldev: the pin controller to map to
|
||||
* @gpio_offset: the start offset in the current gpio_chip number space
|
||||
* @pin_group: name of the pin group inside the pin controller
|
||||
*
|
||||
* Calling this function directly from a DeviceTree-supported
|
||||
* pinctrl driver is DEPRECATED. Please see Section 2.1 of
|
||||
* Documentation/devicetree/bindings/gpio/gpio.txt on how to
|
||||
* bind pinctrl and gpio drivers via the "gpio-ranges" property.
|
||||
*/
|
||||
int gpiochip_add_pingroup_range(struct gpio_chip *chip,
|
||||
struct pinctrl_dev *pctldev,
|
||||
|
@ -2131,6 +2136,11 @@ EXPORT_SYMBOL_GPL(gpiochip_add_pingroup_range);
|
|||
*
|
||||
* Returns:
|
||||
* 0 on success, or a negative error-code on failure.
|
||||
*
|
||||
* Calling this function directly from a DeviceTree-supported
|
||||
* pinctrl driver is DEPRECATED. Please see Section 2.1 of
|
||||
* Documentation/devicetree/bindings/gpio/gpio.txt on how to
|
||||
* bind pinctrl and gpio drivers via the "gpio-ranges" property.
|
||||
*/
|
||||
int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
|
||||
unsigned int gpio_offset, unsigned int pin_offset,
|
||||
|
|
|
@ -337,6 +337,7 @@ config PINCTRL_OCELOT
|
|||
select GENERIC_PINMUX_FUNCTIONS
|
||||
select REGMAP_MMIO
|
||||
|
||||
source "drivers/pinctrl/actions/Kconfig"
|
||||
source "drivers/pinctrl/aspeed/Kconfig"
|
||||
source "drivers/pinctrl/bcm/Kconfig"
|
||||
source "drivers/pinctrl/berlin/Kconfig"
|
||||
|
|
|
@ -43,6 +43,7 @@ obj-$(CONFIG_PINCTRL_INGENIC) += pinctrl-ingenic.o
|
|||
obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o
|
||||
obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o
|
||||
|
||||
obj-y += actions/
|
||||
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
|
||||
obj-y += bcm/
|
||||
obj-$(CONFIG_PINCTRL_BERLIN) += berlin/
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
config PINCTRL_OWL
|
||||
bool "Actions Semi OWL pinctrl driver"
|
||||
depends on (ARCH_ACTIONS || COMPILE_TEST) && OF
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
select GENERIC_PINCONF
|
||||
select GPIOLIB
|
||||
help
|
||||
Say Y here to enable Actions Semi OWL pinctrl driver
|
||||
|
||||
config PINCTRL_S900
|
||||
bool "Actions Semi S900 pinctrl driver"
|
||||
depends on PINCTRL_OWL
|
||||
help
|
||||
Say Y here to enable Actions Semi S900 pinctrl driver
|
|
@ -0,0 +1,2 @@
|
|||
obj-$(CONFIG_PINCTRL_OWL) += pinctrl-owl.o
|
||||
obj-$(CONFIG_PINCTRL_S900) += pinctrl-s900.o
|
|
@ -0,0 +1,785 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* OWL SoC's Pinctrl driver
|
||||
*
|
||||
* Copyright (c) 2014 Actions Semi Inc.
|
||||
* Author: David Liu <liuwei@actions-semi.com>
|
||||
*
|
||||
* Copyright (c) 2018 Linaro Ltd.
|
||||
* Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "../core.h"
|
||||
#include "../pinctrl-utils.h"
|
||||
#include "pinctrl-owl.h"
|
||||
|
||||
/**
|
||||
* struct owl_pinctrl - pinctrl state of the device
|
||||
* @dev: device handle
|
||||
* @pctrldev: pinctrl handle
|
||||
* @chip: gpio chip
|
||||
* @lock: spinlock to protect registers
|
||||
* @soc: reference to soc_data
|
||||
* @base: pinctrl register base address
|
||||
*/
|
||||
struct owl_pinctrl {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pctrldev;
|
||||
struct gpio_chip chip;
|
||||
raw_spinlock_t lock;
|
||||
struct clk *clk;
|
||||
const struct owl_pinctrl_soc_data *soc;
|
||||
void __iomem *base;
|
||||
};
|
||||
|
||||
static void owl_update_bits(void __iomem *base, u32 mask, u32 val)
|
||||
{
|
||||
u32 reg_val;
|
||||
|
||||
reg_val = readl_relaxed(base);
|
||||
|
||||
reg_val = (reg_val & ~mask) | (val & mask);
|
||||
|
||||
writel_relaxed(reg_val, base);
|
||||
}
|
||||
|
||||
static u32 owl_read_field(struct owl_pinctrl *pctrl, u32 reg,
|
||||
u32 bit, u32 width)
|
||||
{
|
||||
u32 tmp, mask;
|
||||
|
||||
tmp = readl_relaxed(pctrl->base + reg);
|
||||
mask = (1 << width) - 1;
|
||||
|
||||
return (tmp >> bit) & mask;
|
||||
}
|
||||
|
||||
static void owl_write_field(struct owl_pinctrl *pctrl, u32 reg, u32 arg,
|
||||
u32 bit, u32 width)
|
||||
{
|
||||
u32 mask;
|
||||
|
||||
mask = (1 << width) - 1;
|
||||
mask = mask << bit;
|
||||
|
||||
owl_update_bits(pctrl->base + reg, mask, (arg << bit));
|
||||
}
|
||||
|
||||
static int owl_get_groups_count(struct pinctrl_dev *pctrldev)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrldev);
|
||||
|
||||
return pctrl->soc->ngroups;
|
||||
}
|
||||
|
||||
static const char *owl_get_group_name(struct pinctrl_dev *pctrldev,
|
||||
unsigned int group)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrldev);
|
||||
|
||||
return pctrl->soc->groups[group].name;
|
||||
}
|
||||
|
||||
static int owl_get_group_pins(struct pinctrl_dev *pctrldev,
|
||||
unsigned int group,
|
||||
const unsigned int **pins,
|
||||
unsigned int *num_pins)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrldev);
|
||||
|
||||
*pins = pctrl->soc->groups[group].pads;
|
||||
*num_pins = pctrl->soc->groups[group].npads;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void owl_pin_dbg_show(struct pinctrl_dev *pctrldev,
|
||||
struct seq_file *s,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrldev);
|
||||
|
||||
seq_printf(s, "%s", dev_name(pctrl->dev));
|
||||
}
|
||||
|
||||
static struct pinctrl_ops owl_pinctrl_ops = {
|
||||
.get_groups_count = owl_get_groups_count,
|
||||
.get_group_name = owl_get_group_name,
|
||||
.get_group_pins = owl_get_group_pins,
|
||||
.pin_dbg_show = owl_pin_dbg_show,
|
||||
.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
|
||||
.dt_free_map = pinctrl_utils_free_map,
|
||||
};
|
||||
|
||||
static int owl_get_funcs_count(struct pinctrl_dev *pctrldev)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrldev);
|
||||
|
||||
return pctrl->soc->nfunctions;
|
||||
}
|
||||
|
||||
static const char *owl_get_func_name(struct pinctrl_dev *pctrldev,
|
||||
unsigned int function)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrldev);
|
||||
|
||||
return pctrl->soc->functions[function].name;
|
||||
}
|
||||
|
||||
static int owl_get_func_groups(struct pinctrl_dev *pctrldev,
|
||||
unsigned int function,
|
||||
const char * const **groups,
|
||||
unsigned int * const num_groups)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrldev);
|
||||
|
||||
*groups = pctrl->soc->functions[function].groups;
|
||||
*num_groups = pctrl->soc->functions[function].ngroups;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int get_group_mfp_mask_val(const struct owl_pingroup *g,
|
||||
int function,
|
||||
u32 *mask,
|
||||
u32 *val)
|
||||
{
|
||||
int id;
|
||||
u32 option_num;
|
||||
u32 option_mask;
|
||||
|
||||
for (id = 0; id < g->nfuncs; id++) {
|
||||
if (g->funcs[id] == function)
|
||||
break;
|
||||
}
|
||||
if (WARN_ON(id == g->nfuncs))
|
||||
return -EINVAL;
|
||||
|
||||
option_num = (1 << g->mfpctl_width);
|
||||
if (id > option_num)
|
||||
id -= option_num;
|
||||
|
||||
option_mask = option_num - 1;
|
||||
*mask = (option_mask << g->mfpctl_shift);
|
||||
*val = (id << g->mfpctl_shift);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int owl_set_mux(struct pinctrl_dev *pctrldev,
|
||||
unsigned int function,
|
||||
unsigned int group)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrldev);
|
||||
const struct owl_pingroup *g;
|
||||
unsigned long flags;
|
||||
u32 val, mask;
|
||||
|
||||
g = &pctrl->soc->groups[group];
|
||||
|
||||
if (get_group_mfp_mask_val(g, function, &mask, &val))
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
owl_update_bits(pctrl->base + g->mfpctl_reg, mask, val);
|
||||
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pinmux_ops owl_pinmux_ops = {
|
||||
.get_functions_count = owl_get_funcs_count,
|
||||
.get_function_name = owl_get_func_name,
|
||||
.get_function_groups = owl_get_func_groups,
|
||||
.set_mux = owl_set_mux,
|
||||
};
|
||||
|
||||
static int owl_pad_pinconf_reg(const struct owl_padinfo *info,
|
||||
unsigned int param,
|
||||
u32 *reg,
|
||||
u32 *bit,
|
||||
u32 *width)
|
||||
{
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_BUS_HOLD:
|
||||
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
if (!info->pullctl)
|
||||
return -EINVAL;
|
||||
*reg = info->pullctl->reg;
|
||||
*bit = info->pullctl->shift;
|
||||
*width = info->pullctl->width;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
if (!info->st)
|
||||
return -EINVAL;
|
||||
*reg = info->st->reg;
|
||||
*bit = info->st->shift;
|
||||
*width = info->st->width;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int owl_pad_pinconf_arg2val(const struct owl_padinfo *info,
|
||||
unsigned int param,
|
||||
u32 *arg)
|
||||
{
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_BUS_HOLD:
|
||||
*arg = OWL_PINCONF_PULL_HOLD;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
|
||||
*arg = OWL_PINCONF_PULL_HIZ;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
*arg = OWL_PINCONF_PULL_DOWN;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
*arg = OWL_PINCONF_PULL_UP;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
*arg = (*arg >= 1 ? 1 : 0);
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int owl_pad_pinconf_val2arg(const struct owl_padinfo *padinfo,
|
||||
unsigned int param,
|
||||
u32 *arg)
|
||||
{
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_BUS_HOLD:
|
||||
*arg = *arg == OWL_PINCONF_PULL_HOLD;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
|
||||
*arg = *arg == OWL_PINCONF_PULL_HIZ;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
*arg = *arg == OWL_PINCONF_PULL_DOWN;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
*arg = *arg == OWL_PINCONF_PULL_UP;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
*arg = *arg == 1;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int owl_pin_config_get(struct pinctrl_dev *pctrldev,
|
||||
unsigned int pin,
|
||||
unsigned long *config)
|
||||
{
|
||||
int ret = 0;
|
||||
struct owl_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrldev);
|
||||
const struct owl_padinfo *info;
|
||||
unsigned int param = pinconf_to_config_param(*config);
|
||||
u32 reg, bit, width, arg;
|
||||
|
||||
info = &pctrl->soc->padinfo[pin];
|
||||
|
||||
ret = owl_pad_pinconf_reg(info, param, ®, &bit, &width);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
arg = owl_read_field(pctrl, reg, bit, width);
|
||||
|
||||
ret = owl_pad_pinconf_val2arg(info, param, &arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*config = pinconf_to_config_packed(param, arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int owl_pin_config_set(struct pinctrl_dev *pctrldev,
|
||||
unsigned int pin,
|
||||
unsigned long *configs,
|
||||
unsigned int num_configs)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrldev);
|
||||
const struct owl_padinfo *info;
|
||||
unsigned long flags;
|
||||
unsigned int param;
|
||||
u32 reg, bit, width, arg;
|
||||
int ret, i;
|
||||
|
||||
info = &pctrl->soc->padinfo[pin];
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
param = pinconf_to_config_param(configs[i]);
|
||||
arg = pinconf_to_config_argument(configs[i]);
|
||||
|
||||
ret = owl_pad_pinconf_reg(info, param, ®, &bit, &width);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = owl_pad_pinconf_arg2val(info, param, &arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
owl_write_field(pctrl, reg, arg, bit, width);
|
||||
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int owl_group_pinconf_reg(const struct owl_pingroup *g,
|
||||
unsigned int param,
|
||||
u32 *reg,
|
||||
u32 *bit,
|
||||
u32 *width)
|
||||
{
|
||||
switch (param) {
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
if (g->drv_reg < 0)
|
||||
return -EINVAL;
|
||||
*reg = g->drv_reg;
|
||||
*bit = g->drv_shift;
|
||||
*width = g->drv_width;
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
if (g->sr_reg < 0)
|
||||
return -EINVAL;
|
||||
*reg = g->sr_reg;
|
||||
*bit = g->sr_shift;
|
||||
*width = g->sr_width;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int owl_group_pinconf_arg2val(const struct owl_pingroup *g,
|
||||
unsigned int param,
|
||||
u32 *arg)
|
||||
{
|
||||
switch (param) {
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
switch (*arg) {
|
||||
case 2:
|
||||
*arg = OWL_PINCONF_DRV_2MA;
|
||||
break;
|
||||
case 4:
|
||||
*arg = OWL_PINCONF_DRV_4MA;
|
||||
break;
|
||||
case 8:
|
||||
*arg = OWL_PINCONF_DRV_8MA;
|
||||
break;
|
||||
case 12:
|
||||
*arg = OWL_PINCONF_DRV_12MA;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
if (*arg)
|
||||
*arg = OWL_PINCONF_SLEW_FAST;
|
||||
else
|
||||
*arg = OWL_PINCONF_SLEW_SLOW;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int owl_group_pinconf_val2arg(const struct owl_pingroup *g,
|
||||
unsigned int param,
|
||||
u32 *arg)
|
||||
{
|
||||
switch (param) {
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
switch (*arg) {
|
||||
case OWL_PINCONF_DRV_2MA:
|
||||
*arg = 2;
|
||||
break;
|
||||
case OWL_PINCONF_DRV_4MA:
|
||||
*arg = 4;
|
||||
break;
|
||||
case OWL_PINCONF_DRV_8MA:
|
||||
*arg = 8;
|
||||
break;
|
||||
case OWL_PINCONF_DRV_12MA:
|
||||
*arg = 12;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
if (*arg)
|
||||
*arg = 1;
|
||||
else
|
||||
*arg = 0;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int owl_group_config_get(struct pinctrl_dev *pctrldev,
|
||||
unsigned int group,
|
||||
unsigned long *config)
|
||||
{
|
||||
const struct owl_pingroup *g;
|
||||
struct owl_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrldev);
|
||||
unsigned int param = pinconf_to_config_param(*config);
|
||||
u32 reg, bit, width, arg;
|
||||
int ret;
|
||||
|
||||
g = &pctrl->soc->groups[group];
|
||||
|
||||
ret = owl_group_pinconf_reg(g, param, ®, &bit, &width);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
arg = owl_read_field(pctrl, reg, bit, width);
|
||||
|
||||
ret = owl_group_pinconf_val2arg(g, param, &arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*config = pinconf_to_config_packed(param, arg);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
static int owl_group_config_set(struct pinctrl_dev *pctrldev,
|
||||
unsigned int group,
|
||||
unsigned long *configs,
|
||||
unsigned int num_configs)
|
||||
{
|
||||
const struct owl_pingroup *g;
|
||||
struct owl_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrldev);
|
||||
unsigned long flags;
|
||||
unsigned int param;
|
||||
u32 reg, bit, width, arg;
|
||||
int ret, i;
|
||||
|
||||
g = &pctrl->soc->groups[group];
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
param = pinconf_to_config_param(configs[i]);
|
||||
arg = pinconf_to_config_argument(configs[i]);
|
||||
|
||||
ret = owl_group_pinconf_reg(g, param, ®, &bit, &width);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = owl_group_pinconf_arg2val(g, param, &arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Update register */
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
owl_write_field(pctrl, reg, arg, bit, width);
|
||||
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinconf_ops owl_pinconf_ops = {
|
||||
.is_generic = true,
|
||||
.pin_config_get = owl_pin_config_get,
|
||||
.pin_config_set = owl_pin_config_set,
|
||||
.pin_config_group_get = owl_group_config_get,
|
||||
.pin_config_group_set = owl_group_config_set,
|
||||
};
|
||||
|
||||
static struct pinctrl_desc owl_pinctrl_desc = {
|
||||
.pctlops = &owl_pinctrl_ops,
|
||||
.pmxops = &owl_pinmux_ops,
|
||||
.confops = &owl_pinconf_ops,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const struct owl_gpio_port *
|
||||
owl_gpio_get_port(struct owl_pinctrl *pctrl, unsigned int *pin)
|
||||
{
|
||||
unsigned int start = 0, i;
|
||||
|
||||
for (i = 0; i < pctrl->soc->nports; i++) {
|
||||
const struct owl_gpio_port *port = &pctrl->soc->ports[i];
|
||||
|
||||
if (*pin >= start && *pin < start + port->pins) {
|
||||
*pin -= start;
|
||||
return port;
|
||||
}
|
||||
|
||||
start += port->pins;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void owl_gpio_update_reg(void __iomem *base, unsigned int pin, int flag)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl_relaxed(base);
|
||||
|
||||
if (flag)
|
||||
val |= BIT(pin);
|
||||
else
|
||||
val &= ~BIT(pin);
|
||||
|
||||
writel_relaxed(val, base);
|
||||
}
|
||||
|
||||
static int owl_gpio_request(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = gpiochip_get_data(chip);
|
||||
const struct owl_gpio_port *port;
|
||||
void __iomem *gpio_base;
|
||||
unsigned long flags;
|
||||
|
||||
port = owl_gpio_get_port(pctrl, &offset);
|
||||
if (WARN_ON(port == NULL))
|
||||
return -ENODEV;
|
||||
|
||||
gpio_base = pctrl->base + port->offset;
|
||||
|
||||
/*
|
||||
* GPIOs have higher priority over other modules, so either setting
|
||||
* them as OUT or IN is sufficient
|
||||
*/
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
owl_gpio_update_reg(gpio_base + port->outen, offset, true);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void owl_gpio_free(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = gpiochip_get_data(chip);
|
||||
const struct owl_gpio_port *port;
|
||||
void __iomem *gpio_base;
|
||||
unsigned long flags;
|
||||
|
||||
port = owl_gpio_get_port(pctrl, &offset);
|
||||
if (WARN_ON(port == NULL))
|
||||
return;
|
||||
|
||||
gpio_base = pctrl->base + port->offset;
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
/* disable gpio output */
|
||||
owl_gpio_update_reg(gpio_base + port->outen, offset, false);
|
||||
|
||||
/* disable gpio input */
|
||||
owl_gpio_update_reg(gpio_base + port->inen, offset, false);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
}
|
||||
|
||||
static int owl_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = gpiochip_get_data(chip);
|
||||
const struct owl_gpio_port *port;
|
||||
void __iomem *gpio_base;
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
|
||||
port = owl_gpio_get_port(pctrl, &offset);
|
||||
if (WARN_ON(port == NULL))
|
||||
return -ENODEV;
|
||||
|
||||
gpio_base = pctrl->base + port->offset;
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
val = readl_relaxed(gpio_base + port->dat);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
return !!(val & BIT(offset));
|
||||
}
|
||||
|
||||
static void owl_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = gpiochip_get_data(chip);
|
||||
const struct owl_gpio_port *port;
|
||||
void __iomem *gpio_base;
|
||||
unsigned long flags;
|
||||
|
||||
port = owl_gpio_get_port(pctrl, &offset);
|
||||
if (WARN_ON(port == NULL))
|
||||
return;
|
||||
|
||||
gpio_base = pctrl->base + port->offset;
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
owl_gpio_update_reg(gpio_base + port->dat, offset, value);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
}
|
||||
|
||||
static int owl_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = gpiochip_get_data(chip);
|
||||
const struct owl_gpio_port *port;
|
||||
void __iomem *gpio_base;
|
||||
unsigned long flags;
|
||||
|
||||
port = owl_gpio_get_port(pctrl, &offset);
|
||||
if (WARN_ON(port == NULL))
|
||||
return -ENODEV;
|
||||
|
||||
gpio_base = pctrl->base + port->offset;
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
owl_gpio_update_reg(gpio_base + port->outen, offset, false);
|
||||
owl_gpio_update_reg(gpio_base + port->inen, offset, true);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int owl_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned int offset, int value)
|
||||
{
|
||||
struct owl_pinctrl *pctrl = gpiochip_get_data(chip);
|
||||
const struct owl_gpio_port *port;
|
||||
void __iomem *gpio_base;
|
||||
unsigned long flags;
|
||||
|
||||
port = owl_gpio_get_port(pctrl, &offset);
|
||||
if (WARN_ON(port == NULL))
|
||||
return -ENODEV;
|
||||
|
||||
gpio_base = pctrl->base + port->offset;
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
owl_gpio_update_reg(gpio_base + port->inen, offset, false);
|
||||
owl_gpio_update_reg(gpio_base + port->outen, offset, true);
|
||||
owl_gpio_update_reg(gpio_base + port->dat, offset, value);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int owl_gpio_init(struct owl_pinctrl *pctrl)
|
||||
{
|
||||
struct gpio_chip *chip;
|
||||
int ret;
|
||||
|
||||
chip = &pctrl->chip;
|
||||
chip->base = -1;
|
||||
chip->ngpio = pctrl->soc->ngpios;
|
||||
chip->label = dev_name(pctrl->dev);
|
||||
chip->parent = pctrl->dev;
|
||||
chip->owner = THIS_MODULE;
|
||||
chip->of_node = pctrl->dev->of_node;
|
||||
|
||||
ret = gpiochip_add_data(&pctrl->chip, pctrl);
|
||||
if (ret) {
|
||||
dev_err(pctrl->dev, "failed to register gpiochip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int owl_pinctrl_probe(struct platform_device *pdev,
|
||||
struct owl_pinctrl_soc_data *soc_data)
|
||||
{
|
||||
struct resource *res;
|
||||
struct owl_pinctrl *pctrl;
|
||||
int ret;
|
||||
|
||||
pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
|
||||
if (!pctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
pctrl->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pctrl->base))
|
||||
return PTR_ERR(pctrl->base);
|
||||
|
||||
/* enable GPIO/MFP clock */
|
||||
pctrl->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(pctrl->clk)) {
|
||||
dev_err(&pdev->dev, "no clock defined\n");
|
||||
return PTR_ERR(pctrl->clk);
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(pctrl->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "clk enable failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
raw_spin_lock_init(&pctrl->lock);
|
||||
|
||||
owl_pinctrl_desc.name = dev_name(&pdev->dev);
|
||||
owl_pinctrl_desc.pins = soc_data->pins;
|
||||
owl_pinctrl_desc.npins = soc_data->npins;
|
||||
|
||||
pctrl->chip.direction_input = owl_gpio_direction_input;
|
||||
pctrl->chip.direction_output = owl_gpio_direction_output;
|
||||
pctrl->chip.get = owl_gpio_get;
|
||||
pctrl->chip.set = owl_gpio_set;
|
||||
pctrl->chip.request = owl_gpio_request;
|
||||
pctrl->chip.free = owl_gpio_free;
|
||||
|
||||
pctrl->soc = soc_data;
|
||||
pctrl->dev = &pdev->dev;
|
||||
|
||||
pctrl->pctrldev = devm_pinctrl_register(&pdev->dev,
|
||||
&owl_pinctrl_desc, pctrl);
|
||||
if (IS_ERR(pctrl->pctrldev)) {
|
||||
dev_err(&pdev->dev, "could not register Actions OWL pinmux driver\n");
|
||||
return PTR_ERR(pctrl->pctrldev);
|
||||
}
|
||||
|
||||
ret = owl_gpio_init(pctrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, pctrl);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* OWL SoC's Pinctrl definitions
|
||||
*
|
||||
* Copyright (c) 2014 Actions Semi Inc.
|
||||
* Author: David Liu <liuwei@actions-semi.com>
|
||||
*
|
||||
* Copyright (c) 2018 Linaro Ltd.
|
||||
* Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
*/
|
||||
|
||||
#ifndef __PINCTRL_OWL_H__
|
||||
#define __PINCTRL_OWL_H__
|
||||
|
||||
#define OWL_PINCONF_SLEW_SLOW 0
|
||||
#define OWL_PINCONF_SLEW_FAST 1
|
||||
|
||||
enum owl_pinconf_pull {
|
||||
OWL_PINCONF_PULL_HIZ,
|
||||
OWL_PINCONF_PULL_DOWN,
|
||||
OWL_PINCONF_PULL_UP,
|
||||
OWL_PINCONF_PULL_HOLD,
|
||||
};
|
||||
|
||||
enum owl_pinconf_drv {
|
||||
OWL_PINCONF_DRV_2MA,
|
||||
OWL_PINCONF_DRV_4MA,
|
||||
OWL_PINCONF_DRV_8MA,
|
||||
OWL_PINCONF_DRV_12MA,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct owl_pullctl - Actions pad pull control register
|
||||
* @reg: offset to the pull control register
|
||||
* @shift: shift value of the register
|
||||
* @width: width of the register
|
||||
*/
|
||||
struct owl_pullctl {
|
||||
int reg;
|
||||
unsigned int shift;
|
||||
unsigned int width;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct owl_st - Actions pad schmitt trigger enable register
|
||||
* @reg: offset to the schmitt trigger enable register
|
||||
* @shift: shift value of the register
|
||||
* @width: width of the register
|
||||
*/
|
||||
struct owl_st {
|
||||
int reg;
|
||||
unsigned int shift;
|
||||
unsigned int width;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct owl_pingroup - Actions pingroup definition
|
||||
* @name: name of the pin group
|
||||
* @pads: list of pins assigned to this pingroup
|
||||
* @npads: size of @pads array
|
||||
* @funcs: list of pinmux functions for this pingroup
|
||||
* @nfuncs: size of @funcs array
|
||||
* @mfpctl_reg: multiplexing control register offset
|
||||
* @mfpctl_shift: multiplexing control register bit mask
|
||||
* @mfpctl_width: multiplexing control register width
|
||||
* @drv_reg: drive control register offset
|
||||
* @drv_shift: drive control register bit mask
|
||||
* @drv_width: driver control register width
|
||||
* @sr_reg: slew rate control register offset
|
||||
* @sr_shift: slew rate control register bit mask
|
||||
* @sr_width: slew rate control register width
|
||||
*/
|
||||
struct owl_pingroup {
|
||||
const char *name;
|
||||
unsigned int *pads;
|
||||
unsigned int npads;
|
||||
unsigned int *funcs;
|
||||
unsigned int nfuncs;
|
||||
|
||||
int mfpctl_reg;
|
||||
unsigned int mfpctl_shift;
|
||||
unsigned int mfpctl_width;
|
||||
|
||||
int drv_reg;
|
||||
unsigned int drv_shift;
|
||||
unsigned int drv_width;
|
||||
|
||||
int sr_reg;
|
||||
unsigned int sr_shift;
|
||||
unsigned int sr_width;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct owl_padinfo - Actions pinctrl pad info
|
||||
* @pad: pad name of the SoC
|
||||
* @pullctl: pull control register info
|
||||
* @st: schmitt trigger register info
|
||||
*/
|
||||
struct owl_padinfo {
|
||||
int pad;
|
||||
struct owl_pullctl *pullctl;
|
||||
struct owl_st *st;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct owl_pinmux_func - Actions pinctrl mux functions
|
||||
* @name: name of the pinmux function.
|
||||
* @groups: array of pin groups that may select this function.
|
||||
* @ngroups: number of entries in @groups.
|
||||
*/
|
||||
struct owl_pinmux_func {
|
||||
const char *name;
|
||||
const char * const *groups;
|
||||
unsigned int ngroups;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct owl_gpio_port - Actions GPIO port info
|
||||
* @offset: offset of the GPIO port.
|
||||
* @pins: number of pins belongs to the GPIO port.
|
||||
* @outen: offset of the output enable register.
|
||||
* @inen: offset of the input enable register.
|
||||
* @dat: offset of the data register.
|
||||
*/
|
||||
struct owl_gpio_port {
|
||||
unsigned int offset;
|
||||
unsigned int pins;
|
||||
unsigned int outen;
|
||||
unsigned int inen;
|
||||
unsigned int dat;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct owl_pinctrl_soc_data - Actions pin controller driver configuration
|
||||
* @pins: array describing all pins of the pin controller.
|
||||
* @npins: number of entries in @pins.
|
||||
* @functions: array describing all mux functions of this SoC.
|
||||
* @nfunction: number of entries in @functions.
|
||||
* @groups: array describing all pin groups of this SoC.
|
||||
* @ngroups: number of entries in @groups.
|
||||
* @padinfo: array describing the pad info of this SoC.
|
||||
* @ngpios: number of pingroups the driver should expose as GPIOs.
|
||||
* @port: array describing all GPIO ports of this SoC.
|
||||
* @nports: number of GPIO ports in this SoC.
|
||||
*/
|
||||
struct owl_pinctrl_soc_data {
|
||||
const struct pinctrl_pin_desc *pins;
|
||||
unsigned int npins;
|
||||
const struct owl_pinmux_func *functions;
|
||||
unsigned int nfunctions;
|
||||
const struct owl_pingroup *groups;
|
||||
unsigned int ngroups;
|
||||
const struct owl_padinfo *padinfo;
|
||||
unsigned int ngpios;
|
||||
const struct owl_gpio_port *ports;
|
||||
unsigned int nports;
|
||||
};
|
||||
|
||||
int owl_pinctrl_probe(struct platform_device *pdev,
|
||||
struct owl_pinctrl_soc_data *soc_data);
|
||||
|
||||
#endif /* __PINCTRL_OWL_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -20,6 +20,7 @@ config PINCTRL_BCM2835
|
|||
bool
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
select GENERIC_PINCONF
|
||||
select GPIOLIB_IRQCHIP
|
||||
|
||||
config PINCTRL_IPROC_GPIO
|
||||
|
|
|
@ -36,11 +36,13 @@
|
|||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
#include <dt-bindings/pinctrl/bcm2835.h>
|
||||
|
||||
#define MODULE_NAME "pinctrl-bcm2835"
|
||||
#define BCM2835_NUM_GPIOS 54
|
||||
|
@ -72,13 +74,9 @@
|
|||
|
||||
enum bcm2835_pinconf_param {
|
||||
/* argument: bcm2835_pinconf_pull */
|
||||
BCM2835_PINCONF_PARAM_PULL,
|
||||
BCM2835_PINCONF_PARAM_PULL = (PIN_CONFIG_END + 1),
|
||||
};
|
||||
|
||||
#define BCM2835_PINCONF_PACK(_param_, _arg_) ((_param_) << 16 | (_arg_))
|
||||
#define BCM2835_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16)
|
||||
#define BCM2835_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff)
|
||||
|
||||
struct bcm2835_pinctrl {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
|
@ -213,14 +211,6 @@ static const char * const bcm2835_gpio_groups[] = {
|
|||
};
|
||||
|
||||
enum bcm2835_fsel {
|
||||
BCM2835_FSEL_GPIO_IN = 0,
|
||||
BCM2835_FSEL_GPIO_OUT = 1,
|
||||
BCM2835_FSEL_ALT0 = 4,
|
||||
BCM2835_FSEL_ALT1 = 5,
|
||||
BCM2835_FSEL_ALT2 = 6,
|
||||
BCM2835_FSEL_ALT3 = 7,
|
||||
BCM2835_FSEL_ALT4 = 3,
|
||||
BCM2835_FSEL_ALT5 = 2,
|
||||
BCM2835_FSEL_COUNT = 8,
|
||||
BCM2835_FSEL_MASK = 0x7,
|
||||
};
|
||||
|
@ -714,7 +704,7 @@ static int bcm2835_pctl_dt_node_to_map_pull(struct bcm2835_pinctrl *pc,
|
|||
configs = kzalloc(sizeof(*configs), GFP_KERNEL);
|
||||
if (!configs)
|
||||
return -ENOMEM;
|
||||
configs[0] = BCM2835_PINCONF_PACK(BCM2835_PINCONF_PARAM_PULL, pull);
|
||||
configs[0] = pinconf_to_config_packed(BCM2835_PINCONF_PARAM_PULL, pull);
|
||||
|
||||
map->type = PIN_MAP_TYPE_CONFIGS_PIN;
|
||||
map->data.configs.group_or_pin = bcm2835_gpio_pins[pin].name;
|
||||
|
@ -727,7 +717,7 @@ static int bcm2835_pctl_dt_node_to_map_pull(struct bcm2835_pinctrl *pc,
|
|||
|
||||
static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map, unsigned *num_maps)
|
||||
struct pinctrl_map **map, unsigned int *num_maps)
|
||||
{
|
||||
struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct property *pins, *funcs, *pulls;
|
||||
|
@ -736,6 +726,12 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
|||
int i, err;
|
||||
u32 pin, func, pull;
|
||||
|
||||
/* Check for generic binding in this node */
|
||||
err = pinconf_generic_dt_node_to_map_all(pctldev, np, map, num_maps);
|
||||
if (err || *num_maps)
|
||||
return err;
|
||||
|
||||
/* Generic binding did not find anything continue with legacy parse */
|
||||
pins = of_find_property(np, "brcm,pins", NULL);
|
||||
if (!pins) {
|
||||
dev_err(pc->dev, "%pOF: missing brcm,pins property\n", np);
|
||||
|
@ -917,37 +913,67 @@ static int bcm2835_pinconf_get(struct pinctrl_dev *pctldev,
|
|||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static void bcm2835_pull_config_set(struct bcm2835_pinctrl *pc,
|
||||
unsigned int pin, unsigned int arg)
|
||||
{
|
||||
u32 off, bit;
|
||||
|
||||
off = GPIO_REG_OFFSET(pin);
|
||||
bit = GPIO_REG_SHIFT(pin);
|
||||
|
||||
bcm2835_gpio_wr(pc, GPPUD, arg & 3);
|
||||
/*
|
||||
* BCM2835 datasheet say to wait 150 cycles, but not of what.
|
||||
* But the VideoCore firmware delay for this operation
|
||||
* based nearly on the same amount of VPU cycles and this clock
|
||||
* runs at 250 MHz.
|
||||
*/
|
||||
udelay(1);
|
||||
bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
|
||||
udelay(1);
|
||||
bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
|
||||
}
|
||||
|
||||
static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
|
||||
unsigned pin, unsigned long *configs,
|
||||
unsigned num_configs)
|
||||
unsigned int pin, unsigned long *configs,
|
||||
unsigned int num_configs)
|
||||
{
|
||||
struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
|
||||
enum bcm2835_pinconf_param param;
|
||||
u16 arg;
|
||||
u32 off, bit;
|
||||
u32 param, arg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
param = BCM2835_PINCONF_UNPACK_PARAM(configs[i]);
|
||||
arg = BCM2835_PINCONF_UNPACK_ARG(configs[i]);
|
||||
param = pinconf_to_config_param(configs[i]);
|
||||
arg = pinconf_to_config_argument(configs[i]);
|
||||
|
||||
if (param != BCM2835_PINCONF_PARAM_PULL)
|
||||
switch (param) {
|
||||
/* Set legacy brcm,pull */
|
||||
case BCM2835_PINCONF_PARAM_PULL:
|
||||
bcm2835_pull_config_set(pc, pin, arg);
|
||||
break;
|
||||
|
||||
/* Set pull generic bindings */
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
bcm2835_pull_config_set(pc, pin, BCM2835_PUD_OFF);
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
bcm2835_pull_config_set(pc, pin, BCM2835_PUD_DOWN);
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
bcm2835_pull_config_set(pc, pin, BCM2835_PUD_UP);
|
||||
break;
|
||||
|
||||
/* Set output-high or output-low */
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
bcm2835_gpio_set_bit(pc, arg ? GPSET0 : GPCLR0, pin);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
||||
off = GPIO_REG_OFFSET(pin);
|
||||
bit = GPIO_REG_SHIFT(pin);
|
||||
|
||||
bcm2835_gpio_wr(pc, GPPUD, arg & 3);
|
||||
/*
|
||||
* BCM2835 datasheet say to wait 150 cycles, but not of what.
|
||||
* But the VideoCore firmware delay for this operation
|
||||
* based nearly on the same amount of VPU cycles and this clock
|
||||
* runs at 250 MHz.
|
||||
*/
|
||||
udelay(1);
|
||||
bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit));
|
||||
udelay(1);
|
||||
bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0);
|
||||
} /* switch param type */
|
||||
} /* for each config */
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Marvell Berlin BG2 pinctrl driver.
|
||||
*
|
||||
* Copyright (C) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Antoine Ténart <antoine.tenart@free-electrons.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Marvell Berlin BG2CD pinctrl driver.
|
||||
*
|
||||
* Copyright (C) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Antoine Ténart <antoine.tenart@free-electrons.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Marvell Berlin BG2Q pinctrl driver
|
||||
*
|
||||
* Copyright (C) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Antoine Ténart <antoine.tenart@free-electrons.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,21 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Marvell berlin4ct pinctrl driver
|
||||
*
|
||||
* Copyright (C) 2015 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Author: Jisheng Zhang <jszhang@marvell.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Marvell Berlin SoC pinctrl core driver
|
||||
*
|
||||
* Copyright (C) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Antoine Ténart <antoine.tenart@free-electrons.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Marvell Berlin SoC pinctrl driver.
|
||||
*
|
||||
* Copyright (C) 2014 Marvell Technology Group Ltd.
|
||||
*
|
||||
* Antoine Ténart <antoine.tenart@free-electrons.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#ifndef __PINCTRL_BERLIN_H
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
/*
|
||||
* Core driver for the imx pin controller
|
||||
*
|
||||
* Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Linaro Ltd.
|
||||
*
|
||||
* Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// Core driver for the imx pin controller
|
||||
//
|
||||
// Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
// Copyright (C) 2012 Linaro Ltd.
|
||||
//
|
||||
// Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -371,7 +366,7 @@ static void imx_pinconf_dbg_show(struct pinctrl_dev *pctldev,
|
|||
unsigned long config;
|
||||
|
||||
if (!pin_reg || pin_reg->conf_reg == -1) {
|
||||
seq_printf(s, "N/A");
|
||||
seq_puts(s, "N/A");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -390,7 +385,7 @@ static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
|
|||
if (group > pctldev->num_groups)
|
||||
return;
|
||||
|
||||
seq_printf(s, "\n");
|
||||
seq_puts(s, "\n");
|
||||
grp = pinctrl_generic_get_group(pctldev, group);
|
||||
if (!grp)
|
||||
return;
|
||||
|
@ -414,11 +409,18 @@ static const struct pinconf_ops imx_pinconf_ops = {
|
|||
};
|
||||
|
||||
/*
|
||||
* Each pin represented in fsl,pins consists of 5 u32 PIN_FUNC_ID and
|
||||
* 1 u32 CONFIG, so 24 types in total for each pin.
|
||||
* Each pin represented in fsl,pins consists of a number of u32 PIN_FUNC_ID
|
||||
* and 1 u32 CONFIG, the total size is PIN_FUNC_ID + CONFIG for each pin.
|
||||
* For generic_pinconf case, there's no extra u32 CONFIG.
|
||||
*
|
||||
* PIN_FUNC_ID format:
|
||||
* Default:
|
||||
* <mux_reg conf_reg input_reg mux_mode input_val>
|
||||
* SHARE_MUX_CONF_REG:
|
||||
* <mux_conf_reg input_reg mux_mode input_val>
|
||||
*/
|
||||
#define FSL_PIN_SIZE 24
|
||||
#define SHARE_FSL_PIN_SIZE 20
|
||||
#define FSL_PIN_SHARE_SIZE 20
|
||||
|
||||
static int imx_pinctrl_parse_groups(struct device_node *np,
|
||||
struct group_desc *grp,
|
||||
|
@ -434,7 +436,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
|
|||
dev_dbg(ipctl->dev, "group(%d): %s\n", index, np->name);
|
||||
|
||||
if (info->flags & SHARE_MUX_CONF_REG)
|
||||
pin_size = SHARE_FSL_PIN_SIZE;
|
||||
pin_size = FSL_PIN_SHARE_SIZE;
|
||||
else
|
||||
pin_size = FSL_PIN_SIZE;
|
||||
|
||||
|
@ -617,7 +619,7 @@ static int imx_pinctrl_probe_dt(struct platform_device *pdev,
|
|||
nfuncs = 1;
|
||||
} else {
|
||||
nfuncs = of_get_child_count(np);
|
||||
if (nfuncs <= 0) {
|
||||
if (nfuncs == 0) {
|
||||
dev_err(&pdev->dev, "no functions defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* IMX pinmux core definitions
|
||||
*
|
||||
|
@ -5,11 +6,6 @@
|
|||
* Copyright (C) 2012 Linaro Ltd.
|
||||
*
|
||||
* Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
*
|
||||
* 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 __DRIVERS_PINCTRL_IMX_H
|
||||
|
|
|
@ -1,19 +1,14 @@
|
|||
/*
|
||||
* Core driver for the imx pin controller in imx1/21/27
|
||||
*
|
||||
* Copyright (C) 2013 Pengutronix
|
||||
* Author: Markus Pargmann <mpa@pengutronix.de>
|
||||
*
|
||||
* Based on pinctrl-imx.c:
|
||||
* Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
* Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Linaro Ltd.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// Core driver for the imx pin controller in imx1/21/27
|
||||
//
|
||||
// Copyright (C) 2013 Pengutronix
|
||||
// Author: Markus Pargmann <mpa@pengutronix.de>
|
||||
//
|
||||
// Based on pinctrl-imx.c:
|
||||
// Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
// Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
// Copyright (C) 2012 Linaro Ltd.
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/err.h>
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
/*
|
||||
* i.MX1 pinctrl driver based on imx pinmux core
|
||||
*
|
||||
* Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// i.MX1 pinctrl driver based on imx pinmux core
|
||||
//
|
||||
// Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* IMX pinmux core definitions
|
||||
*
|
||||
|
@ -5,11 +6,6 @@
|
|||
* Copyright (C) 2012 Linaro Ltd.
|
||||
*
|
||||
* Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
*
|
||||
* 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 __DRIVERS_PINCTRL_IMX1_H
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
/*
|
||||
* i.MX21 pinctrl driver based on imx pinmux core
|
||||
*
|
||||
* Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// i.MX21 pinctrl driver based on imx pinmux core
|
||||
//
|
||||
// Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
/*
|
||||
* Freescale i.MX23 pinctrl driver
|
||||
*
|
||||
* Author: Shawn Guo <shawn.guo@linaro.org>
|
||||
* Copyright 2012 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// Freescale i.MX23 pinctrl driver
|
||||
//
|
||||
// Author: Shawn Guo <shawn.guo@linaro.org>
|
||||
// Copyright 2012 Freescale Semiconductor, Inc.
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_device.h>
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
/*
|
||||
* imx25 pinctrl driver.
|
||||
*
|
||||
* Copyright 2013 Eukréa Electromatique <denis@eukrea.com>
|
||||
*
|
||||
* This driver was mostly copied from the imx51 pinctrl driver which has:
|
||||
*
|
||||
* Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Linaro, Inc.
|
||||
*
|
||||
* Author: Denis Carikli <denis@eukrea.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// imx25 pinctrl driver.
|
||||
//
|
||||
// Copyright 2013 Eukréa Electromatique <denis@eukrea.com>
|
||||
//
|
||||
// This driver was mostly copied from the imx51 pinctrl driver which has:
|
||||
//
|
||||
// Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
// Copyright (C) 2012 Linaro, Inc.
|
||||
//
|
||||
// Author: Denis Carikli <denis@eukrea.com>
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
/*
|
||||
* imx27 pinctrl driver based on imx pinmux core
|
||||
*
|
||||
* Copyright (C) 2013 Pengutronix
|
||||
*
|
||||
* Author: Markus Pargmann <mpa@pengutronix.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// imx27 pinctrl driver based on imx pinmux core
|
||||
//
|
||||
// Copyright (C) 2013 Pengutronix
|
||||
//
|
||||
// Author: Markus Pargmann <mpa@pengutronix.de>
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
/*
|
||||
* Freescale i.MX28 pinctrl driver
|
||||
*
|
||||
* Author: Shawn Guo <shawn.guo@linaro.org>
|
||||
* Copyright 2012 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// Freescale i.MX28 pinctrl driver
|
||||
//
|
||||
// Author: Shawn Guo <shawn.guo@linaro.org>
|
||||
// Copyright 2012 Freescale Semiconductor, Inc.
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_device.h>
|
||||
|
|
|
@ -1,17 +1,13 @@
|
|||
/*
|
||||
* imx35 pinctrl driver.
|
||||
*
|
||||
* This driver was mostly copied from the imx51 pinctrl driver which has:
|
||||
*
|
||||
* Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Linaro, Inc.
|
||||
*
|
||||
* Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as published
|
||||
* by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// imx35 pinctrl driver.
|
||||
//
|
||||
// This driver was mostly copied from the imx51 pinctrl driver which has:
|
||||
//
|
||||
// Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
// Copyright (C) 2012 Linaro, Inc.
|
||||
//
|
||||
// Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
/*
|
||||
* imx50 pinctrl driver based on imx pinmux core
|
||||
*
|
||||
* Copyright (C) 2013 Greg Ungerer <gerg@uclinux.org>
|
||||
* Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Linaro, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// imx50 pinctrl driver based on imx pinmux core
|
||||
//
|
||||
// Copyright (C) 2013 Greg Ungerer <gerg@uclinux.org>
|
||||
// Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
// Copyright (C) 2012 Linaro, Inc.
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
/*
|
||||
* imx51 pinctrl driver based on imx pinmux core
|
||||
*
|
||||
* Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Linaro, Inc.
|
||||
*
|
||||
* Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// imx51 pinctrl driver based on imx pinmux core
|
||||
//
|
||||
// Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
// Copyright (C) 2012 Linaro, Inc.
|
||||
//
|
||||
// Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
/*
|
||||
* imx53 pinctrl driver based on imx pinmux core
|
||||
*
|
||||
* Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Linaro, Inc.
|
||||
*
|
||||
* Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// imx53 pinctrl driver based on imx pinmux core
|
||||
//
|
||||
// Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
// Copyright (C) 2012 Linaro, Inc.
|
||||
//
|
||||
// Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
/*
|
||||
* Freescale imx6dl pinctrl driver
|
||||
*
|
||||
* Author: Shawn Guo <shawn.guo@linaro.org>
|
||||
* Copyright (C) 2013 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Freescale imx6dl pinctrl driver
|
||||
//
|
||||
// Author: Shawn Guo <shawn.guo@linaro.org>
|
||||
// Copyright (C) 2013 Freescale Semiconductor, Inc.
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
/*
|
||||
* imx6q pinctrl driver based on imx pinmux core
|
||||
*
|
||||
* Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2012 Linaro, Inc.
|
||||
*
|
||||
* Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// imx6q pinctrl driver based on imx pinmux core
|
||||
//
|
||||
// Copyright (C) 2012 Freescale Semiconductor, Inc.
|
||||
// Copyright (C) 2012 Linaro, Inc.
|
||||
//
|
||||
// Author: Dong Aisheng <dong.aisheng@linaro.org>
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
/*
|
||||
* Freescale imx6sl pinctrl driver
|
||||
*
|
||||
* Author: Shawn Guo <shawn.guo@linaro.org>
|
||||
* Copyright (C) 2013 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Freescale imx6sl pinctrl driver
|
||||
//
|
||||
// Author: Shawn Guo <shawn.guo@linaro.org>
|
||||
// Copyright (C) 2013 Freescale Semiconductor, Inc.
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017-2018 NXP.
|
||||
*
|
||||
*/
|
||||
//
|
||||
// Copyright (C) 2016 Freescale Semiconductor, Inc.
|
||||
// Copyright 2017-2018 NXP.
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
/*
|
||||
* Freescale imx6sx pinctrl driver
|
||||
*
|
||||
* Author: Anson Huang <Anson.Huang@freescale.com>
|
||||
* Copyright (C) 2014 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Freescale imx6sx pinctrl driver
|
||||
//
|
||||
// Author: Anson Huang <Anson.Huang@freescale.com>
|
||||
// Copyright (C) 2014 Freescale Semiconductor, Inc.
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
/*
|
||||
* Freescale imx6ul pinctrl driver
|
||||
*
|
||||
* Author: Anson Huang <Anson.Huang@freescale.com>
|
||||
* Copyright (C) 2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Freescale imx6ul pinctrl driver
|
||||
//
|
||||
// Author: Anson Huang <Anson.Huang@freescale.com>
|
||||
// Copyright (C) 2015 Freescale Semiconductor, Inc.
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
/*
|
||||
* Freescale imx7d pinctrl driver
|
||||
*
|
||||
* Author: Anson Huang <Anson.Huang@freescale.com>
|
||||
* Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Freescale imx7d pinctrl driver
|
||||
//
|
||||
// Author: Anson Huang <Anson.Huang@freescale.com>
|
||||
// Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2017 NXP
|
||||
*
|
||||
* Author: Dong Aisheng <aisheng.dong@nxp.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Copyright (C) 2016 Freescale Semiconductor, Inc.
|
||||
// Copyright (C) 2017 NXP
|
||||
//
|
||||
// Author: Dong Aisheng <aisheng.dong@nxp.com>
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
/*
|
||||
* Copyright 2012 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// Copyright 2012 Freescale Semiconductor, Inc.
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* Copyright 2012 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
#ifndef __PINCTRL_MXS_H
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
/*
|
||||
* VF610 pinctrl driver based on imx pinmux and pinconf core
|
||||
*
|
||||
* Copyright 2013 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
//
|
||||
// VF610 pinctrl driver based on imx pinmux and pinconf core
|
||||
//
|
||||
// Copyright 2013 Freescale Semiconductor, Inc.
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
|
|
|
@ -1527,6 +1527,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
|
|||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
|
||||
DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"),
|
||||
DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -1534,6 +1535,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
|
|||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "HP"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Setzer"),
|
||||
DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -1541,6 +1543,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
|
|||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"),
|
||||
DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -1548,6 +1551,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
|
|||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "Celes"),
|
||||
DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
menu "MediaTek pinctrl drivers"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
|
||||
config EINT_MTK
|
||||
bool "MediaTek External Interrupt Support"
|
||||
depends on PINCTRL_MTK || PINCTRL_MT7622 || COMPILE_TEST
|
||||
select IRQ_DOMAIN
|
||||
|
||||
config PINCTRL_MTK
|
||||
bool
|
||||
depends on OF
|
||||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
select GPIOLIB
|
||||
select EINT_MTK
|
||||
select OF_GPIO
|
||||
|
||||
# For ARMv7 SoCs
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Core
|
||||
obj-$(CONFIG_EINT_MTK) += mtk-eint.o
|
||||
obj-$(CONFIG_PINCTRL_MTK) += pinctrl-mtk-common.o
|
||||
|
||||
# SoC Drivers
|
||||
|
|
|
@ -0,0 +1,492 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2014-2018 MediaTek Inc.
|
||||
|
||||
/*
|
||||
* Library for MediaTek External Interrupt Support
|
||||
*
|
||||
* Author: Maoguang Meng <maoguang.meng@mediatek.com>
|
||||
* Sean Wang <sean.wang@mediatek.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "mtk-eint.h"
|
||||
|
||||
#define MTK_EINT_EDGE_SENSITIVE 0
|
||||
#define MTK_EINT_LEVEL_SENSITIVE 1
|
||||
#define MTK_EINT_DBNC_SET_DBNC_BITS 4
|
||||
#define MTK_EINT_DBNC_RST_BIT (0x1 << 1)
|
||||
#define MTK_EINT_DBNC_SET_EN (0x1 << 0)
|
||||
|
||||
static const struct mtk_eint_regs mtk_generic_eint_regs = {
|
||||
.stat = 0x000,
|
||||
.ack = 0x040,
|
||||
.mask = 0x080,
|
||||
.mask_set = 0x0c0,
|
||||
.mask_clr = 0x100,
|
||||
.sens = 0x140,
|
||||
.sens_set = 0x180,
|
||||
.sens_clr = 0x1c0,
|
||||
.soft = 0x200,
|
||||
.soft_set = 0x240,
|
||||
.soft_clr = 0x280,
|
||||
.pol = 0x300,
|
||||
.pol_set = 0x340,
|
||||
.pol_clr = 0x380,
|
||||
.dom_en = 0x400,
|
||||
.dbnc_ctrl = 0x500,
|
||||
.dbnc_set = 0x600,
|
||||
.dbnc_clr = 0x700,
|
||||
};
|
||||
|
||||
static void __iomem *mtk_eint_get_offset(struct mtk_eint *eint,
|
||||
unsigned int eint_num,
|
||||
unsigned int offset)
|
||||
{
|
||||
unsigned int eint_base = 0;
|
||||
void __iomem *reg;
|
||||
|
||||
if (eint_num >= eint->hw->ap_num)
|
||||
eint_base = eint->hw->ap_num;
|
||||
|
||||
reg = eint->base + offset + ((eint_num - eint_base) / 32) * 4;
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
static unsigned int mtk_eint_can_en_debounce(struct mtk_eint *eint,
|
||||
unsigned int eint_num)
|
||||
{
|
||||
unsigned int sens;
|
||||
unsigned int bit = BIT(eint_num % 32);
|
||||
void __iomem *reg = mtk_eint_get_offset(eint, eint_num,
|
||||
eint->regs->sens);
|
||||
|
||||
if (readl(reg) & bit)
|
||||
sens = MTK_EINT_LEVEL_SENSITIVE;
|
||||
else
|
||||
sens = MTK_EINT_EDGE_SENSITIVE;
|
||||
|
||||
if (eint_num < eint->hw->db_cnt && sens != MTK_EINT_EDGE_SENSITIVE)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_eint_flip_edge(struct mtk_eint *eint, int hwirq)
|
||||
{
|
||||
int start_level, curr_level;
|
||||
unsigned int reg_offset;
|
||||
u32 mask = BIT(hwirq & 0x1f);
|
||||
u32 port = (hwirq >> 5) & eint->hw->port_mask;
|
||||
void __iomem *reg = eint->base + (port << 2);
|
||||
|
||||
curr_level = eint->gpio_xlate->get_gpio_state(eint->pctl, hwirq);
|
||||
|
||||
do {
|
||||
start_level = curr_level;
|
||||
if (start_level)
|
||||
reg_offset = eint->regs->pol_clr;
|
||||
else
|
||||
reg_offset = eint->regs->pol_set;
|
||||
writel(mask, reg + reg_offset);
|
||||
|
||||
curr_level = eint->gpio_xlate->get_gpio_state(eint->pctl,
|
||||
hwirq);
|
||||
} while (start_level != curr_level);
|
||||
|
||||
return start_level;
|
||||
}
|
||||
|
||||
static void mtk_eint_mask(struct irq_data *d)
|
||||
{
|
||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||
u32 mask = BIT(d->hwirq & 0x1f);
|
||||
void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
|
||||
eint->regs->mask_set);
|
||||
|
||||
writel(mask, reg);
|
||||
}
|
||||
|
||||
static void mtk_eint_unmask(struct irq_data *d)
|
||||
{
|
||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||
u32 mask = BIT(d->hwirq & 0x1f);
|
||||
void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
|
||||
eint->regs->mask_clr);
|
||||
|
||||
writel(mask, reg);
|
||||
|
||||
if (eint->dual_edge[d->hwirq])
|
||||
mtk_eint_flip_edge(eint, d->hwirq);
|
||||
}
|
||||
|
||||
static unsigned int mtk_eint_get_mask(struct mtk_eint *eint,
|
||||
unsigned int eint_num)
|
||||
{
|
||||
unsigned int bit = BIT(eint_num % 32);
|
||||
void __iomem *reg = mtk_eint_get_offset(eint, eint_num,
|
||||
eint->regs->mask);
|
||||
|
||||
return !!(readl(reg) & bit);
|
||||
}
|
||||
|
||||
static void mtk_eint_ack(struct irq_data *d)
|
||||
{
|
||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||
u32 mask = BIT(d->hwirq & 0x1f);
|
||||
void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
|
||||
eint->regs->ack);
|
||||
|
||||
writel(mask, reg);
|
||||
}
|
||||
|
||||
static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||
u32 mask = BIT(d->hwirq & 0x1f);
|
||||
void __iomem *reg;
|
||||
|
||||
if (((type & IRQ_TYPE_EDGE_BOTH) && (type & IRQ_TYPE_LEVEL_MASK)) ||
|
||||
((type & IRQ_TYPE_LEVEL_MASK) == IRQ_TYPE_LEVEL_MASK)) {
|
||||
dev_err(eint->dev,
|
||||
"Can't configure IRQ%d (EINT%lu) for type 0x%X\n",
|
||||
d->irq, d->hwirq, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
|
||||
eint->dual_edge[d->hwirq] = 1;
|
||||
else
|
||||
eint->dual_edge[d->hwirq] = 0;
|
||||
|
||||
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) {
|
||||
reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->pol_clr);
|
||||
writel(mask, reg);
|
||||
} else {
|
||||
reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->pol_set);
|
||||
writel(mask, reg);
|
||||
}
|
||||
|
||||
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
|
||||
reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->sens_clr);
|
||||
writel(mask, reg);
|
||||
} else {
|
||||
reg = mtk_eint_get_offset(eint, d->hwirq, eint->regs->sens_set);
|
||||
writel(mask, reg);
|
||||
}
|
||||
|
||||
if (eint->dual_edge[d->hwirq])
|
||||
mtk_eint_flip_edge(eint, d->hwirq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_eint_irq_set_wake(struct irq_data *d, unsigned int on)
|
||||
{
|
||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||
int shift = d->hwirq & 0x1f;
|
||||
int reg = d->hwirq >> 5;
|
||||
|
||||
if (on)
|
||||
eint->wake_mask[reg] |= BIT(shift);
|
||||
else
|
||||
eint->wake_mask[reg] &= ~BIT(shift);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_eint_chip_write_mask(const struct mtk_eint *eint,
|
||||
void __iomem *base, u32 *buf)
|
||||
{
|
||||
int port;
|
||||
void __iomem *reg;
|
||||
|
||||
for (port = 0; port < eint->hw->ports; port++) {
|
||||
reg = base + (port << 2);
|
||||
writel_relaxed(~buf[port], reg + eint->regs->mask_set);
|
||||
writel_relaxed(buf[port], reg + eint->regs->mask_clr);
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_eint_chip_read_mask(const struct mtk_eint *eint,
|
||||
void __iomem *base, u32 *buf)
|
||||
{
|
||||
int port;
|
||||
void __iomem *reg;
|
||||
|
||||
for (port = 0; port < eint->hw->ports; port++) {
|
||||
reg = base + eint->regs->mask + (port << 2);
|
||||
buf[port] = ~readl_relaxed(reg);
|
||||
/* Mask is 0 when irq is enabled, and 1 when disabled. */
|
||||
}
|
||||
}
|
||||
|
||||
static int mtk_eint_irq_request_resources(struct irq_data *d)
|
||||
{
|
||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gpio_c;
|
||||
unsigned int gpio_n;
|
||||
int err;
|
||||
|
||||
err = eint->gpio_xlate->get_gpio_n(eint->pctl, d->hwirq,
|
||||
&gpio_n, &gpio_c);
|
||||
if (err < 0) {
|
||||
dev_err(eint->dev, "Can not find pin\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = gpiochip_lock_as_irq(gpio_c, gpio_n);
|
||||
if (err < 0) {
|
||||
dev_err(eint->dev, "unable to lock HW IRQ %lu for IRQ\n",
|
||||
irqd_to_hwirq(d));
|
||||
return err;
|
||||
}
|
||||
|
||||
err = eint->gpio_xlate->set_gpio_as_eint(eint->pctl, d->hwirq);
|
||||
if (err < 0) {
|
||||
dev_err(eint->dev, "Can not eint mode\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_eint_irq_release_resources(struct irq_data *d)
|
||||
{
|
||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gpio_c;
|
||||
unsigned int gpio_n;
|
||||
|
||||
eint->gpio_xlate->get_gpio_n(eint->pctl, d->hwirq, &gpio_n,
|
||||
&gpio_c);
|
||||
|
||||
gpiochip_unlock_as_irq(gpio_c, gpio_n);
|
||||
}
|
||||
|
||||
static struct irq_chip mtk_eint_irq_chip = {
|
||||
.name = "mt-eint",
|
||||
.irq_disable = mtk_eint_mask,
|
||||
.irq_mask = mtk_eint_mask,
|
||||
.irq_unmask = mtk_eint_unmask,
|
||||
.irq_ack = mtk_eint_ack,
|
||||
.irq_set_type = mtk_eint_set_type,
|
||||
.irq_set_wake = mtk_eint_irq_set_wake,
|
||||
.irq_request_resources = mtk_eint_irq_request_resources,
|
||||
.irq_release_resources = mtk_eint_irq_release_resources,
|
||||
};
|
||||
|
||||
static unsigned int mtk_eint_hw_init(struct mtk_eint *eint)
|
||||
{
|
||||
void __iomem *reg = eint->base + eint->regs->dom_en;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < eint->hw->ap_num; i += 32) {
|
||||
writel(0xffffffff, reg);
|
||||
reg += 4;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
mtk_eint_debounce_process(struct mtk_eint *eint, int index)
|
||||
{
|
||||
unsigned int rst, ctrl_offset;
|
||||
unsigned int bit, dbnc;
|
||||
|
||||
ctrl_offset = (index / 4) * 4 + eint->regs->dbnc_ctrl;
|
||||
dbnc = readl(eint->base + ctrl_offset);
|
||||
bit = MTK_EINT_DBNC_SET_EN << ((index % 4) * 8);
|
||||
if ((bit & dbnc) > 0) {
|
||||
ctrl_offset = (index / 4) * 4 + eint->regs->dbnc_set;
|
||||
rst = MTK_EINT_DBNC_RST_BIT << ((index % 4) * 8);
|
||||
writel(rst, eint->base + ctrl_offset);
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_eint_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct mtk_eint *eint = irq_desc_get_handler_data(desc);
|
||||
unsigned int status, eint_num;
|
||||
int offset, index, virq;
|
||||
void __iomem *reg = mtk_eint_get_offset(eint, 0, eint->regs->stat);
|
||||
int dual_edge, start_level, curr_level;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
for (eint_num = 0; eint_num < eint->hw->ap_num; eint_num += 32,
|
||||
reg += 4) {
|
||||
status = readl(reg);
|
||||
while (status) {
|
||||
offset = __ffs(status);
|
||||
index = eint_num + offset;
|
||||
virq = irq_find_mapping(eint->domain, index);
|
||||
status &= ~BIT(offset);
|
||||
|
||||
dual_edge = eint->dual_edge[index];
|
||||
if (dual_edge) {
|
||||
/*
|
||||
* Clear soft-irq in case we raised it last
|
||||
* time.
|
||||
*/
|
||||
writel(BIT(offset), reg - eint->regs->stat +
|
||||
eint->regs->soft_clr);
|
||||
|
||||
start_level =
|
||||
eint->gpio_xlate->get_gpio_state(eint->pctl,
|
||||
index);
|
||||
}
|
||||
|
||||
generic_handle_irq(virq);
|
||||
|
||||
if (dual_edge) {
|
||||
curr_level = mtk_eint_flip_edge(eint, index);
|
||||
|
||||
/*
|
||||
* If level changed, we might lost one edge
|
||||
* interrupt, raised it through soft-irq.
|
||||
*/
|
||||
if (start_level != curr_level)
|
||||
writel(BIT(offset), reg -
|
||||
eint->regs->stat +
|
||||
eint->regs->soft_set);
|
||||
}
|
||||
|
||||
if (index < eint->hw->db_cnt)
|
||||
mtk_eint_debounce_process(eint, index);
|
||||
}
|
||||
}
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
int mtk_eint_do_suspend(struct mtk_eint *eint)
|
||||
{
|
||||
mtk_eint_chip_read_mask(eint, eint->base, eint->cur_mask);
|
||||
mtk_eint_chip_write_mask(eint, eint->base, eint->wake_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_eint_do_resume(struct mtk_eint *eint)
|
||||
{
|
||||
mtk_eint_chip_write_mask(eint, eint->base, eint->cur_mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
|
||||
unsigned int debounce)
|
||||
{
|
||||
int virq, eint_offset;
|
||||
unsigned int set_offset, bit, clr_bit, clr_offset, rst, i, unmask,
|
||||
dbnc;
|
||||
static const unsigned int debounce_time[] = {500, 1000, 16000, 32000,
|
||||
64000, 128000, 256000};
|
||||
struct irq_data *d;
|
||||
|
||||
virq = irq_find_mapping(eint->domain, eint_num);
|
||||
eint_offset = (eint_num % 4) * 8;
|
||||
d = irq_get_irq_data(virq);
|
||||
|
||||
set_offset = (eint_num / 4) * 4 + eint->regs->dbnc_set;
|
||||
clr_offset = (eint_num / 4) * 4 + eint->regs->dbnc_clr;
|
||||
|
||||
if (!mtk_eint_can_en_debounce(eint, eint_num))
|
||||
return -EINVAL;
|
||||
|
||||
dbnc = ARRAY_SIZE(debounce_time);
|
||||
for (i = 0; i < ARRAY_SIZE(debounce_time); i++) {
|
||||
if (debounce <= debounce_time[i]) {
|
||||
dbnc = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mtk_eint_get_mask(eint, eint_num)) {
|
||||
mtk_eint_mask(d);
|
||||
unmask = 1;
|
||||
} else {
|
||||
unmask = 0;
|
||||
}
|
||||
|
||||
clr_bit = 0xff << eint_offset;
|
||||
writel(clr_bit, eint->base + clr_offset);
|
||||
|
||||
bit = ((dbnc << MTK_EINT_DBNC_SET_DBNC_BITS) | MTK_EINT_DBNC_SET_EN) <<
|
||||
eint_offset;
|
||||
rst = MTK_EINT_DBNC_RST_BIT << eint_offset;
|
||||
writel(rst | bit, eint->base + set_offset);
|
||||
|
||||
/*
|
||||
* Delay a while (more than 2T) to wait for hw debounce counter reset
|
||||
* work correctly.
|
||||
*/
|
||||
udelay(1);
|
||||
if (unmask == 1)
|
||||
mtk_eint_unmask(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
|
||||
{
|
||||
int irq;
|
||||
|
||||
irq = irq_find_mapping(eint->domain, eint_n);
|
||||
if (!irq)
|
||||
return -EINVAL;
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
int mtk_eint_do_init(struct mtk_eint *eint)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* If clients don't assign a specific regs, let's use generic one */
|
||||
if (!eint->regs)
|
||||
eint->regs = &mtk_generic_eint_regs;
|
||||
|
||||
eint->wake_mask = devm_kcalloc(eint->dev, eint->hw->ports,
|
||||
sizeof(*eint->wake_mask), GFP_KERNEL);
|
||||
if (!eint->wake_mask)
|
||||
return -ENOMEM;
|
||||
|
||||
eint->cur_mask = devm_kcalloc(eint->dev, eint->hw->ports,
|
||||
sizeof(*eint->cur_mask), GFP_KERNEL);
|
||||
if (!eint->cur_mask)
|
||||
return -ENOMEM;
|
||||
|
||||
eint->dual_edge = devm_kcalloc(eint->dev, eint->hw->ap_num,
|
||||
sizeof(int), GFP_KERNEL);
|
||||
if (!eint->dual_edge)
|
||||
return -ENOMEM;
|
||||
|
||||
eint->domain = irq_domain_add_linear(eint->dev->of_node,
|
||||
eint->hw->ap_num,
|
||||
&irq_domain_simple_ops, NULL);
|
||||
if (!eint->domain)
|
||||
return -ENOMEM;
|
||||
|
||||
mtk_eint_hw_init(eint);
|
||||
for (i = 0; i < eint->hw->ap_num; i++) {
|
||||
int virq = irq_create_mapping(eint->domain, i);
|
||||
|
||||
irq_set_chip_and_handler(virq, &mtk_eint_irq_chip,
|
||||
handle_level_irq);
|
||||
irq_set_chip_data(virq, eint);
|
||||
}
|
||||
|
||||
irq_set_chained_handler_and_data(eint->irq, mtk_eint_irq_handler,
|
||||
eint);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2014-2018 MediaTek Inc.
|
||||
*
|
||||
* Author: Maoguang Meng <maoguang.meng@mediatek.com>
|
||||
* Sean Wang <sean.wang@mediatek.com>
|
||||
*
|
||||
*/
|
||||
#ifndef __MTK_EINT_H
|
||||
#define __MTK_EINT_H
|
||||
|
||||
#include <linux/irqdomain.h>
|
||||
|
||||
struct mtk_eint_regs {
|
||||
unsigned int stat;
|
||||
unsigned int ack;
|
||||
unsigned int mask;
|
||||
unsigned int mask_set;
|
||||
unsigned int mask_clr;
|
||||
unsigned int sens;
|
||||
unsigned int sens_set;
|
||||
unsigned int sens_clr;
|
||||
unsigned int soft;
|
||||
unsigned int soft_set;
|
||||
unsigned int soft_clr;
|
||||
unsigned int pol;
|
||||
unsigned int pol_set;
|
||||
unsigned int pol_clr;
|
||||
unsigned int dom_en;
|
||||
unsigned int dbnc_ctrl;
|
||||
unsigned int dbnc_set;
|
||||
unsigned int dbnc_clr;
|
||||
};
|
||||
|
||||
struct mtk_eint_hw {
|
||||
u8 port_mask;
|
||||
u8 ports;
|
||||
unsigned int ap_num;
|
||||
unsigned int db_cnt;
|
||||
};
|
||||
|
||||
struct mtk_eint;
|
||||
|
||||
struct mtk_eint_xt {
|
||||
int (*get_gpio_n)(void *data, unsigned long eint_n,
|
||||
unsigned int *gpio_n,
|
||||
struct gpio_chip **gpio_chip);
|
||||
int (*get_gpio_state)(void *data, unsigned long eint_n);
|
||||
int (*set_gpio_as_eint)(void *data, unsigned long eint_n);
|
||||
};
|
||||
|
||||
struct mtk_eint {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct irq_domain *domain;
|
||||
int irq;
|
||||
|
||||
int *dual_edge;
|
||||
u32 *wake_mask;
|
||||
u32 *cur_mask;
|
||||
|
||||
/* Used to fit into various EINT device */
|
||||
const struct mtk_eint_hw *hw;
|
||||
const struct mtk_eint_regs *regs;
|
||||
|
||||
/* Used to fit into various pinctrl device */
|
||||
void *pctl;
|
||||
const struct mtk_eint_xt *gpio_xlate;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_EINT_MTK)
|
||||
int mtk_eint_do_init(struct mtk_eint *eint);
|
||||
int mtk_eint_do_suspend(struct mtk_eint *eint);
|
||||
int mtk_eint_do_resume(struct mtk_eint *eint);
|
||||
int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_n,
|
||||
unsigned int debounce);
|
||||
int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n);
|
||||
|
||||
#else
|
||||
static inline int mtk_eint_do_init(struct mtk_eint *eint)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int mtk_eint_do_suspend(struct mtk_eint *eint)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int mtk_eint_do_resume(struct mtk_eint *eint)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_n,
|
||||
unsigned int debounce)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
#endif /* __MTK_EINT_H */
|
|
@ -531,31 +531,12 @@ static const struct mtk_pinctrl_devdata mt2701_pinctrl_data = {
|
|||
.port_shf = 4,
|
||||
.port_mask = 0x1f,
|
||||
.port_align = 4,
|
||||
.eint_offsets = {
|
||||
.name = "mt2701_eint",
|
||||
.stat = 0x000,
|
||||
.ack = 0x040,
|
||||
.mask = 0x080,
|
||||
.mask_set = 0x0c0,
|
||||
.mask_clr = 0x100,
|
||||
.sens = 0x140,
|
||||
.sens_set = 0x180,
|
||||
.sens_clr = 0x1c0,
|
||||
.soft = 0x200,
|
||||
.soft_set = 0x240,
|
||||
.soft_clr = 0x280,
|
||||
.pol = 0x300,
|
||||
.pol_set = 0x340,
|
||||
.pol_clr = 0x380,
|
||||
.dom_en = 0x400,
|
||||
.dbnc_ctrl = 0x500,
|
||||
.dbnc_set = 0x600,
|
||||
.dbnc_clr = 0x700,
|
||||
.eint_hw = {
|
||||
.port_mask = 6,
|
||||
.ports = 6,
|
||||
.ap_num = 169,
|
||||
.db_cnt = 16,
|
||||
},
|
||||
.ap_num = 169,
|
||||
.db_cnt = 16,
|
||||
};
|
||||
|
||||
static int mt2701_pinctrl_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -576,31 +576,12 @@ static const struct mtk_pinctrl_devdata mt2712_pinctrl_data = {
|
|||
.port_shf = 4,
|
||||
.port_mask = 0xf,
|
||||
.port_align = 4,
|
||||
.eint_offsets = {
|
||||
.name = "mt2712_eint",
|
||||
.stat = 0x000,
|
||||
.ack = 0x040,
|
||||
.mask = 0x080,
|
||||
.mask_set = 0x0c0,
|
||||
.mask_clr = 0x100,
|
||||
.sens = 0x140,
|
||||
.sens_set = 0x180,
|
||||
.sens_clr = 0x1c0,
|
||||
.soft = 0x200,
|
||||
.soft_set = 0x240,
|
||||
.soft_clr = 0x280,
|
||||
.pol = 0x300,
|
||||
.pol_set = 0x340,
|
||||
.pol_clr = 0x380,
|
||||
.dom_en = 0x400,
|
||||
.dbnc_ctrl = 0x500,
|
||||
.dbnc_set = 0x600,
|
||||
.dbnc_clr = 0x700,
|
||||
.eint_hw = {
|
||||
.port_mask = 0xf,
|
||||
.ports = 8,
|
||||
.ap_num = 229,
|
||||
.db_cnt = 40,
|
||||
},
|
||||
.ap_num = 229,
|
||||
.db_cnt = 40,
|
||||
};
|
||||
|
||||
static int mt2712_pinctrl_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
@ -30,6 +31,7 @@
|
|||
#include "../core.h"
|
||||
#include "../pinconf.h"
|
||||
#include "../pinmux.h"
|
||||
#include "mtk-eint.h"
|
||||
|
||||
#define PINCTRL_PINCTRL_DEV KBUILD_MODNAME
|
||||
#define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), }
|
||||
|
@ -123,6 +125,8 @@ struct mtk_pin_soc {
|
|||
unsigned int ngrps;
|
||||
const struct function_desc *funcs;
|
||||
unsigned int nfuncs;
|
||||
const struct mtk_eint_regs *eint_regs;
|
||||
const struct mtk_eint_hw *eint_hw;
|
||||
};
|
||||
|
||||
struct mtk_pinctrl {
|
||||
|
@ -131,6 +135,7 @@ struct mtk_pinctrl {
|
|||
struct device *dev;
|
||||
struct gpio_chip chip;
|
||||
const struct mtk_pin_soc *soc;
|
||||
struct mtk_eint *eint;
|
||||
};
|
||||
|
||||
static const struct mtk_pin_field_calc mt7622_pin_mode_range[] = {
|
||||
|
@ -913,6 +918,13 @@ static const struct pin_config_item mtk_conf_items[] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
static const struct mtk_eint_hw mt7622_eint_hw = {
|
||||
.port_mask = 7,
|
||||
.ports = 7,
|
||||
.ap_num = ARRAY_SIZE(mt7622_pins),
|
||||
.db_cnt = 20,
|
||||
};
|
||||
|
||||
static const struct mtk_pin_soc mt7622_data = {
|
||||
.reg_cal = mt7622_reg_cals,
|
||||
.pins = mt7622_pins,
|
||||
|
@ -921,6 +933,7 @@ static const struct mtk_pin_soc mt7622_data = {
|
|||
.ngrps = ARRAY_SIZE(mt7622_groups),
|
||||
.funcs = mt7622_functions,
|
||||
.nfuncs = ARRAY_SIZE(mt7622_functions),
|
||||
.eint_hw = &mt7622_eint_hw,
|
||||
};
|
||||
|
||||
static void mtk_w32(struct mtk_pinctrl *pctl, u32 reg, u32 val)
|
||||
|
@ -1441,6 +1454,32 @@ static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
|
|||
return pinctrl_gpio_direction_output(chip->base + gpio);
|
||||
}
|
||||
|
||||
static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct mtk_pinctrl *hw = gpiochip_get_data(chip);
|
||||
unsigned long eint_n;
|
||||
|
||||
eint_n = offset;
|
||||
|
||||
return mtk_eint_find_irq(hw->eint, eint_n);
|
||||
}
|
||||
|
||||
static int mtk_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
|
||||
unsigned long config)
|
||||
{
|
||||
struct mtk_pinctrl *hw = gpiochip_get_data(chip);
|
||||
unsigned long eint_n;
|
||||
u32 debounce;
|
||||
|
||||
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
|
||||
return -ENOTSUPP;
|
||||
|
||||
debounce = pinconf_to_config_argument(config);
|
||||
eint_n = offset;
|
||||
|
||||
return mtk_eint_set_debounce(hw->eint, eint_n, debounce);
|
||||
}
|
||||
|
||||
static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
|
||||
{
|
||||
struct gpio_chip *chip = &hw->chip;
|
||||
|
@ -1454,6 +1493,8 @@ static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
|
|||
chip->direction_output = mtk_gpio_direction_output;
|
||||
chip->get = mtk_gpio_get;
|
||||
chip->set = mtk_gpio_set;
|
||||
chip->to_irq = mtk_gpio_to_irq,
|
||||
chip->set_config = mtk_gpio_set_config,
|
||||
chip->base = -1;
|
||||
chip->ngpio = hw->soc->npins;
|
||||
chip->of_node = np;
|
||||
|
@ -1514,6 +1555,103 @@ static int mtk_build_functions(struct mtk_pinctrl *hw)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_xt_get_gpio_n(void *data, unsigned long eint_n,
|
||||
unsigned int *gpio_n,
|
||||
struct gpio_chip **gpio_chip)
|
||||
{
|
||||
struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
|
||||
|
||||
*gpio_chip = &hw->chip;
|
||||
*gpio_n = eint_n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_xt_get_gpio_state(void *data, unsigned long eint_n)
|
||||
{
|
||||
struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
|
||||
struct gpio_chip *gpio_chip;
|
||||
unsigned int gpio_n;
|
||||
int err;
|
||||
|
||||
err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return mtk_gpio_get(gpio_chip, gpio_n);
|
||||
}
|
||||
|
||||
static int mtk_xt_set_gpio_as_eint(void *data, unsigned long eint_n)
|
||||
{
|
||||
struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
|
||||
struct gpio_chip *gpio_chip;
|
||||
unsigned int gpio_n;
|
||||
int err;
|
||||
|
||||
err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_set_value(hw, gpio_n, PINCTRL_PIN_REG_MODE,
|
||||
MTK_GPIO_MODE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_set_value(hw, gpio_n, PINCTRL_PIN_REG_DIR, MTK_INPUT);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_set_value(hw, gpio_n, PINCTRL_PIN_REG_SMT, MTK_ENABLE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mtk_eint_xt mtk_eint_xt = {
|
||||
.get_gpio_n = mtk_xt_get_gpio_n,
|
||||
.get_gpio_state = mtk_xt_get_gpio_state,
|
||||
.set_gpio_as_eint = mtk_xt_set_gpio_as_eint,
|
||||
};
|
||||
|
||||
static int
|
||||
mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct resource *res;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_EINT_MTK))
|
||||
return 0;
|
||||
|
||||
if (!of_property_read_bool(np, "interrupt-controller"))
|
||||
return -ENODEV;
|
||||
|
||||
hw->eint = devm_kzalloc(hw->dev, sizeof(*hw->eint), GFP_KERNEL);
|
||||
if (!hw->eint)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eint");
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "Unable to get eint resource\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
hw->eint->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(hw->eint->base))
|
||||
return PTR_ERR(hw->eint->base);
|
||||
|
||||
hw->eint->irq = irq_of_parse_and_map(np, 0);
|
||||
if (!hw->eint->irq)
|
||||
return -EINVAL;
|
||||
|
||||
hw->eint->dev = &pdev->dev;
|
||||
hw->eint->hw = hw->soc->eint_hw;
|
||||
hw->eint->pctl = hw;
|
||||
hw->eint->gpio_xlate = &mtk_eint_xt;
|
||||
|
||||
return mtk_eint_do_init(hw->eint);
|
||||
}
|
||||
|
||||
static const struct of_device_id mtk_pinctrl_of_match[] = {
|
||||
{ .compatible = "mediatek,mt7622-pinctrl", .data = &mt7622_data},
|
||||
{ }
|
||||
|
@ -1577,6 +1715,11 @@ static int mtk_pinctrl_probe(struct platform_device *pdev)
|
|||
return err;
|
||||
}
|
||||
|
||||
err = mtk_build_eint(hw, pdev);
|
||||
if (err)
|
||||
dev_warn(&pdev->dev,
|
||||
"Failed to add EINT, but pinctrl still can work\n");
|
||||
|
||||
platform_set_drvdata(pdev, hw);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -300,31 +300,12 @@ static const struct mtk_pinctrl_devdata mt8127_pinctrl_data = {
|
|||
.port_shf = 4,
|
||||
.port_mask = 0xf,
|
||||
.port_align = 4,
|
||||
.eint_offsets = {
|
||||
.name = "mt8127_eint",
|
||||
.stat = 0x000,
|
||||
.ack = 0x040,
|
||||
.mask = 0x080,
|
||||
.mask_set = 0x0c0,
|
||||
.mask_clr = 0x100,
|
||||
.sens = 0x140,
|
||||
.sens_set = 0x180,
|
||||
.sens_clr = 0x1c0,
|
||||
.soft = 0x200,
|
||||
.soft_set = 0x240,
|
||||
.soft_clr = 0x280,
|
||||
.pol = 0x300,
|
||||
.pol_set = 0x340,
|
||||
.pol_clr = 0x380,
|
||||
.dom_en = 0x400,
|
||||
.dbnc_ctrl = 0x500,
|
||||
.dbnc_set = 0x600,
|
||||
.dbnc_clr = 0x700,
|
||||
.eint_hw = {
|
||||
.port_mask = 7,
|
||||
.ports = 6,
|
||||
.ap_num = 143,
|
||||
.db_cnt = 16,
|
||||
},
|
||||
.ap_num = 143,
|
||||
.db_cnt = 16,
|
||||
};
|
||||
|
||||
static int mt8127_pinctrl_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -313,31 +313,12 @@ static const struct mtk_pinctrl_devdata mt8135_pinctrl_data = {
|
|||
.port_shf = 4,
|
||||
.port_mask = 0xf,
|
||||
.port_align = 4,
|
||||
.eint_offsets = {
|
||||
.name = "mt8135_eint",
|
||||
.stat = 0x000,
|
||||
.ack = 0x040,
|
||||
.mask = 0x080,
|
||||
.mask_set = 0x0c0,
|
||||
.mask_clr = 0x100,
|
||||
.sens = 0x140,
|
||||
.sens_set = 0x180,
|
||||
.sens_clr = 0x1c0,
|
||||
.soft = 0x200,
|
||||
.soft_set = 0x240,
|
||||
.soft_clr = 0x280,
|
||||
.pol = 0x300,
|
||||
.pol_set = 0x340,
|
||||
.pol_clr = 0x380,
|
||||
.dom_en = 0x400,
|
||||
.dbnc_ctrl = 0x500,
|
||||
.dbnc_set = 0x600,
|
||||
.dbnc_clr = 0x700,
|
||||
.eint_hw = {
|
||||
.port_mask = 7,
|
||||
.ports = 6,
|
||||
.ap_num = 192,
|
||||
.db_cnt = 16,
|
||||
},
|
||||
.ap_num = 192,
|
||||
.db_cnt = 16,
|
||||
};
|
||||
|
||||
static int mt8135_pinctrl_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -340,31 +340,12 @@ static const struct mtk_pinctrl_devdata mt8173_pinctrl_data = {
|
|||
.port_shf = 4,
|
||||
.port_mask = 0xf,
|
||||
.port_align = 4,
|
||||
.eint_offsets = {
|
||||
.name = "mt8173_eint",
|
||||
.stat = 0x000,
|
||||
.ack = 0x040,
|
||||
.mask = 0x080,
|
||||
.mask_set = 0x0c0,
|
||||
.mask_clr = 0x100,
|
||||
.sens = 0x140,
|
||||
.sens_set = 0x180,
|
||||
.sens_clr = 0x1c0,
|
||||
.soft = 0x200,
|
||||
.soft_set = 0x240,
|
||||
.soft_clr = 0x280,
|
||||
.pol = 0x300,
|
||||
.pol_set = 0x340,
|
||||
.pol_clr = 0x380,
|
||||
.dom_en = 0x400,
|
||||
.dbnc_ctrl = 0x500,
|
||||
.dbnc_set = 0x600,
|
||||
.dbnc_clr = 0x700,
|
||||
.eint_hw = {
|
||||
.port_mask = 7,
|
||||
.ports = 6,
|
||||
.ap_num = 224,
|
||||
.db_cnt = 16,
|
||||
},
|
||||
.ap_num = 224,
|
||||
.db_cnt = 16,
|
||||
};
|
||||
|
||||
static int mt8173_pinctrl_probe(struct platform_device *pdev)
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "../core.h"
|
||||
#include "../pinconf.h"
|
||||
#include "../pinctrl-utils.h"
|
||||
#include "mtk-eint.h"
|
||||
#include "pinctrl-mtk-common.h"
|
||||
|
||||
#define MAX_GPIO_MODE_PER_REG 5
|
||||
|
@ -831,243 +832,38 @@ static int mtk_gpio_get(struct gpio_chip *chip, unsigned offset)
|
|||
|
||||
static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
const struct mtk_desc_pin *pin;
|
||||
struct mtk_pinctrl *pctl = gpiochip_get_data(chip);
|
||||
int irq;
|
||||
const struct mtk_desc_pin *pin;
|
||||
unsigned long eint_n;
|
||||
|
||||
pin = pctl->devdata->pins + offset;
|
||||
if (pin->eint.eintnum == NO_EINT_SUPPORT)
|
||||
return -EINVAL;
|
||||
|
||||
irq = irq_find_mapping(pctl->domain, pin->eint.eintnum);
|
||||
if (!irq)
|
||||
return -EINVAL;
|
||||
eint_n = pin->eint.eintnum;
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
static int mtk_pinctrl_irq_request_resources(struct irq_data *d)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
|
||||
const struct mtk_desc_pin *pin;
|
||||
int ret;
|
||||
|
||||
pin = mtk_find_pin_by_eint_num(pctl, d->hwirq);
|
||||
|
||||
if (!pin) {
|
||||
dev_err(pctl->dev, "Can not find pin\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = gpiochip_lock_as_irq(pctl->chip, pin->pin.number);
|
||||
if (ret) {
|
||||
dev_err(pctl->dev, "unable to lock HW IRQ %lu for IRQ\n",
|
||||
irqd_to_hwirq(d));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set mux to INT mode */
|
||||
mtk_pmx_set_mode(pctl->pctl_dev, pin->pin.number, pin->eint.eintmux);
|
||||
/* set gpio direction to input */
|
||||
mtk_pmx_gpio_set_direction(pctl->pctl_dev, NULL, pin->pin.number, true);
|
||||
/* set input-enable */
|
||||
mtk_pconf_set_ies_smt(pctl, pin->pin.number, 1, PIN_CONFIG_INPUT_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_pinctrl_irq_release_resources(struct irq_data *d)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
|
||||
const struct mtk_desc_pin *pin;
|
||||
|
||||
pin = mtk_find_pin_by_eint_num(pctl, d->hwirq);
|
||||
|
||||
if (!pin) {
|
||||
dev_err(pctl->dev, "Can not find pin\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gpiochip_unlock_as_irq(pctl->chip, pin->pin.number);
|
||||
}
|
||||
|
||||
static void __iomem *mtk_eint_get_offset(struct mtk_pinctrl *pctl,
|
||||
unsigned int eint_num, unsigned int offset)
|
||||
{
|
||||
unsigned int eint_base = 0;
|
||||
void __iomem *reg;
|
||||
|
||||
if (eint_num >= pctl->devdata->ap_num)
|
||||
eint_base = pctl->devdata->ap_num;
|
||||
|
||||
reg = pctl->eint_reg_base + offset + ((eint_num - eint_base) / 32) * 4;
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
/*
|
||||
* mtk_can_en_debounce: Check the EINT number is able to enable debounce or not
|
||||
* @eint_num: the EINT number to setmtk_pinctrl
|
||||
*/
|
||||
static unsigned int mtk_eint_can_en_debounce(struct mtk_pinctrl *pctl,
|
||||
unsigned int eint_num)
|
||||
{
|
||||
unsigned int sens;
|
||||
unsigned int bit = BIT(eint_num % 32);
|
||||
const struct mtk_eint_offsets *eint_offsets =
|
||||
&pctl->devdata->eint_offsets;
|
||||
|
||||
void __iomem *reg = mtk_eint_get_offset(pctl, eint_num,
|
||||
eint_offsets->sens);
|
||||
|
||||
if (readl(reg) & bit)
|
||||
sens = MT_LEVEL_SENSITIVE;
|
||||
else
|
||||
sens = MT_EDGE_SENSITIVE;
|
||||
|
||||
if ((eint_num < pctl->devdata->db_cnt) && (sens != MT_EDGE_SENSITIVE))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* mtk_eint_get_mask: To get the eint mask
|
||||
* @eint_num: the EINT number to get
|
||||
*/
|
||||
static unsigned int mtk_eint_get_mask(struct mtk_pinctrl *pctl,
|
||||
unsigned int eint_num)
|
||||
{
|
||||
unsigned int bit = BIT(eint_num % 32);
|
||||
const struct mtk_eint_offsets *eint_offsets =
|
||||
&pctl->devdata->eint_offsets;
|
||||
|
||||
void __iomem *reg = mtk_eint_get_offset(pctl, eint_num,
|
||||
eint_offsets->mask);
|
||||
|
||||
return !!(readl(reg) & bit);
|
||||
}
|
||||
|
||||
static int mtk_eint_flip_edge(struct mtk_pinctrl *pctl, int hwirq)
|
||||
{
|
||||
int start_level, curr_level;
|
||||
unsigned int reg_offset;
|
||||
const struct mtk_eint_offsets *eint_offsets = &(pctl->devdata->eint_offsets);
|
||||
u32 mask = BIT(hwirq & 0x1f);
|
||||
u32 port = (hwirq >> 5) & eint_offsets->port_mask;
|
||||
void __iomem *reg = pctl->eint_reg_base + (port << 2);
|
||||
const struct mtk_desc_pin *pin;
|
||||
|
||||
pin = mtk_find_pin_by_eint_num(pctl, hwirq);
|
||||
curr_level = mtk_gpio_get(pctl->chip, pin->pin.number);
|
||||
do {
|
||||
start_level = curr_level;
|
||||
if (start_level)
|
||||
reg_offset = eint_offsets->pol_clr;
|
||||
else
|
||||
reg_offset = eint_offsets->pol_set;
|
||||
writel(mask, reg + reg_offset);
|
||||
|
||||
curr_level = mtk_gpio_get(pctl->chip, pin->pin.number);
|
||||
} while (start_level != curr_level);
|
||||
|
||||
return start_level;
|
||||
}
|
||||
|
||||
static void mtk_eint_mask(struct irq_data *d)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
|
||||
const struct mtk_eint_offsets *eint_offsets =
|
||||
&pctl->devdata->eint_offsets;
|
||||
u32 mask = BIT(d->hwirq & 0x1f);
|
||||
void __iomem *reg = mtk_eint_get_offset(pctl, d->hwirq,
|
||||
eint_offsets->mask_set);
|
||||
|
||||
writel(mask, reg);
|
||||
}
|
||||
|
||||
static void mtk_eint_unmask(struct irq_data *d)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
|
||||
const struct mtk_eint_offsets *eint_offsets =
|
||||
&pctl->devdata->eint_offsets;
|
||||
u32 mask = BIT(d->hwirq & 0x1f);
|
||||
void __iomem *reg = mtk_eint_get_offset(pctl, d->hwirq,
|
||||
eint_offsets->mask_clr);
|
||||
|
||||
writel(mask, reg);
|
||||
|
||||
if (pctl->eint_dual_edges[d->hwirq])
|
||||
mtk_eint_flip_edge(pctl, d->hwirq);
|
||||
}
|
||||
|
||||
static int mtk_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
|
||||
unsigned debounce)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = dev_get_drvdata(chip->parent);
|
||||
int eint_num, virq, eint_offset;
|
||||
unsigned int set_offset, bit, clr_bit, clr_offset, rst, i, unmask, dbnc;
|
||||
static const unsigned int debounce_time[] = {500, 1000, 16000, 32000, 64000,
|
||||
128000, 256000};
|
||||
const struct mtk_desc_pin *pin;
|
||||
struct irq_data *d;
|
||||
|
||||
pin = pctl->devdata->pins + offset;
|
||||
if (pin->eint.eintnum == NO_EINT_SUPPORT)
|
||||
return -EINVAL;
|
||||
|
||||
eint_num = pin->eint.eintnum;
|
||||
virq = irq_find_mapping(pctl->domain, eint_num);
|
||||
eint_offset = (eint_num % 4) * 8;
|
||||
d = irq_get_irq_data(virq);
|
||||
|
||||
set_offset = (eint_num / 4) * 4 + pctl->devdata->eint_offsets.dbnc_set;
|
||||
clr_offset = (eint_num / 4) * 4 + pctl->devdata->eint_offsets.dbnc_clr;
|
||||
if (!mtk_eint_can_en_debounce(pctl, eint_num))
|
||||
return -ENOSYS;
|
||||
|
||||
dbnc = ARRAY_SIZE(debounce_time);
|
||||
for (i = 0; i < ARRAY_SIZE(debounce_time); i++) {
|
||||
if (debounce <= debounce_time[i]) {
|
||||
dbnc = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mtk_eint_get_mask(pctl, eint_num)) {
|
||||
mtk_eint_mask(d);
|
||||
unmask = 1;
|
||||
} else {
|
||||
unmask = 0;
|
||||
}
|
||||
|
||||
clr_bit = 0xff << eint_offset;
|
||||
writel(clr_bit, pctl->eint_reg_base + clr_offset);
|
||||
|
||||
bit = ((dbnc << EINT_DBNC_SET_DBNC_BITS) | EINT_DBNC_SET_EN) <<
|
||||
eint_offset;
|
||||
rst = EINT_DBNC_RST_BIT << eint_offset;
|
||||
writel(rst | bit, pctl->eint_reg_base + set_offset);
|
||||
|
||||
/* Delay a while (more than 2T) to wait for hw debounce counter reset
|
||||
work correctly */
|
||||
udelay(1);
|
||||
if (unmask == 1)
|
||||
mtk_eint_unmask(d);
|
||||
|
||||
return 0;
|
||||
return mtk_eint_find_irq(pctl->eint, eint_n);
|
||||
}
|
||||
|
||||
static int mtk_gpio_set_config(struct gpio_chip *chip, unsigned offset,
|
||||
unsigned long config)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = gpiochip_get_data(chip);
|
||||
const struct mtk_desc_pin *pin;
|
||||
unsigned long eint_n;
|
||||
u32 debounce;
|
||||
|
||||
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
|
||||
return -ENOTSUPP;
|
||||
|
||||
pin = pctl->devdata->pins + offset;
|
||||
if (pin->eint.eintnum == NO_EINT_SUPPORT)
|
||||
return -EINVAL;
|
||||
|
||||
debounce = pinconf_to_config_argument(config);
|
||||
return mtk_gpio_set_debounce(chip, offset, debounce);
|
||||
eint_n = pin->eint.eintnum;
|
||||
|
||||
return mtk_eint_set_debounce(pctl->eint, eint_n, debounce);
|
||||
}
|
||||
|
||||
static const struct gpio_chip mtk_gpio_chip = {
|
||||
|
@ -1084,117 +880,18 @@ static const struct gpio_chip mtk_gpio_chip = {
|
|||
.of_gpio_n_cells = 2,
|
||||
};
|
||||
|
||||
static int mtk_eint_set_type(struct irq_data *d,
|
||||
unsigned int type)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
|
||||
const struct mtk_eint_offsets *eint_offsets =
|
||||
&pctl->devdata->eint_offsets;
|
||||
u32 mask = BIT(d->hwirq & 0x1f);
|
||||
void __iomem *reg;
|
||||
|
||||
if (((type & IRQ_TYPE_EDGE_BOTH) && (type & IRQ_TYPE_LEVEL_MASK)) ||
|
||||
((type & IRQ_TYPE_LEVEL_MASK) == IRQ_TYPE_LEVEL_MASK)) {
|
||||
dev_err(pctl->dev, "Can't configure IRQ%d (EINT%lu) for type 0x%X\n",
|
||||
d->irq, d->hwirq, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
|
||||
pctl->eint_dual_edges[d->hwirq] = 1;
|
||||
else
|
||||
pctl->eint_dual_edges[d->hwirq] = 0;
|
||||
|
||||
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) {
|
||||
reg = mtk_eint_get_offset(pctl, d->hwirq,
|
||||
eint_offsets->pol_clr);
|
||||
writel(mask, reg);
|
||||
} else {
|
||||
reg = mtk_eint_get_offset(pctl, d->hwirq,
|
||||
eint_offsets->pol_set);
|
||||
writel(mask, reg);
|
||||
}
|
||||
|
||||
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
|
||||
reg = mtk_eint_get_offset(pctl, d->hwirq,
|
||||
eint_offsets->sens_clr);
|
||||
writel(mask, reg);
|
||||
} else {
|
||||
reg = mtk_eint_get_offset(pctl, d->hwirq,
|
||||
eint_offsets->sens_set);
|
||||
writel(mask, reg);
|
||||
}
|
||||
|
||||
if (pctl->eint_dual_edges[d->hwirq])
|
||||
mtk_eint_flip_edge(pctl, d->hwirq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_eint_irq_set_wake(struct irq_data *d, unsigned int on)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
|
||||
int shift = d->hwirq & 0x1f;
|
||||
int reg = d->hwirq >> 5;
|
||||
|
||||
if (on)
|
||||
pctl->wake_mask[reg] |= BIT(shift);
|
||||
else
|
||||
pctl->wake_mask[reg] &= ~BIT(shift);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_eint_chip_write_mask(const struct mtk_eint_offsets *chip,
|
||||
void __iomem *eint_reg_base, u32 *buf)
|
||||
{
|
||||
int port;
|
||||
void __iomem *reg;
|
||||
|
||||
for (port = 0; port < chip->ports; port++) {
|
||||
reg = eint_reg_base + (port << 2);
|
||||
writel_relaxed(~buf[port], reg + chip->mask_set);
|
||||
writel_relaxed(buf[port], reg + chip->mask_clr);
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_eint_chip_read_mask(const struct mtk_eint_offsets *chip,
|
||||
void __iomem *eint_reg_base, u32 *buf)
|
||||
{
|
||||
int port;
|
||||
void __iomem *reg;
|
||||
|
||||
for (port = 0; port < chip->ports; port++) {
|
||||
reg = eint_reg_base + chip->mask + (port << 2);
|
||||
buf[port] = ~readl_relaxed(reg);
|
||||
/* Mask is 0 when irq is enabled, and 1 when disabled. */
|
||||
}
|
||||
}
|
||||
|
||||
static int mtk_eint_suspend(struct device *device)
|
||||
{
|
||||
void __iomem *reg;
|
||||
struct mtk_pinctrl *pctl = dev_get_drvdata(device);
|
||||
const struct mtk_eint_offsets *eint_offsets =
|
||||
&pctl->devdata->eint_offsets;
|
||||
|
||||
reg = pctl->eint_reg_base;
|
||||
mtk_eint_chip_read_mask(eint_offsets, reg, pctl->cur_mask);
|
||||
mtk_eint_chip_write_mask(eint_offsets, reg, pctl->wake_mask);
|
||||
|
||||
return 0;
|
||||
return mtk_eint_do_suspend(pctl->eint);
|
||||
}
|
||||
|
||||
static int mtk_eint_resume(struct device *device)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = dev_get_drvdata(device);
|
||||
const struct mtk_eint_offsets *eint_offsets =
|
||||
&pctl->devdata->eint_offsets;
|
||||
|
||||
mtk_eint_chip_write_mask(eint_offsets,
|
||||
pctl->eint_reg_base, pctl->cur_mask);
|
||||
|
||||
return 0;
|
||||
return mtk_eint_do_resume(pctl->eint);
|
||||
}
|
||||
|
||||
const struct dev_pm_ops mtk_eint_pm_ops = {
|
||||
|
@ -1202,117 +899,6 @@ const struct dev_pm_ops mtk_eint_pm_ops = {
|
|||
.resume_noirq = mtk_eint_resume,
|
||||
};
|
||||
|
||||
static void mtk_eint_ack(struct irq_data *d)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = irq_data_get_irq_chip_data(d);
|
||||
const struct mtk_eint_offsets *eint_offsets =
|
||||
&pctl->devdata->eint_offsets;
|
||||
u32 mask = BIT(d->hwirq & 0x1f);
|
||||
void __iomem *reg = mtk_eint_get_offset(pctl, d->hwirq,
|
||||
eint_offsets->ack);
|
||||
|
||||
writel(mask, reg);
|
||||
}
|
||||
|
||||
static struct irq_chip mtk_pinctrl_irq_chip = {
|
||||
.name = "mt-eint",
|
||||
.irq_disable = mtk_eint_mask,
|
||||
.irq_mask = mtk_eint_mask,
|
||||
.irq_unmask = mtk_eint_unmask,
|
||||
.irq_ack = mtk_eint_ack,
|
||||
.irq_set_type = mtk_eint_set_type,
|
||||
.irq_set_wake = mtk_eint_irq_set_wake,
|
||||
.irq_request_resources = mtk_pinctrl_irq_request_resources,
|
||||
.irq_release_resources = mtk_pinctrl_irq_release_resources,
|
||||
};
|
||||
|
||||
static unsigned int mtk_eint_init(struct mtk_pinctrl *pctl)
|
||||
{
|
||||
const struct mtk_eint_offsets *eint_offsets =
|
||||
&pctl->devdata->eint_offsets;
|
||||
void __iomem *reg = pctl->eint_reg_base + eint_offsets->dom_en;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < pctl->devdata->ap_num; i += 32) {
|
||||
writel(0xffffffff, reg);
|
||||
reg += 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
mtk_eint_debounce_process(struct mtk_pinctrl *pctl, int index)
|
||||
{
|
||||
unsigned int rst, ctrl_offset;
|
||||
unsigned int bit, dbnc;
|
||||
const struct mtk_eint_offsets *eint_offsets =
|
||||
&pctl->devdata->eint_offsets;
|
||||
|
||||
ctrl_offset = (index / 4) * 4 + eint_offsets->dbnc_ctrl;
|
||||
dbnc = readl(pctl->eint_reg_base + ctrl_offset);
|
||||
bit = EINT_DBNC_SET_EN << ((index % 4) * 8);
|
||||
if ((bit & dbnc) > 0) {
|
||||
ctrl_offset = (index / 4) * 4 + eint_offsets->dbnc_set;
|
||||
rst = EINT_DBNC_RST_BIT << ((index % 4) * 8);
|
||||
writel(rst, pctl->eint_reg_base + ctrl_offset);
|
||||
}
|
||||
}
|
||||
|
||||
static void mtk_eint_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct mtk_pinctrl *pctl = irq_desc_get_handler_data(desc);
|
||||
unsigned int status, eint_num;
|
||||
int offset, index, virq;
|
||||
const struct mtk_eint_offsets *eint_offsets =
|
||||
&pctl->devdata->eint_offsets;
|
||||
void __iomem *reg = mtk_eint_get_offset(pctl, 0, eint_offsets->stat);
|
||||
int dual_edges, start_level, curr_level;
|
||||
const struct mtk_desc_pin *pin;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
for (eint_num = 0;
|
||||
eint_num < pctl->devdata->ap_num;
|
||||
eint_num += 32, reg += 4) {
|
||||
status = readl(reg);
|
||||
while (status) {
|
||||
offset = __ffs(status);
|
||||
index = eint_num + offset;
|
||||
virq = irq_find_mapping(pctl->domain, index);
|
||||
status &= ~BIT(offset);
|
||||
|
||||
dual_edges = pctl->eint_dual_edges[index];
|
||||
if (dual_edges) {
|
||||
/* Clear soft-irq in case we raised it
|
||||
last time */
|
||||
writel(BIT(offset), reg - eint_offsets->stat +
|
||||
eint_offsets->soft_clr);
|
||||
|
||||
pin = mtk_find_pin_by_eint_num(pctl, index);
|
||||
start_level = mtk_gpio_get(pctl->chip,
|
||||
pin->pin.number);
|
||||
}
|
||||
|
||||
generic_handle_irq(virq);
|
||||
|
||||
if (dual_edges) {
|
||||
curr_level = mtk_eint_flip_edge(pctl, index);
|
||||
|
||||
/* If level changed, we might lost one edge
|
||||
interrupt, raised it through soft-irq */
|
||||
if (start_level != curr_level)
|
||||
writel(BIT(offset), reg -
|
||||
eint_offsets->stat +
|
||||
eint_offsets->soft_set);
|
||||
}
|
||||
|
||||
if (index < pctl->devdata->db_cnt)
|
||||
mtk_eint_debounce_process(pctl , index);
|
||||
}
|
||||
}
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static int mtk_pctrl_build_state(struct platform_device *pdev)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = platform_get_drvdata(pdev);
|
||||
|
@ -1345,6 +931,101 @@ static int mtk_pctrl_build_state(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mtk_xt_get_gpio_n(void *data, unsigned long eint_n, unsigned int *gpio_n,
|
||||
struct gpio_chip **gpio_chip)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = (struct mtk_pinctrl *)data;
|
||||
const struct mtk_desc_pin *pin;
|
||||
|
||||
pin = mtk_find_pin_by_eint_num(pctl, eint_n);
|
||||
if (!pin)
|
||||
return -EINVAL;
|
||||
|
||||
*gpio_chip = pctl->chip;
|
||||
*gpio_n = pin->pin.number;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_xt_get_gpio_state(void *data, unsigned long eint_n)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = (struct mtk_pinctrl *)data;
|
||||
const struct mtk_desc_pin *pin;
|
||||
|
||||
pin = mtk_find_pin_by_eint_num(pctl, eint_n);
|
||||
if (!pin)
|
||||
return -EINVAL;
|
||||
|
||||
return mtk_gpio_get(pctl->chip, pin->pin.number);
|
||||
}
|
||||
|
||||
static int mtk_xt_set_gpio_as_eint(void *data, unsigned long eint_n)
|
||||
{
|
||||
struct mtk_pinctrl *pctl = (struct mtk_pinctrl *)data;
|
||||
const struct mtk_desc_pin *pin;
|
||||
|
||||
pin = mtk_find_pin_by_eint_num(pctl, eint_n);
|
||||
if (!pin)
|
||||
return -EINVAL;
|
||||
|
||||
/* set mux to INT mode */
|
||||
mtk_pmx_set_mode(pctl->pctl_dev, pin->pin.number, pin->eint.eintmux);
|
||||
/* set gpio direction to input */
|
||||
mtk_pmx_gpio_set_direction(pctl->pctl_dev, NULL, pin->pin.number,
|
||||
true);
|
||||
/* set input-enable */
|
||||
mtk_pconf_set_ies_smt(pctl, pin->pin.number, 1,
|
||||
PIN_CONFIG_INPUT_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct mtk_eint_xt mtk_eint_xt = {
|
||||
.get_gpio_n = mtk_xt_get_gpio_n,
|
||||
.get_gpio_state = mtk_xt_get_gpio_state,
|
||||
.set_gpio_as_eint = mtk_xt_set_gpio_as_eint,
|
||||
};
|
||||
|
||||
static int mtk_eint_init(struct mtk_pinctrl *pctl, struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct resource *res;
|
||||
|
||||
if (!of_property_read_bool(np, "interrupt-controller"))
|
||||
return -ENODEV;
|
||||
|
||||
pctl->eint = devm_kzalloc(pctl->dev, sizeof(*pctl->eint), GFP_KERNEL);
|
||||
if (!pctl->eint)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "Unable to get eint resource\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pctl->eint->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pctl->eint->base))
|
||||
return PTR_ERR(pctl->eint->base);
|
||||
|
||||
pctl->eint->irq = irq_of_parse_and_map(np, 0);
|
||||
if (!pctl->eint->irq)
|
||||
return -EINVAL;
|
||||
|
||||
pctl->eint->dev = &pdev->dev;
|
||||
/*
|
||||
* If pctl->eint->regs == NULL, it would fall back into using a generic
|
||||
* register map in mtk_eint_do_init calls.
|
||||
*/
|
||||
pctl->eint->regs = pctl->devdata->eint_regs;
|
||||
pctl->eint->hw = &pctl->devdata->eint_hw;
|
||||
pctl->eint->pctl = pctl;
|
||||
pctl->eint->gpio_xlate = &mtk_eint_xt;
|
||||
|
||||
return mtk_eint_do_init(pctl->eint);
|
||||
}
|
||||
|
||||
int mtk_pctrl_init(struct platform_device *pdev,
|
||||
const struct mtk_pinctrl_devdata *data,
|
||||
struct regmap *regmap)
|
||||
|
@ -1353,8 +1034,7 @@ int mtk_pctrl_init(struct platform_device *pdev,
|
|||
struct mtk_pinctrl *pctl;
|
||||
struct device_node *np = pdev->dev.of_node, *node;
|
||||
struct property *prop;
|
||||
struct resource *res;
|
||||
int i, ret, irq, ports_buf;
|
||||
int ret, i;
|
||||
|
||||
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
|
||||
if (!pctl)
|
||||
|
@ -1441,70 +1121,10 @@ int mtk_pctrl_init(struct platform_device *pdev,
|
|||
goto chip_error;
|
||||
}
|
||||
|
||||
if (!of_property_read_bool(np, "interrupt-controller"))
|
||||
return 0;
|
||||
|
||||
/* Get EINT register base from dts. */
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "Unable to get Pinctrl resource\n");
|
||||
ret = -EINVAL;
|
||||
ret = mtk_eint_init(pctl, pdev);
|
||||
if (ret)
|
||||
goto chip_error;
|
||||
}
|
||||
|
||||
pctl->eint_reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pctl->eint_reg_base)) {
|
||||
ret = -EINVAL;
|
||||
goto chip_error;
|
||||
}
|
||||
|
||||
ports_buf = pctl->devdata->eint_offsets.ports;
|
||||
pctl->wake_mask = devm_kcalloc(&pdev->dev, ports_buf,
|
||||
sizeof(*pctl->wake_mask), GFP_KERNEL);
|
||||
if (!pctl->wake_mask) {
|
||||
ret = -ENOMEM;
|
||||
goto chip_error;
|
||||
}
|
||||
|
||||
pctl->cur_mask = devm_kcalloc(&pdev->dev, ports_buf,
|
||||
sizeof(*pctl->cur_mask), GFP_KERNEL);
|
||||
if (!pctl->cur_mask) {
|
||||
ret = -ENOMEM;
|
||||
goto chip_error;
|
||||
}
|
||||
|
||||
pctl->eint_dual_edges = devm_kcalloc(&pdev->dev, pctl->devdata->ap_num,
|
||||
sizeof(int), GFP_KERNEL);
|
||||
if (!pctl->eint_dual_edges) {
|
||||
ret = -ENOMEM;
|
||||
goto chip_error;
|
||||
}
|
||||
|
||||
irq = irq_of_parse_and_map(np, 0);
|
||||
if (!irq) {
|
||||
dev_err(&pdev->dev, "couldn't parse and map irq\n");
|
||||
ret = -EINVAL;
|
||||
goto chip_error;
|
||||
}
|
||||
|
||||
pctl->domain = irq_domain_add_linear(np,
|
||||
pctl->devdata->ap_num, &irq_domain_simple_ops, NULL);
|
||||
if (!pctl->domain) {
|
||||
dev_err(&pdev->dev, "Couldn't register IRQ domain\n");
|
||||
ret = -ENOMEM;
|
||||
goto chip_error;
|
||||
}
|
||||
|
||||
mtk_eint_init(pctl);
|
||||
for (i = 0; i < pctl->devdata->ap_num; i++) {
|
||||
int virq = irq_create_mapping(pctl->domain, i);
|
||||
|
||||
irq_set_chip_and_handler(virq, &mtk_pinctrl_irq_chip,
|
||||
handle_level_irq);
|
||||
irq_set_chip_data(virq, pctl);
|
||||
}
|
||||
|
||||
irq_set_chained_handler_and_data(irq, mtk_eint_irq_handler, pctl);
|
||||
return 0;
|
||||
|
||||
chip_error:
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <linux/regmap.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
|
||||
#include "mtk-eint.h"
|
||||
|
||||
#define NO_EINT_SUPPORT 255
|
||||
#define MT_EDGE_SENSITIVE 0
|
||||
#define MT_LEVEL_SENSITIVE 1
|
||||
|
@ -258,9 +260,8 @@ struct mtk_pinctrl_devdata {
|
|||
unsigned char port_shf;
|
||||
unsigned char port_mask;
|
||||
unsigned char port_align;
|
||||
struct mtk_eint_offsets eint_offsets;
|
||||
unsigned int ap_num;
|
||||
unsigned int db_cnt;
|
||||
struct mtk_eint_hw eint_hw;
|
||||
struct mtk_eint_regs *eint_regs;
|
||||
};
|
||||
|
||||
struct mtk_pinctrl {
|
||||
|
@ -274,11 +275,7 @@ struct mtk_pinctrl {
|
|||
const char **grp_names;
|
||||
struct pinctrl_dev *pctl_dev;
|
||||
const struct mtk_pinctrl_devdata *devdata;
|
||||
void __iomem *eint_reg_base;
|
||||
struct irq_domain *domain;
|
||||
int *eint_dual_edges;
|
||||
u32 *wake_mask;
|
||||
u32 *cur_mask;
|
||||
struct mtk_eint *eint;
|
||||
};
|
||||
|
||||
int mtk_pctrl_init(struct platform_device *pdev,
|
||||
|
|
|
@ -312,6 +312,47 @@ static const unsigned int pdm_din1_pins[] = {GPIOA_16};
|
|||
static const unsigned int pdm_din2_pins[] = {GPIOA_17};
|
||||
static const unsigned int pdm_din3_pins[] = {GPIOA_18};
|
||||
|
||||
/* mclk */
|
||||
static const unsigned int mclk_c_pins[] = {GPIOA_0};
|
||||
static const unsigned int mclk_b_pins[] = {GPIOA_1};
|
||||
|
||||
/* tdm */
|
||||
static const unsigned int tdma_sclk_pins[] = {GPIOX_12};
|
||||
static const unsigned int tdma_sclk_slv_pins[] = {GPIOX_12};
|
||||
static const unsigned int tdma_fs_pins[] = {GPIOX_13};
|
||||
static const unsigned int tdma_fs_slv_pins[] = {GPIOX_13};
|
||||
static const unsigned int tdma_din0_pins[] = {GPIOX_14};
|
||||
static const unsigned int tdma_dout0_x14_pins[] = {GPIOX_14};
|
||||
static const unsigned int tdma_dout0_x15_pins[] = {GPIOX_15};
|
||||
static const unsigned int tdma_dout1_pins[] = {GPIOX_15};
|
||||
static const unsigned int tdma_din1_pins[] = {GPIOX_15};
|
||||
|
||||
static const unsigned int tdmc_sclk_pins[] = {GPIOA_2};
|
||||
static const unsigned int tdmc_sclk_slv_pins[] = {GPIOA_2};
|
||||
static const unsigned int tdmc_fs_pins[] = {GPIOA_3};
|
||||
static const unsigned int tdmc_fs_slv_pins[] = {GPIOA_3};
|
||||
static const unsigned int tdmc_din0_pins[] = {GPIOA_4};
|
||||
static const unsigned int tdmc_dout0_pins[] = {GPIOA_4};
|
||||
static const unsigned int tdmc_din1_pins[] = {GPIOA_5};
|
||||
static const unsigned int tdmc_dout1_pins[] = {GPIOA_5};
|
||||
static const unsigned int tdmc_din2_pins[] = {GPIOA_6};
|
||||
static const unsigned int tdmc_dout2_pins[] = {GPIOA_6};
|
||||
static const unsigned int tdmc_din3_pins[] = {GPIOA_7};
|
||||
static const unsigned int tdmc_dout3_pins[] = {GPIOA_7};
|
||||
|
||||
static const unsigned int tdmb_sclk_pins[] = {GPIOA_8};
|
||||
static const unsigned int tdmb_sclk_slv_pins[] = {GPIOA_8};
|
||||
static const unsigned int tdmb_fs_pins[] = {GPIOA_9};
|
||||
static const unsigned int tdmb_fs_slv_pins[] = {GPIOA_9};
|
||||
static const unsigned int tdmb_din0_pins[] = {GPIOA_10};
|
||||
static const unsigned int tdmb_dout0_pins[] = {GPIOA_10};
|
||||
static const unsigned int tdmb_din1_pins[] = {GPIOA_11};
|
||||
static const unsigned int tdmb_dout1_pins[] = {GPIOA_11};
|
||||
static const unsigned int tdmb_din2_pins[] = {GPIOA_12};
|
||||
static const unsigned int tdmb_dout2_pins[] = {GPIOA_12};
|
||||
static const unsigned int tdmb_din3_pins[] = {GPIOA_13};
|
||||
static const unsigned int tdmb_dout3_pins[] = {GPIOA_13};
|
||||
|
||||
static struct meson_pmx_group meson_axg_periphs_groups[] = {
|
||||
GPIO_GROUP(GPIOZ_0),
|
||||
GPIO_GROUP(GPIOZ_1),
|
||||
|
@ -495,6 +536,15 @@ static struct meson_pmx_group meson_axg_periphs_groups[] = {
|
|||
GROUP(eth_rx_dv_x, 4),
|
||||
GROUP(eth_mdio_x, 4),
|
||||
GROUP(eth_mdc_x, 4),
|
||||
GROUP(tdma_sclk, 1),
|
||||
GROUP(tdma_sclk_slv, 2),
|
||||
GROUP(tdma_fs, 1),
|
||||
GROUP(tdma_fs_slv, 2),
|
||||
GROUP(tdma_din0, 1),
|
||||
GROUP(tdma_dout0_x14, 2),
|
||||
GROUP(tdma_dout0_x15, 1),
|
||||
GROUP(tdma_dout1, 2),
|
||||
GROUP(tdma_din1, 3),
|
||||
|
||||
/* bank GPIOY */
|
||||
GROUP(eth_txd0_y, 1),
|
||||
|
@ -544,6 +594,32 @@ static struct meson_pmx_group meson_axg_periphs_groups[] = {
|
|||
GROUP(pdm_din1, 1),
|
||||
GROUP(pdm_din2, 1),
|
||||
GROUP(pdm_din3, 1),
|
||||
GROUP(mclk_c, 1),
|
||||
GROUP(mclk_b, 1),
|
||||
GROUP(tdmc_sclk, 1),
|
||||
GROUP(tdmc_sclk_slv, 2),
|
||||
GROUP(tdmc_fs, 1),
|
||||
GROUP(tdmc_fs_slv, 2),
|
||||
GROUP(tdmc_din0, 2),
|
||||
GROUP(tdmc_dout0, 1),
|
||||
GROUP(tdmc_din1, 2),
|
||||
GROUP(tdmc_dout1, 1),
|
||||
GROUP(tdmc_din2, 2),
|
||||
GROUP(tdmc_dout2, 1),
|
||||
GROUP(tdmc_din3, 2),
|
||||
GROUP(tdmc_dout3, 1),
|
||||
GROUP(tdmb_sclk, 1),
|
||||
GROUP(tdmb_sclk_slv, 2),
|
||||
GROUP(tdmb_fs, 1),
|
||||
GROUP(tdmb_fs_slv, 2),
|
||||
GROUP(tdmb_din0, 2),
|
||||
GROUP(tdmb_dout0, 1),
|
||||
GROUP(tdmb_din1, 2),
|
||||
GROUP(tdmb_dout1, 1),
|
||||
GROUP(tdmb_din2, 2),
|
||||
GROUP(tdmb_dout2, 1),
|
||||
GROUP(tdmb_din3, 2),
|
||||
GROUP(tdmb_dout3, 1),
|
||||
};
|
||||
|
||||
/* uart_ao_a */
|
||||
|
@ -845,6 +921,32 @@ static const char * const jtag_ao_groups[] = {
|
|||
"jtag_ao_tdi", "jtag_ao_tdo", "jtag_ao_clk", "jtag_ao_tms",
|
||||
};
|
||||
|
||||
static const char * const mclk_c_groups[] = {
|
||||
"mclk_c",
|
||||
};
|
||||
|
||||
static const char * const mclk_b_groups[] = {
|
||||
"mclk_b",
|
||||
};
|
||||
|
||||
static const char * const tdma_groups[] = {
|
||||
"tdma_sclk", "tdma_sclk_slv", "tdma_fs", "tdma_fs_slv",
|
||||
"tdma_din0", "tdma_dout0_x14", "tdma_dout0_x15", "tdma_dout1",
|
||||
"tdma_din1",
|
||||
};
|
||||
|
||||
static const char * const tdmc_groups[] = {
|
||||
"tdmc_sclk", "tdmc_sclk_slv", "tdmc_fs", "tdmc_fs_slv",
|
||||
"tdmc_din0", "tdmc_dout0", "tdmc_din1", "tdmc_dout1",
|
||||
"tdmc_din2", "tdmc_dout2", "tdmc_din3", "tdmc_dout3",
|
||||
};
|
||||
|
||||
static const char * const tdmb_groups[] = {
|
||||
"tdmb_sclk", "tdmb_sclk_slv", "tdmb_fs", "tdmb_fs_slv",
|
||||
"tdmb_din0", "tdmb_dout0", "tdmb_din1", "tdmb_dout1",
|
||||
"tdmb_din2", "tdmb_dout2", "tdmb_din3", "tdmb_dout3",
|
||||
};
|
||||
|
||||
static struct meson_pmx_func meson_axg_periphs_functions[] = {
|
||||
FUNCTION(gpio_periphs),
|
||||
FUNCTION(emmc),
|
||||
|
@ -870,6 +972,11 @@ static struct meson_pmx_func meson_axg_periphs_functions[] = {
|
|||
FUNCTION(spdif_in),
|
||||
FUNCTION(jtag_ee),
|
||||
FUNCTION(pdm),
|
||||
FUNCTION(mclk_b),
|
||||
FUNCTION(mclk_c),
|
||||
FUNCTION(tdma),
|
||||
FUNCTION(tdmb),
|
||||
FUNCTION(tdmc),
|
||||
};
|
||||
|
||||
static struct meson_pmx_func meson_axg_aobus_functions[] = {
|
||||
|
|
|
@ -627,8 +627,8 @@ static const char * const sdio_groups[] = {
|
|||
};
|
||||
|
||||
static const char * const nand_groups[] = {
|
||||
"nand_ce0", "nand_ce1", "nand_rb0", "nand_ale", "nand_cle",
|
||||
"nand_wen_clk", "nand_ren_wr", "nand_dqs",
|
||||
"emmc_nand_d07", "nand_ce0", "nand_ce1", "nand_rb0", "nand_ale",
|
||||
"nand_cle", "nand_wen_clk", "nand_ren_wr", "nand_dqs",
|
||||
};
|
||||
|
||||
static const char * const uart_a_groups[] = {
|
||||
|
|
|
@ -617,8 +617,8 @@ static const char * const sdio_groups[] = {
|
|||
};
|
||||
|
||||
static const char * const nand_groups[] = {
|
||||
"nand_ce0", "nand_ce1", "nand_rb0", "nand_ale", "nand_cle",
|
||||
"nand_wen_clk", "nand_ren_wr", "nand_dqs",
|
||||
"emmc_nand_d07", "nand_ce0", "nand_ce1", "nand_rb0", "nand_ale",
|
||||
"nand_cle", "nand_wen_clk", "nand_ren_wr", "nand_dqs",
|
||||
};
|
||||
|
||||
static const char * const uart_a_groups[] = {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Pin controller and GPIO driver for Amlogic Meson8.
|
||||
* Pin controller and GPIO driver for Amlogic Meson8 and Meson8m2.
|
||||
*
|
||||
* Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
|
||||
*
|
||||
|
@ -299,6 +299,10 @@ static const unsigned int spi_mosi_1_pins[] = { GPIOZ_12 };
|
|||
static const unsigned int spi_miso_1_pins[] = { GPIOZ_13 };
|
||||
static const unsigned int spi_ss2_1_pins[] = { GPIOZ_14 };
|
||||
|
||||
static const unsigned int eth_txd3_pins[] = { GPIOZ_0 };
|
||||
static const unsigned int eth_txd2_pins[] = { GPIOZ_1 };
|
||||
static const unsigned int eth_rxd3_pins[] = { GPIOZ_2 };
|
||||
static const unsigned int eth_rxd2_pins[] = { GPIOZ_3 };
|
||||
static const unsigned int eth_tx_clk_50m_pins[] = { GPIOZ_4 };
|
||||
static const unsigned int eth_tx_en_pins[] = { GPIOZ_5 };
|
||||
static const unsigned int eth_txd1_pins[] = { GPIOZ_6 };
|
||||
|
@ -650,6 +654,12 @@ static struct meson_pmx_group meson8_cbus_groups[] = {
|
|||
GROUP(eth_mdio, 6, 6),
|
||||
GROUP(eth_mdc, 6, 5),
|
||||
|
||||
/* NOTE: the following four groups are only available on Meson8m2: */
|
||||
GROUP(eth_rxd2, 6, 3),
|
||||
GROUP(eth_rxd3, 6, 2),
|
||||
GROUP(eth_txd2, 6, 1),
|
||||
GROUP(eth_txd3, 6, 0),
|
||||
|
||||
GROUP(i2c_sda_a0, 5, 31),
|
||||
GROUP(i2c_sck_a0, 5, 30),
|
||||
|
||||
|
@ -877,7 +887,8 @@ static const char * const spi_groups[] = {
|
|||
static const char * const ethernet_groups[] = {
|
||||
"eth_tx_clk_50m", "eth_tx_en", "eth_txd1",
|
||||
"eth_txd0", "eth_rx_clk_in", "eth_rx_dv",
|
||||
"eth_rxd1", "eth_rxd0", "eth_mdio", "eth_mdc"
|
||||
"eth_rxd1", "eth_rxd0", "eth_mdio", "eth_mdc", "eth_rxd2",
|
||||
"eth_rxd3", "eth_txd2", "eth_txd3"
|
||||
};
|
||||
|
||||
static const char * const i2c_a_groups[] = {
|
||||
|
@ -1080,6 +1091,14 @@ static const struct of_device_id meson8_pinctrl_dt_match[] = {
|
|||
.compatible = "amlogic,meson8-aobus-pinctrl",
|
||||
.data = &meson8_aobus_pinctrl_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,meson8m2-cbus-pinctrl",
|
||||
.data = &meson8_cbus_pinctrl_data,
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,meson8m2-aobus-pinctrl",
|
||||
.data = &meson8_aobus_pinctrl_data,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
|
|
|
@ -214,18 +214,6 @@ static inline void armada_37xx_update_reg(unsigned int *reg,
|
|||
}
|
||||
}
|
||||
|
||||
static int armada_37xx_get_func_reg(struct armada_37xx_pin_group *grp,
|
||||
const char *func)
|
||||
{
|
||||
int f;
|
||||
|
||||
for (f = 0; (f < NB_FUNCS) && grp->funcs[f]; f++)
|
||||
if (!strcmp(grp->funcs[f], func))
|
||||
return f;
|
||||
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static struct armada_37xx_pin_group *armada_37xx_find_next_grp_by_pin(
|
||||
struct armada_37xx_pinctrl *info, int pin, int *grp)
|
||||
{
|
||||
|
@ -344,10 +332,9 @@ static int armada_37xx_pmx_set_by_name(struct pinctrl_dev *pctldev,
|
|||
dev_dbg(info->dev, "enable function %s group %s\n",
|
||||
name, grp->name);
|
||||
|
||||
func = armada_37xx_get_func_reg(grp, name);
|
||||
|
||||
func = match_string(grp->funcs, NB_FUNCS, name);
|
||||
if (func < 0)
|
||||
return func;
|
||||
return -ENOTSUPP;
|
||||
|
||||
val = grp->val[func];
|
||||
|
||||
|
@ -679,12 +666,13 @@ static void armada_37xx_irq_handler(struct irq_desc *desc)
|
|||
writel(1 << hwirq,
|
||||
info->base +
|
||||
IRQ_STATUS + 4 * i);
|
||||
continue;
|
||||
goto update_status;
|
||||
}
|
||||
}
|
||||
|
||||
generic_handle_irq(virq);
|
||||
|
||||
update_status:
|
||||
/* Update status in case a new IRQ appears */
|
||||
spin_lock_irqsave(&info->irq_lock, flags);
|
||||
status = readl_relaxed(info->base +
|
||||
|
@ -932,12 +920,12 @@ static int armada_37xx_fill_func(struct armada_37xx_pinctrl *info)
|
|||
struct armada_37xx_pin_group *gp = &info->groups[g];
|
||||
int f;
|
||||
|
||||
for (f = 0; (f < NB_FUNCS) && gp->funcs[f]; f++) {
|
||||
if (strcmp(gp->funcs[f], name) == 0) {
|
||||
*groups = gp->name;
|
||||
groups++;
|
||||
}
|
||||
}
|
||||
f = match_string(gp->funcs, NB_FUNCS, name);
|
||||
if (f < 0)
|
||||
continue;
|
||||
|
||||
*groups = gp->name;
|
||||
groups++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -431,40 +431,40 @@ static struct mvebu_mpp_mode mv98dx3236_mpp_modes[] = {
|
|||
MPP_MODE(19,
|
||||
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x4, "dev", "rb", V_98DX3236_PLUS)),
|
||||
MPP_VAR_FUNCTION(0x4, "nand", "rb", V_98DX3236_PLUS)),
|
||||
MPP_MODE(20,
|
||||
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x4, "dev", "we0", V_98DX3236_PLUS)),
|
||||
MPP_MODE(21,
|
||||
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x1, "dev", "ad0", V_98DX3236_PLUS)),
|
||||
MPP_VAR_FUNCTION(0x4, "dev", "ad0", V_98DX3236_PLUS)),
|
||||
MPP_MODE(22,
|
||||
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x1, "dev", "ad1", V_98DX3236_PLUS)),
|
||||
MPP_VAR_FUNCTION(0x4, "dev", "ad1", V_98DX3236_PLUS)),
|
||||
MPP_MODE(23,
|
||||
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x1, "dev", "ad2", V_98DX3236_PLUS)),
|
||||
MPP_VAR_FUNCTION(0x4, "dev", "ad2", V_98DX3236_PLUS)),
|
||||
MPP_MODE(24,
|
||||
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x1, "dev", "ad3", V_98DX3236_PLUS)),
|
||||
MPP_VAR_FUNCTION(0x4, "dev", "ad3", V_98DX3236_PLUS)),
|
||||
MPP_MODE(25,
|
||||
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x1, "dev", "ad4", V_98DX3236_PLUS)),
|
||||
MPP_VAR_FUNCTION(0x4, "dev", "ad4", V_98DX3236_PLUS)),
|
||||
MPP_MODE(26,
|
||||
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x1, "dev", "ad5", V_98DX3236_PLUS)),
|
||||
MPP_VAR_FUNCTION(0x4, "dev", "ad5", V_98DX3236_PLUS)),
|
||||
MPP_MODE(27,
|
||||
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x1, "dev", "ad6", V_98DX3236_PLUS)),
|
||||
MPP_VAR_FUNCTION(0x4, "dev", "ad6", V_98DX3236_PLUS)),
|
||||
MPP_MODE(28,
|
||||
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x1, "dev", "ad7", V_98DX3236_PLUS)),
|
||||
MPP_VAR_FUNCTION(0x4, "dev", "ad7", V_98DX3236_PLUS)),
|
||||
MPP_MODE(29,
|
||||
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x1, "dev", "a0", V_98DX3236_PLUS)),
|
||||
MPP_VAR_FUNCTION(0x4, "dev", "a0", V_98DX3236_PLUS)),
|
||||
MPP_MODE(30,
|
||||
MPP_VAR_FUNCTION(0x0, "gpo", NULL, V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x1, "dev", "a1", V_98DX3236_PLUS)),
|
||||
MPP_VAR_FUNCTION(0x4, "dev", "a1", V_98DX3236_PLUS)),
|
||||
MPP_MODE(31,
|
||||
MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_98DX3236_PLUS),
|
||||
MPP_VAR_FUNCTION(0x1, "slv_smi", "mdc", V_98DX3236_PLUS),
|
||||
|
|
|
@ -576,8 +576,10 @@ static int atmel_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
|||
for_each_child_of_node(np_config, np) {
|
||||
ret = atmel_pctl_dt_subnode_to_map(pctldev, np, map,
|
||||
&reserved_maps, num_maps);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
of_node_put(np);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#define GPIO_LS_SYNC 0x60
|
||||
|
||||
enum rockchip_pinctrl_type {
|
||||
PX30,
|
||||
RV1108,
|
||||
RK2928,
|
||||
RK3066B,
|
||||
|
@ -701,6 +702,66 @@ static void rockchip_get_recalced_mux(struct rockchip_pin_bank *bank, int pin,
|
|||
*bit = data->bit;
|
||||
}
|
||||
|
||||
static struct rockchip_mux_route_data px30_mux_route_data[] = {
|
||||
{
|
||||
/* cif-d2m0 */
|
||||
.bank_num = 2,
|
||||
.pin = 0,
|
||||
.func = 1,
|
||||
.route_offset = 0x184,
|
||||
.route_val = BIT(16 + 7),
|
||||
}, {
|
||||
/* cif-d2m1 */
|
||||
.bank_num = 3,
|
||||
.pin = 3,
|
||||
.func = 3,
|
||||
.route_offset = 0x184,
|
||||
.route_val = BIT(16 + 7) | BIT(7),
|
||||
}, {
|
||||
/* pdm-m0 */
|
||||
.bank_num = 3,
|
||||
.pin = 22,
|
||||
.func = 2,
|
||||
.route_offset = 0x184,
|
||||
.route_val = BIT(16 + 8),
|
||||
}, {
|
||||
/* pdm-m1 */
|
||||
.bank_num = 2,
|
||||
.pin = 22,
|
||||
.func = 1,
|
||||
.route_offset = 0x184,
|
||||
.route_val = BIT(16 + 8) | BIT(8),
|
||||
}, {
|
||||
/* uart2-rxm0 */
|
||||
.bank_num = 1,
|
||||
.pin = 27,
|
||||
.func = 2,
|
||||
.route_offset = 0x184,
|
||||
.route_val = BIT(16 + 10),
|
||||
}, {
|
||||
/* uart2-rxm1 */
|
||||
.bank_num = 2,
|
||||
.pin = 14,
|
||||
.func = 2,
|
||||
.route_offset = 0x184,
|
||||
.route_val = BIT(16 + 10) | BIT(10),
|
||||
}, {
|
||||
/* uart3-rxm0 */
|
||||
.bank_num = 0,
|
||||
.pin = 17,
|
||||
.func = 2,
|
||||
.route_offset = 0x184,
|
||||
.route_val = BIT(16 + 9),
|
||||
}, {
|
||||
/* uart3-rxm1 */
|
||||
.bank_num = 1,
|
||||
.pin = 15,
|
||||
.func = 2,
|
||||
.route_offset = 0x184,
|
||||
.route_val = BIT(16 + 9) | BIT(9),
|
||||
},
|
||||
};
|
||||
|
||||
static struct rockchip_mux_route_data rk3128_mux_route_data[] = {
|
||||
{
|
||||
/* spi-0 */
|
||||
|
@ -1202,6 +1263,97 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define PX30_PULL_PMU_OFFSET 0x10
|
||||
#define PX30_PULL_GRF_OFFSET 0x60
|
||||
#define PX30_PULL_BITS_PER_PIN 2
|
||||
#define PX30_PULL_PINS_PER_REG 8
|
||||
#define PX30_PULL_BANK_STRIDE 16
|
||||
|
||||
static void px30_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
|
||||
int pin_num, struct regmap **regmap,
|
||||
int *reg, u8 *bit)
|
||||
{
|
||||
struct rockchip_pinctrl *info = bank->drvdata;
|
||||
|
||||
/* The first 32 pins of the first bank are located in PMU */
|
||||
if (bank->bank_num == 0) {
|
||||
*regmap = info->regmap_pmu;
|
||||
*reg = PX30_PULL_PMU_OFFSET;
|
||||
} else {
|
||||
*regmap = info->regmap_base;
|
||||
*reg = PX30_PULL_GRF_OFFSET;
|
||||
|
||||
/* correct the offset, as we're starting with the 2nd bank */
|
||||
*reg -= 0x10;
|
||||
*reg += bank->bank_num * PX30_PULL_BANK_STRIDE;
|
||||
}
|
||||
|
||||
*reg += ((pin_num / PX30_PULL_PINS_PER_REG) * 4);
|
||||
*bit = (pin_num % PX30_PULL_PINS_PER_REG);
|
||||
*bit *= PX30_PULL_BITS_PER_PIN;
|
||||
}
|
||||
|
||||
#define PX30_DRV_PMU_OFFSET 0x20
|
||||
#define PX30_DRV_GRF_OFFSET 0xf0
|
||||
#define PX30_DRV_BITS_PER_PIN 2
|
||||
#define PX30_DRV_PINS_PER_REG 8
|
||||
#define PX30_DRV_BANK_STRIDE 16
|
||||
|
||||
static void px30_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
|
||||
int pin_num, struct regmap **regmap,
|
||||
int *reg, u8 *bit)
|
||||
{
|
||||
struct rockchip_pinctrl *info = bank->drvdata;
|
||||
|
||||
/* The first 32 pins of the first bank are located in PMU */
|
||||
if (bank->bank_num == 0) {
|
||||
*regmap = info->regmap_pmu;
|
||||
*reg = PX30_DRV_PMU_OFFSET;
|
||||
} else {
|
||||
*regmap = info->regmap_base;
|
||||
*reg = PX30_DRV_GRF_OFFSET;
|
||||
|
||||
/* correct the offset, as we're starting with the 2nd bank */
|
||||
*reg -= 0x10;
|
||||
*reg += bank->bank_num * PX30_DRV_BANK_STRIDE;
|
||||
}
|
||||
|
||||
*reg += ((pin_num / PX30_DRV_PINS_PER_REG) * 4);
|
||||
*bit = (pin_num % PX30_DRV_PINS_PER_REG);
|
||||
*bit *= PX30_DRV_BITS_PER_PIN;
|
||||
}
|
||||
|
||||
#define PX30_SCHMITT_PMU_OFFSET 0x38
|
||||
#define PX30_SCHMITT_GRF_OFFSET 0xc0
|
||||
#define PX30_SCHMITT_PINS_PER_PMU_REG 16
|
||||
#define PX30_SCHMITT_BANK_STRIDE 16
|
||||
#define PX30_SCHMITT_PINS_PER_GRF_REG 8
|
||||
|
||||
static int px30_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
|
||||
int pin_num,
|
||||
struct regmap **regmap,
|
||||
int *reg, u8 *bit)
|
||||
{
|
||||
struct rockchip_pinctrl *info = bank->drvdata;
|
||||
int pins_per_reg;
|
||||
|
||||
if (bank->bank_num == 0) {
|
||||
*regmap = info->regmap_pmu;
|
||||
*reg = PX30_SCHMITT_PMU_OFFSET;
|
||||
pins_per_reg = PX30_SCHMITT_PINS_PER_PMU_REG;
|
||||
} else {
|
||||
*regmap = info->regmap_base;
|
||||
*reg = PX30_SCHMITT_GRF_OFFSET;
|
||||
pins_per_reg = PX30_SCHMITT_PINS_PER_GRF_REG;
|
||||
*reg += (bank->bank_num - 1) * PX30_SCHMITT_BANK_STRIDE;
|
||||
}
|
||||
|
||||
*reg += ((pin_num / pins_per_reg) * 4);
|
||||
*bit = pin_num % pins_per_reg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RV1108_PULL_PMU_OFFSET 0x10
|
||||
#define RV1108_PULL_OFFSET 0x110
|
||||
#define RV1108_PULL_PINS_PER_REG 8
|
||||
|
@ -1798,6 +1950,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
|
|||
return !(data & BIT(bit))
|
||||
? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT
|
||||
: PIN_CONFIG_BIAS_DISABLE;
|
||||
case PX30:
|
||||
case RV1108:
|
||||
case RK3188:
|
||||
case RK3288:
|
||||
|
@ -1841,6 +1994,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
|
|||
data |= BIT(bit);
|
||||
ret = regmap_write(regmap, reg, data);
|
||||
break;
|
||||
case PX30:
|
||||
case RV1108:
|
||||
case RK3188:
|
||||
case RK3288:
|
||||
|
@ -2103,6 +2257,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
|
|||
pull == PIN_CONFIG_BIAS_DISABLE);
|
||||
case RK3066B:
|
||||
return pull ? false : true;
|
||||
case PX30:
|
||||
case RV1108:
|
||||
case RK3188:
|
||||
case RK3288:
|
||||
|
@ -2555,6 +2710,57 @@ static int rockchip_gpio_direction_output(struct gpio_chip *gc,
|
|||
return pinctrl_gpio_direction_output(gc->base + offset);
|
||||
}
|
||||
|
||||
static void rockchip_gpio_set_debounce(struct gpio_chip *gc,
|
||||
unsigned int offset, bool enable)
|
||||
{
|
||||
struct rockchip_pin_bank *bank = gpiochip_get_data(gc);
|
||||
void __iomem *reg = bank->reg_base + GPIO_DEBOUNCE;
|
||||
unsigned long flags;
|
||||
u32 data;
|
||||
|
||||
clk_enable(bank->clk);
|
||||
raw_spin_lock_irqsave(&bank->slock, flags);
|
||||
|
||||
data = readl(reg);
|
||||
if (enable)
|
||||
data |= BIT(offset);
|
||||
else
|
||||
data &= ~BIT(offset);
|
||||
writel(data, reg);
|
||||
|
||||
raw_spin_unlock_irqrestore(&bank->slock, flags);
|
||||
clk_disable(bank->clk);
|
||||
}
|
||||
|
||||
/*
|
||||
* gpiolib set_config callback function. The setting of the pin
|
||||
* mux function as 'gpio output' will be handled by the pinctrl subsystem
|
||||
* interface.
|
||||
*/
|
||||
static int rockchip_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
|
||||
unsigned long config)
|
||||
{
|
||||
enum pin_config_param param = pinconf_to_config_param(config);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_INPUT_DEBOUNCE:
|
||||
rockchip_gpio_set_debounce(gc, offset, true);
|
||||
/*
|
||||
* Rockchip's gpio could only support up to one period
|
||||
* of the debounce clock(pclk), which is far away from
|
||||
* satisftying the requirement, as pclk is usually near
|
||||
* 100MHz shared by all peripherals. So the fact is it
|
||||
* has crippled debounce capability could only be useful
|
||||
* to prevent any spurious glitches from waking up the system
|
||||
* if the gpio is conguired as wakeup interrupt source. Let's
|
||||
* still return -ENOTSUPP as before, to make sure the caller
|
||||
* of gpiod_set_debounce won't change its behaviour.
|
||||
*/
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin
|
||||
* and a virtual IRQ, if not already present.
|
||||
|
@ -2580,6 +2786,7 @@ static const struct gpio_chip rockchip_gpiolib_chip = {
|
|||
.get_direction = rockchip_gpio_get_direction,
|
||||
.direction_input = rockchip_gpio_direction_input,
|
||||
.direction_output = rockchip_gpio_direction_output,
|
||||
.set_config = rockchip_gpio_set_config,
|
||||
.to_irq = rockchip_gpio_to_irq,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
@ -3237,6 +3444,43 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct rockchip_pin_bank px30_pin_banks[] = {
|
||||
PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
|
||||
IOMUX_SOURCE_PMU,
|
||||
IOMUX_SOURCE_PMU,
|
||||
IOMUX_SOURCE_PMU
|
||||
),
|
||||
PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT
|
||||
),
|
||||
PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT
|
||||
),
|
||||
PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT
|
||||
),
|
||||
};
|
||||
|
||||
static struct rockchip_pin_ctrl px30_pin_ctrl = {
|
||||
.pin_banks = px30_pin_banks,
|
||||
.nr_banks = ARRAY_SIZE(px30_pin_banks),
|
||||
.label = "PX30-GPIO",
|
||||
.type = PX30,
|
||||
.grf_mux_offset = 0x0,
|
||||
.pmu_mux_offset = 0x0,
|
||||
.iomux_routes = px30_mux_route_data,
|
||||
.niomux_routes = ARRAY_SIZE(px30_mux_route_data),
|
||||
.pull_calc_reg = px30_calc_pull_reg_and_bit,
|
||||
.drv_calc_reg = px30_calc_drv_reg_and_bit,
|
||||
.schmitt_calc_reg = px30_calc_schmitt_reg_and_bit,
|
||||
};
|
||||
|
||||
static struct rockchip_pin_bank rv1108_pin_banks[] = {
|
||||
PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
|
||||
IOMUX_SOURCE_PMU,
|
||||
|
@ -3545,6 +3789,8 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
|
|||
};
|
||||
|
||||
static const struct of_device_id rockchip_pinctrl_dt_match[] = {
|
||||
{ .compatible = "rockchip,px30-pinctrl",
|
||||
.data = &px30_pin_ctrl },
|
||||
{ .compatible = "rockchip,rv1108-pinctrl",
|
||||
.data = &rv1108_pin_ctrl },
|
||||
{ .compatible = "rockchip,rk2928-pinctrl",
|
||||
|
|
|
@ -144,6 +144,7 @@ struct pcs_soc_data {
|
|||
* struct pcs_device - pinctrl device instance
|
||||
* @res: resources
|
||||
* @base: virtual address of the controller
|
||||
* @saved_vals: saved values for the controller
|
||||
* @size: size of the ioremapped area
|
||||
* @dev: device entry
|
||||
* @np: device tree node
|
||||
|
@ -172,11 +173,13 @@ struct pcs_soc_data {
|
|||
struct pcs_device {
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
void *saved_vals;
|
||||
unsigned size;
|
||||
struct device *dev;
|
||||
struct device_node *np;
|
||||
struct pinctrl_dev *pctl;
|
||||
unsigned flags;
|
||||
#define PCS_CONTEXT_LOSS_OFF (1 << 3)
|
||||
#define PCS_QUIRK_SHARED_IRQ (1 << 2)
|
||||
#define PCS_FEAT_IRQ (1 << 1)
|
||||
#define PCS_FEAT_PINCONF (1 << 0)
|
||||
|
@ -1576,6 +1579,67 @@ static int pcs_irq_init_chained_handler(struct pcs_device *pcs,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int pcs_save_context(struct pcs_device *pcs)
|
||||
{
|
||||
int i, mux_bytes;
|
||||
u64 *regsl;
|
||||
u32 *regsw;
|
||||
u16 *regshw;
|
||||
|
||||
mux_bytes = pcs->width / BITS_PER_BYTE;
|
||||
|
||||
if (!pcs->saved_vals)
|
||||
pcs->saved_vals = devm_kzalloc(pcs->dev, pcs->size, GFP_ATOMIC);
|
||||
|
||||
switch (pcs->width) {
|
||||
case 64:
|
||||
regsl = (u64 *)pcs->saved_vals;
|
||||
for (i = 0; i < pcs->size / mux_bytes; i++)
|
||||
regsl[i] = pcs->read(pcs->base + i * mux_bytes);
|
||||
break;
|
||||
case 32:
|
||||
regsw = (u32 *)pcs->saved_vals;
|
||||
for (i = 0; i < pcs->size / mux_bytes; i++)
|
||||
regsw[i] = pcs->read(pcs->base + i * mux_bytes);
|
||||
break;
|
||||
case 16:
|
||||
regshw = (u16 *)pcs->saved_vals;
|
||||
for (i = 0; i < pcs->size / mux_bytes; i++)
|
||||
regshw[i] = pcs->read(pcs->base + i * mux_bytes);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcs_restore_context(struct pcs_device *pcs)
|
||||
{
|
||||
int i, mux_bytes;
|
||||
u64 *regsl;
|
||||
u32 *regsw;
|
||||
u16 *regshw;
|
||||
|
||||
mux_bytes = pcs->width / BITS_PER_BYTE;
|
||||
|
||||
switch (pcs->width) {
|
||||
case 64:
|
||||
regsl = (u64 *)pcs->saved_vals;
|
||||
for (i = 0; i < pcs->size / mux_bytes; i++)
|
||||
pcs->write(regsl[i], pcs->base + i * mux_bytes);
|
||||
break;
|
||||
case 32:
|
||||
regsw = (u32 *)pcs->saved_vals;
|
||||
for (i = 0; i < pcs->size / mux_bytes; i++)
|
||||
pcs->write(regsw[i], pcs->base + i * mux_bytes);
|
||||
break;
|
||||
case 16:
|
||||
regshw = (u16 *)pcs->saved_vals;
|
||||
for (i = 0; i < pcs->size / mux_bytes; i++)
|
||||
pcs->write(regshw[i], pcs->base + i * mux_bytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int pinctrl_single_suspend(struct platform_device *pdev,
|
||||
pm_message_t state)
|
||||
{
|
||||
|
@ -1585,6 +1649,9 @@ static int pinctrl_single_suspend(struct platform_device *pdev,
|
|||
if (!pcs)
|
||||
return -EINVAL;
|
||||
|
||||
if (pcs->flags & PCS_CONTEXT_LOSS_OFF)
|
||||
pcs_save_context(pcs);
|
||||
|
||||
return pinctrl_force_sleep(pcs->pctl);
|
||||
}
|
||||
|
||||
|
@ -1596,6 +1663,9 @@ static int pinctrl_single_resume(struct platform_device *pdev)
|
|||
if (!pcs)
|
||||
return -EINVAL;
|
||||
|
||||
if (pcs->flags & PCS_CONTEXT_LOSS_OFF)
|
||||
pcs_restore_context(pcs);
|
||||
|
||||
return pinctrl_force_default(pcs->pctl);
|
||||
}
|
||||
#endif
|
||||
|
@ -1824,7 +1894,7 @@ static const struct pcs_soc_data pinctrl_single_dra7 = {
|
|||
};
|
||||
|
||||
static const struct pcs_soc_data pinctrl_single_am437x = {
|
||||
.flags = PCS_QUIRK_SHARED_IRQ,
|
||||
.flags = PCS_QUIRK_SHARED_IRQ | PCS_CONTEXT_LOSS_OFF,
|
||||
.irq_enable_mask = (1 << 29), /* OMAP_WAKEUP_EN */
|
||||
.irq_status_mask = (1 << 30), /* OMAP_WAKEUP_EVENT */
|
||||
};
|
||||
|
|
|
@ -58,7 +58,10 @@ struct msm_pinctrl {
|
|||
struct device *dev;
|
||||
struct pinctrl_dev *pctrl;
|
||||
struct gpio_chip chip;
|
||||
struct pinctrl_desc desc;
|
||||
struct notifier_block restart_nb;
|
||||
|
||||
struct irq_chip irq_chip;
|
||||
int irq;
|
||||
|
||||
raw_spinlock_t lock;
|
||||
|
@ -390,13 +393,6 @@ static const struct pinconf_ops msm_pinconf_ops = {
|
|||
.pin_config_group_set = msm_config_group_set,
|
||||
};
|
||||
|
||||
static struct pinctrl_desc msm_pinctrl_desc = {
|
||||
.pctlops = &msm_pinctrl_ops,
|
||||
.pmxops = &msm_pinmux_ops,
|
||||
.confops = &msm_pinconf_ops,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
const struct msm_pingroup *g;
|
||||
|
@ -506,29 +502,46 @@ static void msm_gpio_dbg_show_one(struct seq_file *s,
|
|||
int is_out;
|
||||
int drive;
|
||||
int pull;
|
||||
u32 ctl_reg;
|
||||
int val;
|
||||
u32 ctl_reg, io_reg;
|
||||
|
||||
static const char * const pulls[] = {
|
||||
static const char * const pulls_keeper[] = {
|
||||
"no pull",
|
||||
"pull down",
|
||||
"keeper",
|
||||
"pull up"
|
||||
};
|
||||
|
||||
static const char * const pulls_no_keeper[] = {
|
||||
"no pull",
|
||||
"pull down",
|
||||
"pull up",
|
||||
};
|
||||
|
||||
if (!gpiochip_line_is_valid(chip, offset))
|
||||
return;
|
||||
|
||||
g = &pctrl->soc->groups[offset];
|
||||
ctl_reg = readl(pctrl->regs + g->ctl_reg);
|
||||
io_reg = readl(pctrl->regs + g->io_reg);
|
||||
|
||||
is_out = !!(ctl_reg & BIT(g->oe_bit));
|
||||
func = (ctl_reg >> g->mux_bit) & 7;
|
||||
drive = (ctl_reg >> g->drv_bit) & 7;
|
||||
pull = (ctl_reg >> g->pull_bit) & 3;
|
||||
|
||||
seq_printf(s, " %-8s: %-3s %d", g->name, is_out ? "out" : "in", func);
|
||||
if (is_out)
|
||||
val = !!(io_reg & BIT(g->out_bit));
|
||||
else
|
||||
val = !!(io_reg & BIT(g->in_bit));
|
||||
|
||||
seq_printf(s, " %-8s: %-3s", g->name, is_out ? "out" : "in");
|
||||
seq_printf(s, " %-4s func%d", val ? "high" : "low", func);
|
||||
seq_printf(s, " %dmA", msm_regval_to_drive(drive));
|
||||
seq_printf(s, " %s", pulls[pull]);
|
||||
if (pctrl->soc->pull_no_keeper)
|
||||
seq_printf(s, " %s", pulls_no_keeper[pull]);
|
||||
else
|
||||
seq_printf(s, " %s", pulls_keeper[pull]);
|
||||
seq_puts(s, "\n");
|
||||
}
|
||||
|
||||
|
@ -776,15 +789,6 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip msm_gpio_irq_chip = {
|
||||
.name = "msmgpio",
|
||||
.irq_mask = msm_gpio_irq_mask,
|
||||
.irq_unmask = msm_gpio_irq_unmask,
|
||||
.irq_ack = msm_gpio_irq_ack,
|
||||
.irq_set_type = msm_gpio_irq_set_type,
|
||||
.irq_set_wake = msm_gpio_irq_set_wake,
|
||||
};
|
||||
|
||||
static void msm_gpio_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
|
||||
|
@ -877,6 +881,13 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
|
|||
chip->of_node = pctrl->dev->of_node;
|
||||
chip->need_valid_mask = msm_gpio_needs_valid_mask(pctrl);
|
||||
|
||||
pctrl->irq_chip.name = "msmgpio";
|
||||
pctrl->irq_chip.irq_mask = msm_gpio_irq_mask;
|
||||
pctrl->irq_chip.irq_unmask = msm_gpio_irq_unmask;
|
||||
pctrl->irq_chip.irq_ack = msm_gpio_irq_ack;
|
||||
pctrl->irq_chip.irq_set_type = msm_gpio_irq_set_type;
|
||||
pctrl->irq_chip.irq_set_wake = msm_gpio_irq_set_wake;
|
||||
|
||||
ret = gpiochip_add_data(&pctrl->chip, pctrl);
|
||||
if (ret) {
|
||||
dev_err(pctrl->dev, "Failed register gpiochip\n");
|
||||
|
@ -890,15 +901,28 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio);
|
||||
if (ret) {
|
||||
dev_err(pctrl->dev, "Failed to add pin range\n");
|
||||
gpiochip_remove(&pctrl->chip);
|
||||
return ret;
|
||||
/*
|
||||
* For DeviceTree-supported systems, the gpio core checks the
|
||||
* pinctrl's device node for the "gpio-ranges" property.
|
||||
* If it is present, it takes care of adding the pin ranges
|
||||
* for the driver. In this case the driver can skip ahead.
|
||||
*
|
||||
* In order to remain compatible with older, existing DeviceTree
|
||||
* files which don't set the "gpio-ranges" property or systems that
|
||||
* utilize ACPI the driver has to call gpiochip_add_pin_range().
|
||||
*/
|
||||
if (!of_property_read_bool(pctrl->dev->of_node, "gpio-ranges")) {
|
||||
ret = gpiochip_add_pin_range(&pctrl->chip,
|
||||
dev_name(pctrl->dev), 0, 0, chip->ngpio);
|
||||
if (ret) {
|
||||
dev_err(pctrl->dev, "Failed to add pin range\n");
|
||||
gpiochip_remove(&pctrl->chip);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = gpiochip_irqchip_add(chip,
|
||||
&msm_gpio_irq_chip,
|
||||
&pctrl->irq_chip,
|
||||
0,
|
||||
handle_edge_irq,
|
||||
IRQ_TYPE_NONE);
|
||||
|
@ -908,7 +932,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
gpiochip_set_chained_irqchip(chip, &msm_gpio_irq_chip, pctrl->irq,
|
||||
gpiochip_set_chained_irqchip(chip, &pctrl->irq_chip, pctrl->irq,
|
||||
msm_gpio_irq_handler);
|
||||
|
||||
return 0;
|
||||
|
@ -979,11 +1003,15 @@ int msm_pinctrl_probe(struct platform_device *pdev,
|
|||
return pctrl->irq;
|
||||
}
|
||||
|
||||
msm_pinctrl_desc.name = dev_name(&pdev->dev);
|
||||
msm_pinctrl_desc.pins = pctrl->soc->pins;
|
||||
msm_pinctrl_desc.npins = pctrl->soc->npins;
|
||||
pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &msm_pinctrl_desc,
|
||||
pctrl);
|
||||
pctrl->desc.owner = THIS_MODULE;
|
||||
pctrl->desc.pctlops = &msm_pinctrl_ops;
|
||||
pctrl->desc.pmxops = &msm_pinmux_ops;
|
||||
pctrl->desc.confops = &msm_pinconf_ops;
|
||||
pctrl->desc.name = dev_name(&pdev->dev);
|
||||
pctrl->desc.pins = pctrl->soc->pins;
|
||||
pctrl->desc.npins = pctrl->soc->npins;
|
||||
|
||||
pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl);
|
||||
if (IS_ERR(pctrl->pctrl)) {
|
||||
dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
|
||||
return PTR_ERR(pctrl->pctrl);
|
||||
|
|
|
@ -30,9 +30,7 @@
|
|||
|
||||
#include "pinctrl-msm.h"
|
||||
|
||||
static struct msm_pinctrl_soc_data qdf2xxx_pinctrl;
|
||||
|
||||
/* A reasonable limit to the number of GPIOS */
|
||||
/* A maximum of 256 allows us to use a u8 array to hold the GPIO numbers */
|
||||
#define MAX_GPIOS 256
|
||||
|
||||
/* maximum size of each gpio name (enough room for "gpioXXX" + null) */
|
||||
|
@ -40,77 +38,111 @@ static struct msm_pinctrl_soc_data qdf2xxx_pinctrl;
|
|||
|
||||
static int qdf2xxx_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct msm_pinctrl_soc_data *pinctrl;
|
||||
struct pinctrl_pin_desc *pins;
|
||||
struct msm_pingroup *groups;
|
||||
char (*names)[NAME_SIZE];
|
||||
unsigned int i;
|
||||
u32 num_gpios;
|
||||
unsigned int avail_gpios; /* The number of GPIOs we support */
|
||||
u8 gpios[MAX_GPIOS]; /* An array of supported GPIOs */
|
||||
int ret;
|
||||
|
||||
/* Query the number of GPIOs from ACPI */
|
||||
ret = device_property_read_u32(&pdev->dev, "num-gpios", &num_gpios);
|
||||
if (ret < 0) {
|
||||
dev_warn(&pdev->dev, "missing num-gpios property\n");
|
||||
dev_err(&pdev->dev, "missing 'num-gpios' property\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!num_gpios || num_gpios > MAX_GPIOS) {
|
||||
dev_warn(&pdev->dev, "invalid num-gpios property\n");
|
||||
dev_err(&pdev->dev, "invalid 'num-gpios' property\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* The number of GPIOs in the approved list */
|
||||
ret = device_property_read_u8_array(&pdev->dev, "gpios", NULL, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "missing 'gpios' property\n");
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* The number of available GPIOs should be non-zero, and no
|
||||
* more than the total number of GPIOS.
|
||||
*/
|
||||
if (!ret || ret > num_gpios) {
|
||||
dev_err(&pdev->dev, "invalid 'gpios' property\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
avail_gpios = ret;
|
||||
|
||||
ret = device_property_read_u8_array(&pdev->dev, "gpios", gpios,
|
||||
avail_gpios);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "could not read list of GPIOs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
pinctrl = devm_kzalloc(&pdev->dev, sizeof(*pinctrl), GFP_KERNEL);
|
||||
pins = devm_kcalloc(&pdev->dev, num_gpios,
|
||||
sizeof(struct pinctrl_pin_desc), GFP_KERNEL);
|
||||
groups = devm_kcalloc(&pdev->dev, num_gpios,
|
||||
sizeof(struct msm_pingroup), GFP_KERNEL);
|
||||
names = devm_kcalloc(&pdev->dev, num_gpios, NAME_SIZE, GFP_KERNEL);
|
||||
names = devm_kcalloc(&pdev->dev, avail_gpios, NAME_SIZE, GFP_KERNEL);
|
||||
|
||||
if (!pins || !groups || !names)
|
||||
if (!pinctrl || !pins || !groups || !names)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Initialize the array. GPIOs not listed in the 'gpios' array
|
||||
* still need a number, but nothing else.
|
||||
*/
|
||||
for (i = 0; i < num_gpios; i++) {
|
||||
snprintf(names[i], NAME_SIZE, "gpio%u", i);
|
||||
|
||||
pins[i].number = i;
|
||||
pins[i].name = names[i];
|
||||
|
||||
groups[i].npins = 1;
|
||||
groups[i].name = names[i];
|
||||
groups[i].pins = &pins[i].number;
|
||||
|
||||
groups[i].ctl_reg = 0x10000 * i;
|
||||
groups[i].io_reg = 0x04 + 0x10000 * i;
|
||||
groups[i].intr_cfg_reg = 0x08 + 0x10000 * i;
|
||||
groups[i].intr_status_reg = 0x0c + 0x10000 * i;
|
||||
groups[i].intr_target_reg = 0x08 + 0x10000 * i;
|
||||
|
||||
groups[i].mux_bit = 2;
|
||||
groups[i].pull_bit = 0;
|
||||
groups[i].drv_bit = 6;
|
||||
groups[i].oe_bit = 9;
|
||||
groups[i].in_bit = 0;
|
||||
groups[i].out_bit = 1;
|
||||
groups[i].intr_enable_bit = 0;
|
||||
groups[i].intr_status_bit = 0;
|
||||
groups[i].intr_target_bit = 5;
|
||||
groups[i].intr_target_kpss_val = 1;
|
||||
groups[i].intr_raw_status_bit = 4;
|
||||
groups[i].intr_polarity_bit = 1;
|
||||
groups[i].intr_detection_bit = 2;
|
||||
groups[i].intr_detection_width = 2;
|
||||
}
|
||||
|
||||
qdf2xxx_pinctrl.pins = pins;
|
||||
qdf2xxx_pinctrl.groups = groups;
|
||||
qdf2xxx_pinctrl.npins = num_gpios;
|
||||
qdf2xxx_pinctrl.ngroups = num_gpios;
|
||||
qdf2xxx_pinctrl.ngpios = num_gpios;
|
||||
/* Populate the entries that are meant to be exposed as GPIOs. */
|
||||
for (i = 0; i < avail_gpios; i++) {
|
||||
unsigned int gpio = gpios[i];
|
||||
|
||||
return msm_pinctrl_probe(pdev, &qdf2xxx_pinctrl);
|
||||
groups[gpio].npins = 1;
|
||||
snprintf(names[i], NAME_SIZE, "gpio%u", gpio);
|
||||
pins[gpio].name = names[i];
|
||||
groups[gpio].name = names[i];
|
||||
|
||||
groups[gpio].ctl_reg = 0x10000 * gpio;
|
||||
groups[gpio].io_reg = 0x04 + 0x10000 * gpio;
|
||||
groups[gpio].intr_cfg_reg = 0x08 + 0x10000 * gpio;
|
||||
groups[gpio].intr_status_reg = 0x0c + 0x10000 * gpio;
|
||||
groups[gpio].intr_target_reg = 0x08 + 0x10000 * gpio;
|
||||
|
||||
groups[gpio].mux_bit = 2;
|
||||
groups[gpio].pull_bit = 0;
|
||||
groups[gpio].drv_bit = 6;
|
||||
groups[gpio].oe_bit = 9;
|
||||
groups[gpio].in_bit = 0;
|
||||
groups[gpio].out_bit = 1;
|
||||
groups[gpio].intr_enable_bit = 0;
|
||||
groups[gpio].intr_status_bit = 0;
|
||||
groups[gpio].intr_target_bit = 5;
|
||||
groups[gpio].intr_target_kpss_val = 1;
|
||||
groups[gpio].intr_raw_status_bit = 4;
|
||||
groups[gpio].intr_polarity_bit = 1;
|
||||
groups[gpio].intr_detection_bit = 2;
|
||||
groups[gpio].intr_detection_width = 2;
|
||||
}
|
||||
|
||||
pinctrl->pins = pins;
|
||||
pinctrl->groups = groups;
|
||||
pinctrl->npins = num_gpios;
|
||||
pinctrl->ngroups = num_gpios;
|
||||
pinctrl->ngpios = num_gpios;
|
||||
|
||||
return msm_pinctrl_probe(pdev, pinctrl);
|
||||
}
|
||||
|
||||
static const struct acpi_device_id qdf2xxx_acpi_ids[] = {
|
||||
{"QCOM8001"},
|
||||
{"QCOM8002"},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, qdf2xxx_acpi_ids);
|
||||
|
|
|
@ -8,26 +8,20 @@ config PINCTRL_SAMSUNG
|
|||
select PINCONF
|
||||
|
||||
config PINCTRL_EXYNOS
|
||||
bool "Pinctrl driver data for Samsung EXYNOS SoCs other than 5440"
|
||||
bool "Pinctrl driver data for Samsung EXYNOS SoCs"
|
||||
depends on OF && GPIOLIB && (ARCH_EXYNOS || ARCH_S5PV210)
|
||||
select PINCTRL_SAMSUNG
|
||||
select PINCTRL_EXYNOS_ARM if ARM && (ARCH_EXYNOS || ARCH_S5PV210)
|
||||
select PINCTRL_EXYNOS_ARM64 if ARM64 && ARCH_EXYNOS
|
||||
|
||||
config PINCTRL_EXYNOS_ARM
|
||||
bool "ARMv7-specific pinctrl driver data for Exynos (except Exynos5440)" if COMPILE_TEST
|
||||
bool "ARMv7-specific pinctrl driver data for Exynos" if COMPILE_TEST
|
||||
depends on PINCTRL_EXYNOS
|
||||
|
||||
config PINCTRL_EXYNOS_ARM64
|
||||
bool "ARMv8-specific pinctrl driver data for Exynos" if COMPILE_TEST
|
||||
depends on PINCTRL_EXYNOS
|
||||
|
||||
config PINCTRL_EXYNOS5440
|
||||
bool "Samsung EXYNOS5440 SoC pinctrl driver"
|
||||
depends on SOC_EXYNOS5440
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
|
||||
config PINCTRL_S3C24XX
|
||||
bool "Samsung S3C24XX SoC pinctrl driver"
|
||||
depends on ARCH_S3C24XX && OF
|
||||
|
|
|
@ -5,6 +5,5 @@ obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
|
|||
obj-$(CONFIG_PINCTRL_EXYNOS) += pinctrl-exynos.o
|
||||
obj-$(CONFIG_PINCTRL_EXYNOS_ARM) += pinctrl-exynos-arm.o
|
||||
obj-$(CONFIG_PINCTRL_EXYNOS_ARM64) += pinctrl-exynos-arm64.o
|
||||
obj-$(CONFIG_PINCTRL_EXYNOS5440) += pinctrl-exynos5440.o
|
||||
obj-$(CONFIG_PINCTRL_S3C24XX) += pinctrl-s3c24xx.o
|
||||
obj-$(CONFIG_PINCTRL_S3C64XX) += pinctrl-s3c64xx.o
|
||||
|
|
|
@ -88,6 +88,7 @@ static const struct samsung_retention_data s5pv210_retention_data __initconst =
|
|||
|
||||
/* pin banks of s5pv210 pin-controller */
|
||||
static const struct samsung_pin_bank_data s5pv210_pin_bank[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpa1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
|
||||
|
@ -105,12 +106,12 @@ static const struct samsung_pin_bank_data s5pv210_pin_bank[] __initconst = {
|
|||
EXYNOS_PIN_BANK_EINTG(7, 0x1c0, "gpg1", 0x38),
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x1e0, "gpg2", 0x3c),
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x200, "gpg3", 0x40),
|
||||
EXYNOS_PIN_BANK_EINTN(7, 0x220, "gpi"),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x240, "gpj0", 0x44),
|
||||
EXYNOS_PIN_BANK_EINTG(6, 0x260, "gpj1", 0x48),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x280, "gpj2", 0x4c),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x2a0, "gpj3", 0x50),
|
||||
EXYNOS_PIN_BANK_EINTG(5, 0x2c0, "gpj4", 0x54),
|
||||
EXYNOS_PIN_BANK_EINTN(7, 0x220, "gpi"),
|
||||
EXYNOS_PIN_BANK_EINTN(8, 0x2e0, "mp01"),
|
||||
EXYNOS_PIN_BANK_EINTN(4, 0x300, "mp02"),
|
||||
EXYNOS_PIN_BANK_EINTN(8, 0x320, "mp03"),
|
||||
|
@ -147,6 +148,7 @@ static atomic_t exynos_shared_retention_refcnt;
|
|||
|
||||
/* pin banks of exynos3250 pin-controller 0 */
|
||||
static const struct samsung_pin_bank_data exynos3250_pin_banks0[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
|
||||
|
@ -158,6 +160,7 @@ static const struct samsung_pin_bank_data exynos3250_pin_banks0[] __initconst =
|
|||
|
||||
/* pin banks of exynos3250 pin-controller 1 */
|
||||
static const struct samsung_pin_bank_data exynos3250_pin_banks1[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTN(8, 0x120, "gpe0"),
|
||||
EXYNOS_PIN_BANK_EINTN(8, 0x140, "gpe1"),
|
||||
EXYNOS_PIN_BANK_EINTN(3, 0x180, "gpe2"),
|
||||
|
@ -232,6 +235,7 @@ const struct samsung_pinctrl_of_match_data exynos3250_of_data __initconst = {
|
|||
|
||||
/* pin banks of exynos4210 pin-controller 0 */
|
||||
static const struct samsung_pin_bank_data exynos4210_pin_banks0[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
|
||||
|
@ -252,6 +256,7 @@ static const struct samsung_pin_bank_data exynos4210_pin_banks0[] __initconst =
|
|||
|
||||
/* pin banks of exynos4210 pin-controller 1 */
|
||||
static const struct samsung_pin_bank_data exynos4210_pin_banks1[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpj0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpj1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08),
|
||||
|
@ -276,6 +281,7 @@ static const struct samsung_pin_bank_data exynos4210_pin_banks1[] __initconst =
|
|||
|
||||
/* pin banks of exynos4210 pin-controller 2 */
|
||||
static const struct samsung_pin_bank_data exynos4210_pin_banks2[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTN(7, 0x000, "gpz"),
|
||||
};
|
||||
|
||||
|
@ -346,6 +352,7 @@ const struct samsung_pinctrl_of_match_data exynos4210_of_data __initconst = {
|
|||
|
||||
/* pin banks of exynos4x12 pin-controller 0 */
|
||||
static const struct samsung_pin_bank_data exynos4x12_pin_banks0[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
|
||||
|
@ -363,6 +370,7 @@ static const struct samsung_pin_bank_data exynos4x12_pin_banks0[] __initconst =
|
|||
|
||||
/* pin banks of exynos4x12 pin-controller 1 */
|
||||
static const struct samsung_pin_bank_data exynos4x12_pin_banks1[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08),
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
|
||||
|
@ -390,11 +398,13 @@ static const struct samsung_pin_bank_data exynos4x12_pin_banks1[] __initconst =
|
|||
|
||||
/* pin banks of exynos4x12 pin-controller 2 */
|
||||
static const struct samsung_pin_bank_data exynos4x12_pin_banks2[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos4x12 pin-controller 3 */
|
||||
static const struct samsung_pin_bank_data exynos4x12_pin_banks3[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpv2", 0x08),
|
||||
|
@ -449,6 +459,7 @@ const struct samsung_pinctrl_of_match_data exynos4x12_of_data __initconst = {
|
|||
|
||||
/* pin banks of exynos5250 pin-controller 0 */
|
||||
static const struct samsung_pin_bank_data exynos5250_pin_banks0[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
|
||||
|
@ -478,6 +489,7 @@ static const struct samsung_pin_bank_data exynos5250_pin_banks0[] __initconst =
|
|||
|
||||
/* pin banks of exynos5250 pin-controller 1 */
|
||||
static const struct samsung_pin_bank_data exynos5250_pin_banks1[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpe0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(2, 0x020, "gpe1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(4, 0x040, "gpf0", 0x08),
|
||||
|
@ -491,6 +503,7 @@ static const struct samsung_pin_bank_data exynos5250_pin_banks1[] __initconst =
|
|||
|
||||
/* pin banks of exynos5250 pin-controller 2 */
|
||||
static const struct samsung_pin_bank_data exynos5250_pin_banks2[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv2", 0x08),
|
||||
|
@ -500,6 +513,7 @@ static const struct samsung_pin_bank_data exynos5250_pin_banks2[] __initconst =
|
|||
|
||||
/* pin banks of exynos5250 pin-controller 3 */
|
||||
static const struct samsung_pin_bank_data exynos5250_pin_banks3[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
|
||||
};
|
||||
|
||||
|
@ -550,6 +564,7 @@ const struct samsung_pinctrl_of_match_data exynos5250_of_data __initconst = {
|
|||
|
||||
/* pin banks of exynos5260 pin-controller 0 */
|
||||
static const struct samsung_pin_bank_data exynos5260_pin_banks0[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(4, 0x000, "gpa0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x020, "gpa1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
|
||||
|
@ -575,6 +590,7 @@ static const struct samsung_pin_bank_data exynos5260_pin_banks0[] __initconst =
|
|||
|
||||
/* pin banks of exynos5260 pin-controller 1 */
|
||||
static const struct samsung_pin_bank_data exynos5260_pin_banks1[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpc0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpc1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpc2", 0x08),
|
||||
|
@ -584,6 +600,7 @@ static const struct samsung_pin_bank_data exynos5260_pin_banks1[] __initconst =
|
|||
|
||||
/* pin banks of exynos5260 pin-controller 2 */
|
||||
static const struct samsung_pin_bank_data exynos5260_pin_banks2[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04),
|
||||
};
|
||||
|
@ -619,6 +636,7 @@ const struct samsung_pinctrl_of_match_data exynos5260_of_data __initconst = {
|
|||
|
||||
/* pin banks of exynos5410 pin-controller 0 */
|
||||
static const struct samsung_pin_bank_data exynos5410_pin_banks0[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
|
||||
|
@ -630,7 +648,6 @@ static const struct samsung_pin_bank_data exynos5410_pin_banks0[] __initconst =
|
|||
EXYNOS_PIN_BANK_EINTG(4, 0x100, "gpc3", 0x20),
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x120, "gpc1", 0x24),
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x140, "gpc2", 0x28),
|
||||
EXYNOS_PIN_BANK_EINTN(2, 0x160, "gpm5"),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpd1", 0x2c),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpe0", 0x30),
|
||||
EXYNOS_PIN_BANK_EINTG(2, 0x1C0, "gpe1", 0x34),
|
||||
|
@ -641,6 +658,7 @@ static const struct samsung_pin_bank_data exynos5410_pin_banks0[] __initconst =
|
|||
EXYNOS_PIN_BANK_EINTG(2, 0x260, "gpg2", 0x48),
|
||||
EXYNOS_PIN_BANK_EINTG(4, 0x280, "gph0", 0x4c),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x2A0, "gph1", 0x50),
|
||||
EXYNOS_PIN_BANK_EINTN(2, 0x160, "gpm5"),
|
||||
EXYNOS_PIN_BANK_EINTN(8, 0x2C0, "gpm7"),
|
||||
EXYNOS_PIN_BANK_EINTN(6, 0x2E0, "gpy0"),
|
||||
EXYNOS_PIN_BANK_EINTN(4, 0x300, "gpy1"),
|
||||
|
@ -658,6 +676,7 @@ static const struct samsung_pin_bank_data exynos5410_pin_banks0[] __initconst =
|
|||
|
||||
/* pin banks of exynos5410 pin-controller 1 */
|
||||
static const struct samsung_pin_bank_data exynos5410_pin_banks1[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(5, 0x000, "gpj0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpj1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpj2", 0x08),
|
||||
|
@ -671,6 +690,7 @@ static const struct samsung_pin_bank_data exynos5410_pin_banks1[] __initconst =
|
|||
|
||||
/* pin banks of exynos5410 pin-controller 2 */
|
||||
static const struct samsung_pin_bank_data exynos5410_pin_banks2[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv2", 0x08),
|
||||
|
@ -680,6 +700,7 @@ static const struct samsung_pin_bank_data exynos5410_pin_banks2[] __initconst =
|
|||
|
||||
/* pin banks of exynos5410 pin-controller 3 */
|
||||
static const struct samsung_pin_bank_data exynos5410_pin_banks3[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
|
||||
};
|
||||
|
||||
|
@ -727,6 +748,7 @@ const struct samsung_pinctrl_of_match_data exynos5410_of_data __initconst = {
|
|||
|
||||
/* pin banks of exynos5420 pin-controller 0 */
|
||||
static const struct samsung_pin_bank_data exynos5420_pin_banks0[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpy7", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
|
||||
|
@ -736,6 +758,7 @@ static const struct samsung_pin_bank_data exynos5420_pin_banks0[] __initconst =
|
|||
|
||||
/* pin banks of exynos5420 pin-controller 1 */
|
||||
static const struct samsung_pin_bank_data exynos5420_pin_banks1[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpc0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpc1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpc2", 0x08),
|
||||
|
@ -753,6 +776,7 @@ static const struct samsung_pin_bank_data exynos5420_pin_banks1[] __initconst =
|
|||
|
||||
/* pin banks of exynos5420 pin-controller 2 */
|
||||
static const struct samsung_pin_bank_data exynos5420_pin_banks2[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpe0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(2, 0x020, "gpe1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(6, 0x040, "gpf0", 0x08),
|
||||
|
@ -765,6 +789,7 @@ static const struct samsung_pin_bank_data exynos5420_pin_banks2[] __initconst =
|
|||
|
||||
/* pin banks of exynos5420 pin-controller 3 */
|
||||
static const struct samsung_pin_bank_data exynos5420_pin_banks3[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
|
||||
|
@ -778,6 +803,7 @@ static const struct samsung_pin_bank_data exynos5420_pin_banks3[] __initconst =
|
|||
|
||||
/* pin banks of exynos5420 pin-controller 4 */
|
||||
static const struct samsung_pin_bank_data exynos5420_pin_banks4[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
|
||||
};
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ static atomic_t exynos_shared_retention_refcnt;
|
|||
|
||||
/* pin banks of exynos5433 pin-controller - ALIVE */
|
||||
static const struct samsung_pin_bank_data exynos5433_pin_banks0[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS5433_PIN_BANK_EINTW(8, 0x000, "gpa0", 0x00),
|
||||
EXYNOS5433_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04),
|
||||
EXYNOS5433_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08),
|
||||
|
@ -58,27 +59,32 @@ static const struct samsung_pin_bank_data exynos5433_pin_banks0[] __initconst =
|
|||
|
||||
/* pin banks of exynos5433 pin-controller - AUD */
|
||||
static const struct samsung_pin_bank_data exynos5433_pin_banks1[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS5433_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00),
|
||||
EXYNOS5433_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04),
|
||||
};
|
||||
|
||||
/* pin banks of exynos5433 pin-controller - CPIF */
|
||||
static const struct samsung_pin_bank_data exynos5433_pin_banks2[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS5433_PIN_BANK_EINTG(2, 0x000, "gpv6", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos5433 pin-controller - eSE */
|
||||
static const struct samsung_pin_bank_data exynos5433_pin_banks3[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS5433_PIN_BANK_EINTG(3, 0x000, "gpj2", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos5433 pin-controller - FINGER */
|
||||
static const struct samsung_pin_bank_data exynos5433_pin_banks4[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS5433_PIN_BANK_EINTG(4, 0x000, "gpd5", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos5433 pin-controller - FSYS */
|
||||
static const struct samsung_pin_bank_data exynos5433_pin_banks5[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS5433_PIN_BANK_EINTG(6, 0x000, "gph1", 0x00),
|
||||
EXYNOS5433_PIN_BANK_EINTG(7, 0x020, "gpr4", 0x04),
|
||||
EXYNOS5433_PIN_BANK_EINTG(5, 0x040, "gpr0", 0x08),
|
||||
|
@ -89,16 +95,19 @@ static const struct samsung_pin_bank_data exynos5433_pin_banks5[] __initconst =
|
|||
|
||||
/* pin banks of exynos5433 pin-controller - IMEM */
|
||||
static const struct samsung_pin_bank_data exynos5433_pin_banks6[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS5433_PIN_BANK_EINTG(8, 0x000, "gpf0", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos5433 pin-controller - NFC */
|
||||
static const struct samsung_pin_bank_data exynos5433_pin_banks7[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS5433_PIN_BANK_EINTG(3, 0x000, "gpj0", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos5433 pin-controller - PERIC */
|
||||
static const struct samsung_pin_bank_data exynos5433_pin_banks8[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS5433_PIN_BANK_EINTG(6, 0x000, "gpv7", 0x00),
|
||||
EXYNOS5433_PIN_BANK_EINTG(5, 0x020, "gpb0", 0x04),
|
||||
EXYNOS5433_PIN_BANK_EINTG(8, 0x040, "gpc0", 0x08),
|
||||
|
@ -120,6 +129,7 @@ static const struct samsung_pin_bank_data exynos5433_pin_banks8[] __initconst =
|
|||
|
||||
/* pin banks of exynos5433 pin-controller - TOUCH */
|
||||
static const struct samsung_pin_bank_data exynos5433_pin_banks9[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS5433_PIN_BANK_EINTG(3, 0x000, "gpj1", 0x00),
|
||||
};
|
||||
|
||||
|
@ -267,6 +277,7 @@ const struct samsung_pinctrl_of_match_data exynos5433_of_data __initconst = {
|
|||
|
||||
/* pin banks of exynos7 pin-controller - ALIVE */
|
||||
static const struct samsung_pin_bank_data exynos7_pin_banks0[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTW(8, 0x000, "gpa0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08),
|
||||
|
@ -275,6 +286,7 @@ static const struct samsung_pin_bank_data exynos7_pin_banks0[] __initconst = {
|
|||
|
||||
/* pin banks of exynos7 pin-controller - BUS0 */
|
||||
static const struct samsung_pin_bank_data exynos7_pin_banks1[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(5, 0x000, "gpb0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpc0", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(2, 0x040, "gpc1", 0x08),
|
||||
|
@ -294,31 +306,37 @@ static const struct samsung_pin_bank_data exynos7_pin_banks1[] __initconst = {
|
|||
|
||||
/* pin banks of exynos7 pin-controller - NFC */
|
||||
static const struct samsung_pin_bank_data exynos7_pin_banks2[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(3, 0x000, "gpj0", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7 pin-controller - TOUCH */
|
||||
static const struct samsung_pin_bank_data exynos7_pin_banks3[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(3, 0x000, "gpj1", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7 pin-controller - FF */
|
||||
static const struct samsung_pin_bank_data exynos7_pin_banks4[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(4, 0x000, "gpg4", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7 pin-controller - ESE */
|
||||
static const struct samsung_pin_bank_data exynos7_pin_banks5[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(5, 0x000, "gpv7", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7 pin-controller - FSYS0 */
|
||||
static const struct samsung_pin_bank_data exynos7_pin_banks6[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpr4", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7 pin-controller - FSYS1 */
|
||||
static const struct samsung_pin_bank_data exynos7_pin_banks7[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(4, 0x000, "gpr0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpr1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(5, 0x040, "gpr2", 0x08),
|
||||
|
@ -327,6 +345,7 @@ static const struct samsung_pin_bank_data exynos7_pin_banks7[] __initconst = {
|
|||
|
||||
/* pin banks of exynos7 pin-controller - BUS1 */
|
||||
static const struct samsung_pin_bank_data exynos7_pin_banks8[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpf0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpf1", 0x04),
|
||||
EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpf2", 0x08),
|
||||
|
@ -340,6 +359,7 @@ static const struct samsung_pin_bank_data exynos7_pin_banks8[] __initconst = {
|
|||
};
|
||||
|
||||
static const struct samsung_pin_bank_data exynos7_pin_banks9[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz0", 0x00),
|
||||
EXYNOS_PIN_BANK_EINTG(4, 0x020, "gpz1", 0x04),
|
||||
};
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
|
||||
#define EXYNOS5433_PIN_BANK_EINTW_EXT(pins, reg, id, offs, pctl_idx) \
|
||||
{ \
|
||||
.type = &exynos5433_bank_type_alive, \
|
||||
.type = &exynos5433_bank_type_off, \
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_WKUP, \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -279,6 +279,32 @@ static int samsung_dt_node_to_map(struct pinctrl_dev *pctldev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
/* Forward declaration which can be used by samsung_pin_dbg_show */
|
||||
static int samsung_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *config);
|
||||
static const char * const reg_names[] = {"CON", "DAT", "PUD", "DRV", "CON_PDN",
|
||||
"PUD_PDN"};
|
||||
|
||||
static void samsung_pin_dbg_show(struct pinctrl_dev *pctldev,
|
||||
struct seq_file *s, unsigned int pin)
|
||||
{
|
||||
enum pincfg_type cfg_type;
|
||||
unsigned long config;
|
||||
int ret;
|
||||
|
||||
for (cfg_type = 0; cfg_type < PINCFG_TYPE_NUM; cfg_type++) {
|
||||
config = PINCFG_PACK(cfg_type, 0);
|
||||
ret = samsung_pinconf_get(pctldev, pin, &config);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
seq_printf(s, " %s(0x%lx)", reg_names[cfg_type],
|
||||
PINCFG_UNPACK_VALUE(config));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* list of pinctrl callbacks for the pinctrl core */
|
||||
static const struct pinctrl_ops samsung_pctrl_ops = {
|
||||
.get_groups_count = samsung_get_group_count,
|
||||
|
@ -286,6 +312,9 @@ static const struct pinctrl_ops samsung_pctrl_ops = {
|
|||
.get_group_pins = samsung_get_group_pins,
|
||||
.dt_node_to_map = samsung_dt_node_to_map,
|
||||
.dt_free_map = samsung_dt_free_map,
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
.pin_dbg_show = samsung_pin_dbg_show,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* check if the selector is a valid pin function selector */
|
||||
|
|
|
@ -44,6 +44,11 @@ config PINCTRL_PFC_R8A7745
|
|||
depends on ARCH_R8A7745
|
||||
select PINCTRL_SH_PFC
|
||||
|
||||
config PINCTRL_PFC_R8A77470
|
||||
def_bool y
|
||||
depends on ARCH_R8A77470
|
||||
select PINCTRL_SH_PFC
|
||||
|
||||
config PINCTRL_PFC_R8A7778
|
||||
def_bool y
|
||||
depends on ARCH_R8A7778
|
||||
|
@ -104,6 +109,11 @@ config PINCTRL_PFC_R8A77980
|
|||
depends on ARCH_R8A77980
|
||||
select PINCTRL_SH_PFC
|
||||
|
||||
config PINCTRL_PFC_R8A77990
|
||||
def_bool y
|
||||
depends on ARCH_R8A77990
|
||||
select PINCTRL_SH_PFC
|
||||
|
||||
config PINCTRL_PFC_R8A77995
|
||||
def_bool y
|
||||
depends on ARCH_R8A77995
|
||||
|
|
|
@ -6,6 +6,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A73A4) += pfc-r8a73a4.o
|
|||
obj-$(CONFIG_PINCTRL_PFC_R8A7740) += pfc-r8a7740.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A7743) += pfc-r8a7791.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A7745) += pfc-r8a7794.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A77470) += pfc-r8a77470.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A7778) += pfc-r8a7778.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A7779) += pfc-r8a7779.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A7790) += pfc-r8a7790.o
|
||||
|
@ -19,6 +20,7 @@ obj-$(CONFIG_PINCTRL_PFC_R8A7796) += pfc-r8a7796.o
|
|||
obj-$(CONFIG_PINCTRL_PFC_R8A77965) += pfc-r8a77965.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A77970) += pfc-r8a77970.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A77980) += pfc-r8a77980.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A77990) += pfc-r8a77990.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_R8A77995) += pfc-r8a77995.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_SH7203) += pfc-sh7203.o
|
||||
obj-$(CONFIG_PINCTRL_PFC_SH7264) += pfc-sh7264.o
|
||||
|
|
|
@ -503,6 +503,12 @@ static const struct of_device_id sh_pfc_of_table[] = {
|
|||
.data = &r8a7745_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A77470
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a77470",
|
||||
.data = &r8a77470_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A7778
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a7778",
|
||||
|
@ -575,6 +581,12 @@ static const struct of_device_id sh_pfc_of_table[] = {
|
|||
.data = &r8a77980_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A77990
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a77990",
|
||||
.data = &r8a77990_pinmux_info,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_PINCTRL_PFC_R8A77995
|
||||
{
|
||||
.compatible = "renesas,pfc-r8a77995",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1432,10 +1432,10 @@ static const u16 pinmux_data[] = {
|
|||
|
||||
/*
|
||||
* Static pins can not be muxed between different functions but
|
||||
* still needs a mark entry in the pinmux list. Add each static
|
||||
* still need mark entries in the pinmux list. Add each static
|
||||
* pin to the list without an associated function. The sh-pfc
|
||||
* core will do the right thing and skip trying to mux then pin
|
||||
* while still applying configuration to it
|
||||
* core will do the right thing and skip trying to mux the pin
|
||||
* while still applying configuration to it.
|
||||
*/
|
||||
#define FM(x) PINMUX_DATA(x##_MARK, 0),
|
||||
PINMUX_STATIC
|
||||
|
|
|
@ -1493,10 +1493,10 @@ static const u16 pinmux_data[] = {
|
|||
|
||||
/*
|
||||
* Static pins can not be muxed between different functions but
|
||||
* still needs a mark entry in the pinmux list. Add each static
|
||||
* still need mark entries in the pinmux list. Add each static
|
||||
* pin to the list without an associated function. The sh-pfc
|
||||
* core will do the right thing and skip trying to mux then pin
|
||||
* while still applying configuration to it
|
||||
* core will do the right thing and skip trying to mux the pin
|
||||
* while still applying configuration to it.
|
||||
*/
|
||||
#define FM(x) PINMUX_DATA(x##_MARK, 0),
|
||||
PINMUX_STATIC
|
||||
|
@ -3122,7 +3122,7 @@ static const unsigned int msiof3_ss1_e_mux[] = {
|
|||
MSIOF3_SS1_E_MARK,
|
||||
};
|
||||
static const unsigned int msiof3_ss2_e_pins[] = {
|
||||
/* SS1 */
|
||||
/* SS2 */
|
||||
RCAR_GP_PIN(2, 0),
|
||||
};
|
||||
static const unsigned int msiof3_ss2_e_mux[] = {
|
||||
|
|
|
@ -1499,10 +1499,10 @@ static const u16 pinmux_data[] = {
|
|||
|
||||
/*
|
||||
* Static pins can not be muxed between different functions but
|
||||
* still needs a mark entry in the pinmux list. Add each static
|
||||
* still need mark entries in the pinmux list. Add each static
|
||||
* pin to the list without an associated function. The sh-pfc
|
||||
* core will do the right thing and skip trying to mux then pin
|
||||
* while still applying configuration to it
|
||||
* core will do the right thing and skip trying to mux the pin
|
||||
* while still applying configuration to it.
|
||||
*/
|
||||
#define FM(x) PINMUX_DATA(x##_MARK, 0),
|
||||
PINMUX_STATIC
|
||||
|
@ -3122,7 +3122,7 @@ static const unsigned int msiof3_ss1_e_mux[] = {
|
|||
MSIOF3_SS1_E_MARK,
|
||||
};
|
||||
static const unsigned int msiof3_ss2_e_pins[] = {
|
||||
/* SS1 */
|
||||
/* SS2 */
|
||||
RCAR_GP_PIN(2, 0),
|
||||
};
|
||||
static const unsigned int msiof3_ss2_e_mux[] = {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -21,13 +21,15 @@
|
|||
#include "core.h"
|
||||
#include "sh_pfc.h"
|
||||
|
||||
#define CFG_FLAGS SH_PFC_PIN_CFG_DRIVE_STRENGTH
|
||||
|
||||
#define CPU_ALL_PORT(fn, sfx) \
|
||||
PORT_GP_CFG_22(0, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
|
||||
PORT_GP_CFG_28(1, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
|
||||
PORT_GP_CFG_17(2, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
|
||||
PORT_GP_CFG_17(3, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
|
||||
PORT_GP_CFG_6(4, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH), \
|
||||
PORT_GP_CFG_15(5, fn, sfx, SH_PFC_PIN_CFG_DRIVE_STRENGTH)
|
||||
PORT_GP_CFG_22(0, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE), \
|
||||
PORT_GP_CFG_28(1, fn, sfx, CFG_FLAGS), \
|
||||
PORT_GP_CFG_17(2, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE), \
|
||||
PORT_GP_CFG_17(3, fn, sfx, CFG_FLAGS | SH_PFC_PIN_CFG_IO_VOLTAGE), \
|
||||
PORT_GP_CFG_6(4, fn, sfx, CFG_FLAGS), \
|
||||
PORT_GP_CFG_15(5, fn, sfx, CFG_FLAGS)
|
||||
/*
|
||||
* F_() : just information
|
||||
* FM() : macro for FN_xxx / xxx_MARK
|
||||
|
@ -2382,18 +2384,31 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
|
|||
{ },
|
||||
};
|
||||
|
||||
enum ioctrl_regs {
|
||||
IOCTRL30,
|
||||
IOCTRL31,
|
||||
IOCTRL32,
|
||||
};
|
||||
|
||||
static const struct pinmux_ioctrl_reg pinmux_ioctrl_regs[] = {
|
||||
[IOCTRL30] = { 0xe6060380 },
|
||||
[IOCTRL31] = { 0xe6060384 },
|
||||
[IOCTRL32] = { 0xe6060388 },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static int r8a77970_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin,
|
||||
u32 *pocctrl)
|
||||
{
|
||||
int bit = pin & 0x1f;
|
||||
|
||||
*pocctrl = 0xe6060380;
|
||||
*pocctrl = pinmux_ioctrl_regs[IOCTRL30].reg;
|
||||
if (pin >= RCAR_GP_PIN(0, 0) && pin <= RCAR_GP_PIN(0, 21))
|
||||
return bit;
|
||||
if (pin >= RCAR_GP_PIN(2, 0) && pin <= RCAR_GP_PIN(2, 9))
|
||||
return bit + 22;
|
||||
|
||||
*pocctrl += 4;
|
||||
*pocctrl = pinmux_ioctrl_regs[IOCTRL31].reg;
|
||||
if (pin >= RCAR_GP_PIN(2, 10) && pin <= RCAR_GP_PIN(2, 16))
|
||||
return bit - 10;
|
||||
if (pin >= RCAR_GP_PIN(3, 0) && pin <= RCAR_GP_PIN(3, 16))
|
||||
|
@ -2421,6 +2436,7 @@ const struct sh_pfc_soc_info r8a77970_pinmux_info = {
|
|||
.nr_functions = ARRAY_SIZE(pinmux_functions),
|
||||
|
||||
.cfg_regs = pinmux_config_regs,
|
||||
.ioctrl_regs = pinmux_ioctrl_regs,
|
||||
|
||||
.pinmux_data = pinmux_data,
|
||||
.pinmux_data_size = ARRAY_SIZE(pinmux_data),
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
#include "sh_pfc.h"
|
||||
|
||||
#define CPU_ALL_PORT(fn, sfx) \
|
||||
PORT_GP_22(0, fn, sfx), \
|
||||
PORT_GP_CFG_22(0, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE), \
|
||||
PORT_GP_28(1, fn, sfx), \
|
||||
PORT_GP_30(2, fn, sfx), \
|
||||
PORT_GP_17(3, fn, sfx), \
|
||||
PORT_GP_CFG_30(2, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE), \
|
||||
PORT_GP_CFG_17(3, fn, sfx, SH_PFC_PIN_CFG_IO_VOLTAGE), \
|
||||
PORT_GP_25(4, fn, sfx), \
|
||||
PORT_GP_15(5, fn, sfx)
|
||||
|
||||
|
@ -2779,8 +2779,53 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = {
|
|||
{ },
|
||||
};
|
||||
|
||||
enum ioctrl_regs {
|
||||
IOCTRL30,
|
||||
IOCTRL31,
|
||||
IOCTRL32,
|
||||
IOCTRL33,
|
||||
};
|
||||
|
||||
static const struct pinmux_ioctrl_reg pinmux_ioctrl_regs[] = {
|
||||
[IOCTRL30] = { 0xe6060380, },
|
||||
[IOCTRL31] = { 0xe6060384, },
|
||||
[IOCTRL32] = { 0xe6060388, },
|
||||
[IOCTRL33] = { 0xe606038c, },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static int r8a77980_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin,
|
||||
u32 *pocctrl)
|
||||
{
|
||||
int bit = pin & 0x1f;
|
||||
|
||||
*pocctrl = pinmux_ioctrl_regs[IOCTRL30].reg;
|
||||
if (pin >= RCAR_GP_PIN(0, 0) && pin <= RCAR_GP_PIN(0, 21))
|
||||
return bit;
|
||||
else if (pin >= RCAR_GP_PIN(2, 0) && pin <= RCAR_GP_PIN(2, 9))
|
||||
return bit + 22;
|
||||
|
||||
*pocctrl = pinmux_ioctrl_regs[IOCTRL31].reg;
|
||||
if (pin >= RCAR_GP_PIN(2, 10) && pin <= RCAR_GP_PIN(2, 16))
|
||||
return bit - 10;
|
||||
if ((pin >= RCAR_GP_PIN(2, 17) && pin <= RCAR_GP_PIN(2, 24)) ||
|
||||
(pin >= RCAR_GP_PIN(3, 0) && pin <= RCAR_GP_PIN(3, 16)))
|
||||
return bit + 7;
|
||||
|
||||
*pocctrl = pinmux_ioctrl_regs[IOCTRL32].reg;
|
||||
if (pin >= RCAR_GP_PIN(2, 25) && pin <= RCAR_GP_PIN(2, 29))
|
||||
return pin - 25;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct sh_pfc_soc_operations pinmux_ops = {
|
||||
.pin_to_pocctrl = r8a77980_pin_to_pocctrl,
|
||||
};
|
||||
|
||||
const struct sh_pfc_soc_info r8a77980_pinmux_info = {
|
||||
.name = "r8a77980_pfc",
|
||||
.ops = &pinmux_ops,
|
||||
.unlock_reg = 0xe6060000, /* PMMR */
|
||||
|
||||
.function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
|
||||
|
@ -2793,6 +2838,7 @@ const struct sh_pfc_soc_info r8a77980_pinmux_info = {
|
|||
.nr_functions = ARRAY_SIZE(pinmux_functions),
|
||||
|
||||
.cfg_regs = pinmux_config_regs,
|
||||
.ioctrl_regs = pinmux_ioctrl_regs,
|
||||
|
||||
.pinmux_data = pinmux_data,
|
||||
.pinmux_data_size = ARRAY_SIZE(pinmux_data),
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -274,6 +274,7 @@ extern const struct sh_pfc_soc_info r8a73a4_pinmux_info;
|
|||
extern const struct sh_pfc_soc_info r8a7740_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a7743_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a7745_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a77470_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a7778_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a7779_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a7790_pinmux_info;
|
||||
|
@ -287,6 +288,7 @@ extern const struct sh_pfc_soc_info r8a7796_pinmux_info;
|
|||
extern const struct sh_pfc_soc_info r8a77965_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a77970_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a77980_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a77990_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info r8a77995_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info sh7203_pinmux_info;
|
||||
extern const struct sh_pfc_soc_info sh7264_pinmux_info;
|
||||
|
@ -415,9 +417,13 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info;
|
|||
PORT_GP_CFG_1(bank, 9, fn, sfx, cfg)
|
||||
#define PORT_GP_10(bank, fn, sfx) PORT_GP_CFG_10(bank, fn, sfx, 0)
|
||||
|
||||
#define PORT_GP_CFG_12(bank, fn, sfx, cfg) \
|
||||
#define PORT_GP_CFG_11(bank, fn, sfx, cfg) \
|
||||
PORT_GP_CFG_10(bank, fn, sfx, cfg), \
|
||||
PORT_GP_CFG_1(bank, 10, fn, sfx, cfg), \
|
||||
PORT_GP_CFG_1(bank, 10, fn, sfx, cfg)
|
||||
#define PORT_GP_11(bank, fn, sfx) PORT_GP_CFG_11(bank, fn, sfx, 0)
|
||||
|
||||
#define PORT_GP_CFG_12(bank, fn, sfx, cfg) \
|
||||
PORT_GP_CFG_11(bank, fn, sfx, cfg), \
|
||||
PORT_GP_CFG_1(bank, 11, fn, sfx, cfg)
|
||||
#define PORT_GP_12(bank, fn, sfx) PORT_GP_CFG_12(bank, fn, sfx, 0)
|
||||
|
||||
|
|
|
@ -81,4 +81,8 @@ config PINCTRL_SUN50I_H6
|
|||
def_bool ARM64 && ARCH_SUNXI
|
||||
select PINCTRL_SUNXI
|
||||
|
||||
config PINCTRL_SUN50I_H6_R
|
||||
def_bool ARM64 && ARCH_SUNXI
|
||||
select PINCTRL_SUNXI
|
||||
|
||||
endif
|
||||
|
|
|
@ -19,5 +19,6 @@ obj-$(CONFIG_PINCTRL_SUN8I_H3_R) += pinctrl-sun8i-h3-r.o
|
|||
obj-$(CONFIG_PINCTRL_SUN8I_V3S) += pinctrl-sun8i-v3s.o
|
||||
obj-$(CONFIG_PINCTRL_SUN50I_H5) += pinctrl-sun50i-h5.o
|
||||
obj-$(CONFIG_PINCTRL_SUN50I_H6) += pinctrl-sun50i-h6.o
|
||||
obj-$(CONFIG_PINCTRL_SUN50I_H6_R) += pinctrl-sun50i-h6-r.o
|
||||
obj-$(CONFIG_PINCTRL_SUN9I_A80) += pinctrl-sun9i-a80.o
|
||||
obj-$(CONFIG_PINCTRL_SUN9I_A80_R) += pinctrl-sun9i-a80-r.o
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Allwinner H6 R_PIO pin controller driver
|
||||
*
|
||||
* Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
|
||||
*
|
||||
* Based on pinctrl-sun6i-a31-r.c, which is:
|
||||
* Copyright (C) 2014 Boris Brezillon
|
||||
* Boris Brezillon <boris.brezillon@free-electrons.com>
|
||||
* Copyright (C) 2014 Maxime Ripard
|
||||
* Maxime Ripard <maxime.ripard@free-electrons.com>
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include "pinctrl-sunxi.h"
|
||||
|
||||
static const struct sunxi_desc_pin sun50i_h6_r_pins[] = {
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x3, "s_i2c"), /* SCK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PL_EINT0 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x3, "s_i2c"), /* SDA */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PL_EINT1 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "s_uart"), /* TX */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)), /* PL_EINT2 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 3),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "s_uart"), /* RX */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)), /* PL_EINT3 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 4),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "s_jtag"), /* MS */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)), /* PL_EINT4 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 5),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "s_jtag"), /* CK */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)), /* PL_EINT5 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 6),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "s_jtag"), /* DO */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)), /* PL_EINT6 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 7),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "s_jtag"), /* DI */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)), /* PL_EINT7 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 8),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "s_pwm"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)), /* PL_EINT8 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 9),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "s_cir_rx"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)), /* PL_EINT9 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 10),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "s_w1"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)), /* PL_EINT10 */
|
||||
/* Hole */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 0),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)), /* PM_EINT0 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 1),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)), /* PM_EINT1 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 2),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2), /* PM_EINT2 */
|
||||
SUNXI_FUNCTION(0x3, "1wire")),
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 3),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)), /* PM_EINT3 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 4),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)), /* PM_EINT4 */
|
||||
};
|
||||
|
||||
static const struct sunxi_pinctrl_desc sun50i_h6_r_pinctrl_data = {
|
||||
.pins = sun50i_h6_r_pins,
|
||||
.npins = ARRAY_SIZE(sun50i_h6_r_pins),
|
||||
.pin_base = PL_BASE,
|
||||
.irq_banks = 2,
|
||||
};
|
||||
|
||||
static int sun50i_h6_r_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
return sunxi_pinctrl_init(pdev,
|
||||
&sun50i_h6_r_pinctrl_data);
|
||||
}
|
||||
|
||||
static const struct of_device_id sun50i_h6_r_pinctrl_match[] = {
|
||||
{ .compatible = "allwinner,sun50i-h6-r-pinctrl", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver sun50i_h6_r_pinctrl_driver = {
|
||||
.probe = sun50i_h6_r_pinctrl_probe,
|
||||
.driver = {
|
||||
.name = "sun50i-h6-r-pinctrl",
|
||||
.of_match_table = sun50i_h6_r_pinctrl_match,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(sun50i_h6_r_pinctrl_driver);
|
|
@ -33,17 +33,6 @@
|
|||
#include "../pinctrl-utils.h"
|
||||
#include "pinctrl-tegra.h"
|
||||
|
||||
struct tegra_pmx {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pctl;
|
||||
|
||||
const struct tegra_pinctrl_soc_data *soc;
|
||||
const char **group_pins;
|
||||
|
||||
int nbanks;
|
||||
void __iomem **regs;
|
||||
};
|
||||
|
||||
static inline u32 pmx_readl(struct tegra_pmx *pmx, u32 bank, u32 reg)
|
||||
{
|
||||
return readl(pmx->regs[bank] + reg);
|
||||
|
|
|
@ -16,6 +16,17 @@
|
|||
#ifndef __PINMUX_TEGRA_H__
|
||||
#define __PINMUX_TEGRA_H__
|
||||
|
||||
struct tegra_pmx {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pctl;
|
||||
|
||||
const struct tegra_pinctrl_soc_data *soc;
|
||||
const char **group_pins;
|
||||
|
||||
int nbanks;
|
||||
void __iomem **regs;
|
||||
};
|
||||
|
||||
enum tegra_pinconf_param {
|
||||
/* argument: tegra_pinconf_pull */
|
||||
TEGRA_PINCONF_PARAM_PULL,
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
* more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
@ -2231,9 +2232,36 @@ static const struct tegra_pinctrl_soc_data tegra20_pinctrl = {
|
|||
.drvtype_in_mux = false,
|
||||
};
|
||||
|
||||
static const char *cdev1_parents[] = {
|
||||
"dev1_osc_div", "pll_a_out0", "pll_m_out1", "audio",
|
||||
};
|
||||
|
||||
static const char *cdev2_parents[] = {
|
||||
"dev2_osc_div", "hclk", "pclk", "pll_p_out4",
|
||||
};
|
||||
|
||||
static void tegra20_pinctrl_register_clock_muxes(struct platform_device *pdev)
|
||||
{
|
||||
struct tegra_pmx *pmx = platform_get_drvdata(pdev);
|
||||
|
||||
clk_register_mux(NULL, "cdev1_mux", cdev1_parents, 4, 0,
|
||||
pmx->regs[1] + 0x8, 2, 2, CLK_MUX_READ_ONLY, NULL);
|
||||
|
||||
clk_register_mux(NULL, "cdev2_mux", cdev2_parents, 4, 0,
|
||||
pmx->regs[1] + 0x8, 4, 2, CLK_MUX_READ_ONLY, NULL);
|
||||
}
|
||||
|
||||
static int tegra20_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
return tegra_pinctrl_probe(pdev, &tegra20_pinctrl);
|
||||
int err;
|
||||
|
||||
err = tegra_pinctrl_probe(pdev, &tegra20_pinctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
tegra20_pinctrl_register_clock_muxes(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id tegra20_pinctrl_of_match[] = {
|
||||
|
|
|
@ -481,6 +481,31 @@ static const int emmc_dat8_muxvals[] = {0, 0, 0, 0};
|
|||
static const unsigned ether_rmii_pins[] = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
16, 17};
|
||||
static const int ether_rmii_muxvals[] = {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
|
||||
static const unsigned hscin0_ci_pins[] = {102, 103, 104, 105, 106, 107, 108,
|
||||
109, 110, 111, 112};
|
||||
static const int hscin0_ci_muxvals[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
static const unsigned hscin0_p_pins[] = {102, 103, 104, 105, 106, 107, 108, 109,
|
||||
110, 111, 112};
|
||||
static const int hscin0_p_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static const unsigned hscin0_s_pins[] = {116, 117, 118, 119};
|
||||
static const int hscin0_s_muxvals[] = {3, 3, 3, 3};
|
||||
static const unsigned hscin1_p_pins[] = {124, 125, 126, 127, 128, 129, 130, 131,
|
||||
132, 133, 134};
|
||||
static const int hscin1_p_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static const unsigned hscin1_s_pins[] = {120, 121, 122, 123};
|
||||
static const int hscin1_s_muxvals[] = {3, 3, 3, 3};
|
||||
static const unsigned hscin2_s_pins[] = {124, 125, 126, 127};
|
||||
static const int hscin2_s_muxvals[] = {3, 3, 3, 3};
|
||||
static const unsigned hscout0_ci_pins[] = {113, 114, 115, 116, 117, 118, 119,
|
||||
120, 121, 122, 123};
|
||||
static const int hscout0_ci_muxvals[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
static const unsigned hscout0_p_pins[] = {113, 114, 115, 116, 117, 118, 119,
|
||||
120, 121, 122, 123};
|
||||
static const int hscout0_p_muxvals[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
static const unsigned hscout0_s_pins[] = {116, 117, 118, 119};
|
||||
static const int hscout0_s_muxvals[] = {4, 4, 4, 4};
|
||||
static const unsigned hscout1_s_pins[] = {120, 121, 122, 123};
|
||||
static const int hscout1_s_muxvals[] = {4, 4, 4, 4};
|
||||
static const unsigned i2c0_pins[] = {63, 64};
|
||||
static const int i2c0_muxvals[] = {0, 0};
|
||||
static const unsigned i2c1_pins[] = {65, 66};
|
||||
|
@ -556,6 +581,16 @@ static const struct uniphier_pinctrl_group uniphier_ld11_groups[] = {
|
|||
UNIPHIER_PINCTRL_GROUP(emmc),
|
||||
UNIPHIER_PINCTRL_GROUP(emmc_dat8),
|
||||
UNIPHIER_PINCTRL_GROUP(ether_rmii),
|
||||
UNIPHIER_PINCTRL_GROUP(hscin0_ci),
|
||||
UNIPHIER_PINCTRL_GROUP(hscin0_p),
|
||||
UNIPHIER_PINCTRL_GROUP(hscin0_s),
|
||||
UNIPHIER_PINCTRL_GROUP(hscin1_p),
|
||||
UNIPHIER_PINCTRL_GROUP(hscin1_s),
|
||||
UNIPHIER_PINCTRL_GROUP(hscin2_s),
|
||||
UNIPHIER_PINCTRL_GROUP(hscout0_ci),
|
||||
UNIPHIER_PINCTRL_GROUP(hscout0_p),
|
||||
UNIPHIER_PINCTRL_GROUP(hscout0_s),
|
||||
UNIPHIER_PINCTRL_GROUP(hscout1_s),
|
||||
UNIPHIER_PINCTRL_GROUP(i2c0),
|
||||
UNIPHIER_PINCTRL_GROUP(i2c1),
|
||||
UNIPHIER_PINCTRL_GROUP(i2c3),
|
||||
|
@ -583,6 +618,15 @@ static const char * const aout1_groups[] = {"aout1"};
|
|||
static const char * const aoutiec1_groups[] = {"aoutiec1"};
|
||||
static const char * const emmc_groups[] = {"emmc", "emmc_dat8"};
|
||||
static const char * const ether_rmii_groups[] = {"ether_rmii"};
|
||||
static const char * const hscin0_groups[] = {"hscin0_ci",
|
||||
"hscin0_p",
|
||||
"hscin0_s"};
|
||||
static const char * const hscin1_groups[] = {"hscin1_p", "hscin1_s"};
|
||||
static const char * const hscin2_groups[] = {"hscin2_s"};
|
||||
static const char * const hscout0_groups[] = {"hscout0_ci",
|
||||
"hscout0_p",
|
||||
"hscout0_s"};
|
||||
static const char * const hscout1_groups[] = {"hscout1_s"};
|
||||
static const char * const i2c0_groups[] = {"i2c0"};
|
||||
static const char * const i2c1_groups[] = {"i2c1"};
|
||||
static const char * const i2c3_groups[] = {"i2c3"};
|
||||
|
@ -603,6 +647,11 @@ static const struct uniphier_pinmux_function uniphier_ld11_functions[] = {
|
|||
UNIPHIER_PINMUX_FUNCTION(aoutiec1),
|
||||
UNIPHIER_PINMUX_FUNCTION(emmc),
|
||||
UNIPHIER_PINMUX_FUNCTION(ether_rmii),
|
||||
UNIPHIER_PINMUX_FUNCTION(hscin0),
|
||||
UNIPHIER_PINMUX_FUNCTION(hscin1),
|
||||
UNIPHIER_PINMUX_FUNCTION(hscin2),
|
||||
UNIPHIER_PINMUX_FUNCTION(hscout0),
|
||||
UNIPHIER_PINMUX_FUNCTION(hscout1),
|
||||
UNIPHIER_PINMUX_FUNCTION(i2c0),
|
||||
UNIPHIER_PINMUX_FUNCTION(i2c1),
|
||||
UNIPHIER_PINMUX_FUNCTION(i2c3),
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue