mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 20:51:44 +00:00
This is the bulk of pin control changes for the v4.20 series:
There were no significant changes to the core this time! New drivers: - Broadcom Northstar pin control driver. - Mediatek MT8183 subdriver. - Mediatek MT7623 subdriver. - Mediatek MT6765 subdriver. - Meson g12a subdriver. - Nuvoton NPCM7xx pin control and GPIO driver. - Qualcomm QCS404 pin control and GPIO subdriver. - Qualcomm SDM660 pin control and GPIO subdriver. - Renesas R8A7744 PFC subdriver. - Renesas R8A774C0 PFC subdriver. - Renesas RZ/N1 pinctrl driver Major improvements: - Pulled the GPIO support for Ingenic over from the GPIO subsystem and consolidated it all in the Ingenic pin control driver. - Major cleanups and consolidation work in all Intel drivers. - Major cleanups and consolidation work in all Mediatek drivers. - Lots of incremental improvements to the Renesas PFC pin controller family. - All drivers doing GPIO now include <linux/gpio/driver.h> and nothing else. -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJbzcMKAAoJEEEQszewGV1z7UYP/1XnwE8EyOam4XuQMQPI5t3w q6vUDClR2dgLDFdQOaSU+5+GgO9ke/RLLIcp9e4EWS7a9gcq7Q/w371GL3PplnKZ s718SJnJRUGO4Cdzz57emhsqXgJus6Clj11Gqtey+s6a5rlaJJldgRrwha2iGCaP Wn3OByCtRNlvRPDmP7EmO+BeZrYvN9xzC7trweetKxx6/QibopnrgRPmARn5HvEq 0myUQis8RSpZ3ck1Ky375WKnUkeuVoADp7PeH12gQUYdvhQ5+G9/4NDAkUuShYD/ RLylNCVwgKOU4zhH/z2Rx0zY92u6JjDphiM6GSt1z0DUf3hmp2sJkQWUrLJJmh2t MO5csePHn18UXiHSee8Uhc39dHDY5wCywScYetFZuJwhhJY9yGQ0610qpO2HQ67q 9RobHS6pH8EWqIqwFe9rg4YncWU9R7gkxHAMSEBvnrXKyHNTl35lKHwyKQzgUKDu EXbgoE7cKMTGtlD9paMltDNM9rDQfARnKxI8gW43ju0AKfIdBrWlVYwGiGxmfvpm Fzb7I6stEKs8EprgHo7/SYUZPhFpQVzX+VMWQxbag2aQoMx1jHGYT4yDf7Z1Liy0 2/8SZDqOnyWOCt/Npb/v7yS8+9FQ3PL3OndsgfoZIKyyBTO+lnMzXVFkn0g9umXc 5rASYfGie9JTXW7XeQ17 =rBtH -----END PGP SIGNATURE----- Merge tag 'pinctrl-v4.20-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 the v4.20 series: There were no significant changes to the core this time! Bur the new Qualcomm, Mediatek and Broadcom drivers are quite interesting as they will be used in a few million embedded devices the coming years as it seems. New drivers: - Broadcom Northstar pin control driver. - Mediatek MT8183 subdriver. - Mediatek MT7623 subdriver. - Mediatek MT6765 subdriver. - Meson g12a subdriver. - Nuvoton NPCM7xx pin control and GPIO driver. - Qualcomm QCS404 pin control and GPIO subdriver. - Qualcomm SDM660 pin control and GPIO subdriver. - Renesas R8A7744 PFC subdriver. - Renesas R8A774C0 PFC subdriver. - Renesas RZ/N1 pinctrl driver Major improvements: - Pulled the GPIO support for Ingenic over from the GPIO subsystem and consolidated it all in the Ingenic pin control driver. - Major cleanups and consolidation work in all Intel drivers. - Major cleanups and consolidation work in all Mediatek drivers. - Lots of incremental improvements to the Renesas PFC pin controller family. - All drivers doing GPIO now include <linux/gpio/driver.h> and nothing else" * tag 'pinctrl-v4.20-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (153 commits) pinctrl: sunxi: Fix a memory leak in 'sunxi_pinctrl_build_state()' gpio: uniphier: include <linux/bits.h> instead of <linux/bitops.h> pinctrl: uniphier: include <linux/bits.h> instead of <linux/bitops.h> dt-bindings: pinctrl: bcm4708-pinmux: improve example binding pinctrl: geminilake: Sort register offsets by value pinctrl: geminilake: Get rid of unneeded ->probe() stub pinctrl: geminilake: Update pin list for B0 stepping pinctrl: renesas: Fix platform_no_drv_owner.cocci warnings pinctrl: mediatek: Make eint_m u16 pinctrl: bcm: ns: Use uintptr_t for casting data pinctrl: madera: Fix uninitialized variable bug in madera_mux_set_mux pinctrl: gemini: Fix up TVC clock group pinctrl: gemini: Drop noisy debug prints pinctrl: gemini: Mask and set properly pinctrl: mediatek: select GPIOLIB pinctrl: rza1: don't manually release devm managed resources MAINTAINERS: update entry for Mediatek pin controller pinctrl: bcm: add Northstar driver dt-bindings: pinctrl: document Broadcom Northstar pin mux controller pinctrl: qcom: fix 'const' pointer handling ...
This commit is contained in:
commit
b0b6a28bc4
@ -1,46 +0,0 @@
|
||||
Ingenic jz47xx GPIO controller
|
||||
|
||||
That the Ingenic GPIO driver node must be a sub-node of the Ingenic pinctrl
|
||||
driver node.
|
||||
|
||||
Required properties:
|
||||
--------------------
|
||||
|
||||
- compatible: Must contain one of:
|
||||
- "ingenic,jz4740-gpio"
|
||||
- "ingenic,jz4770-gpio"
|
||||
- "ingenic,jz4780-gpio"
|
||||
- reg: The GPIO bank number.
|
||||
- interrupt-controller: Marks the device node as an interrupt controller.
|
||||
- interrupts: Interrupt specifier for the controllers interrupt.
|
||||
- #interrupt-cells: Should be 2. Refer to
|
||||
../interrupt-controller/interrupts.txt for more details.
|
||||
- gpio-controller: Marks the device node as a GPIO controller.
|
||||
- #gpio-cells: Should be 2. The first cell is the GPIO number and the second
|
||||
cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. Only the
|
||||
GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
|
||||
- gpio-ranges: Range of pins managed by the GPIO controller. Refer to
|
||||
'gpio.txt' in this directory for more details.
|
||||
|
||||
Example:
|
||||
--------
|
||||
|
||||
&pinctrl {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
gpa: gpio@0 {
|
||||
compatible = "ingenic,jz4740-gpio";
|
||||
reg = <0>;
|
||||
|
||||
gpio-controller;
|
||||
gpio-ranges = <&pinctrl 0 0 32>;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <28>;
|
||||
};
|
||||
};
|
@ -0,0 +1,57 @@
|
||||
Broadcom Northstar pins mux controller
|
||||
|
||||
Some of Northstar SoCs's pins can be used for various purposes thanks to the mux
|
||||
controller. This binding allows describing mux controller and listing available
|
||||
functions. They can be referenced later by other bindings to let system
|
||||
configure controller correctly.
|
||||
|
||||
A list of pins varies across chipsets so few bindings are available.
|
||||
|
||||
Required properties:
|
||||
- compatible: must be one of:
|
||||
"brcm,bcm4708-pinmux"
|
||||
"brcm,bcm4709-pinmux"
|
||||
"brcm,bcm53012-pinmux"
|
||||
- reg: iomem address range of CRU (Central Resource Unit) pin registers
|
||||
- reg-names: "cru_gpio_control" - the only needed & supported reg right now
|
||||
|
||||
Functions and their groups available for all chipsets:
|
||||
- "spi": "spi_grp"
|
||||
- "i2c": "i2c_grp"
|
||||
- "pwm": "pwm0_grp", "pwm1_grp", "pwm2_grp", "pwm3_grp"
|
||||
- "uart1": "uart1_grp"
|
||||
|
||||
Additionally available on BCM4709 and BCM53012:
|
||||
- "mdio": "mdio_grp"
|
||||
- "uart2": "uart2_grp"
|
||||
- "sdio": "sdio_pwr_grp", "sdio_1p8v_grp"
|
||||
|
||||
For documentation of subnodes see:
|
||||
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
|
||||
|
||||
Example:
|
||||
dmu@1800c000 {
|
||||
compatible = "simple-bus";
|
||||
ranges = <0 0x1800c000 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
cru@100 {
|
||||
compatible = "simple-bus";
|
||||
reg = <0x100 0x1a4>;
|
||||
ranges;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
pin-controller@1c0 {
|
||||
compatible = "brcm,bcm4708-pinmux";
|
||||
reg = <0x1c0 0x24>;
|
||||
reg-names = "cru_gpio_control";
|
||||
|
||||
spi-pins {
|
||||
function = "spi";
|
||||
groups = "spi_grp";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -20,16 +20,30 @@ Required properties:
|
||||
|
||||
- compatible: One of:
|
||||
- "ingenic,jz4740-pinctrl"
|
||||
- "ingenic,jz4725b-pinctrl"
|
||||
- "ingenic,jz4770-pinctrl"
|
||||
- "ingenic,jz4780-pinctrl"
|
||||
- reg: Address range of the pinctrl registers.
|
||||
|
||||
|
||||
GPIO sub-nodes
|
||||
--------------
|
||||
Required properties for sub-nodes (GPIO chips):
|
||||
-----------------------------------------------
|
||||
|
||||
The pinctrl node can have optional sub-nodes for the Ingenic GPIO driver;
|
||||
please refer to ../gpio/ingenic,gpio.txt.
|
||||
- compatible: Must contain one of:
|
||||
- "ingenic,jz4740-gpio"
|
||||
- "ingenic,jz4770-gpio"
|
||||
- "ingenic,jz4780-gpio"
|
||||
- reg: The GPIO bank number.
|
||||
- interrupt-controller: Marks the device node as an interrupt controller.
|
||||
- interrupts: Interrupt specifier for the controllers interrupt.
|
||||
- #interrupt-cells: Should be 2. Refer to
|
||||
../interrupt-controller/interrupts.txt for more details.
|
||||
- gpio-controller: Marks the device node as a GPIO controller.
|
||||
- #gpio-cells: Should be 2. The first cell is the GPIO number and the second
|
||||
cell specifies GPIO flags, as defined in <dt-bindings/gpio/gpio.h>. Only the
|
||||
GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags are supported.
|
||||
- gpio-ranges: Range of pins managed by the GPIO controller. Refer to
|
||||
../gpio/gpio.txt for more details.
|
||||
|
||||
|
||||
Example:
|
||||
@ -38,4 +52,21 @@ Example:
|
||||
pinctrl: pin-controller@10010000 {
|
||||
compatible = "ingenic,jz4740-pinctrl";
|
||||
reg = <0x10010000 0x400>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
gpa: gpio@0 {
|
||||
compatible = "ingenic,jz4740-gpio";
|
||||
reg = <0>;
|
||||
|
||||
gpio-controller;
|
||||
gpio-ranges = <&pinctrl 0 0 32>;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <28>;
|
||||
};
|
||||
};
|
||||
|
@ -13,6 +13,8 @@ Required properties for the root node:
|
||||
"amlogic,meson-gxl-aobus-pinctrl"
|
||||
"amlogic,meson-axg-periphs-pinctrl"
|
||||
"amlogic,meson-axg-aobus-pinctrl"
|
||||
"amlogic,meson-g12a-periphs-pinctrl"
|
||||
"amlogic,meson-g12a-aobus-pinctrl"
|
||||
- reg: address and size of registers controlling irq functionality
|
||||
|
||||
=== GPIO sub-nodes ===
|
||||
|
@ -0,0 +1,216 @@
|
||||
Nuvoton NPCM7XX Pin Controllers
|
||||
|
||||
The Nuvoton BMC NPCM7XX Pin Controller multi-function routed through
|
||||
the multiplexing block, Each pin supports GPIO functionality (GPIOx)
|
||||
and multiple functions that directly connect the pin to different
|
||||
hardware blocks.
|
||||
|
||||
Required properties:
|
||||
- #address-cells : should be 1.
|
||||
- #size-cells : should be 1.
|
||||
- compatible : "nuvoton,npcm750-pinctrl" for Poleg NPCM7XX.
|
||||
- ranges : defines mapping ranges between pin controller node (parent)
|
||||
to GPIO bank node (children).
|
||||
|
||||
=== GPIO Bank Subnode ===
|
||||
|
||||
The NPCM7XX has 8 GPIO Banks each GPIO bank supports 32 GPIO.
|
||||
|
||||
Required GPIO Bank subnode-properties:
|
||||
- reg : specifies physical base address and size of the GPIO
|
||||
bank registers.
|
||||
- gpio-controller : Marks the device node as a GPIO controller.
|
||||
- #gpio-cells : Must be <2>. The first cell is the gpio pin number
|
||||
and the second cell is used for optional parameters.
|
||||
- interrupts : contain the GPIO bank interrupt with flags for falling edge.
|
||||
- gpio-ranges : defines the range of pins managed by the GPIO bank controller.
|
||||
|
||||
For example, GPIO bank subnodes like the following:
|
||||
gpio0: gpio@f0010000 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
reg = <0x0 0x80>;
|
||||
interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
|
||||
gpio-ranges = <&pinctrl 0 0 32>;
|
||||
};
|
||||
|
||||
=== Pin Mux Subnode ===
|
||||
|
||||
- pin: A string containing the name of the pin
|
||||
An array of strings, each string containing the name of a pin.
|
||||
These pin are used for selecting pin configuration.
|
||||
|
||||
The following are the list of pins available:
|
||||
"GPIO0/IOX1DI", "GPIO1/IOX1LD", "GPIO2/IOX1CK", "GPIO3/IOX1D0",
|
||||
"GPIO4/IOX2DI/SMB1DSDA", "GPIO5/IOX2LD/SMB1DSCL", "GPIO6/IOX2CK/SMB2DSDA",
|
||||
"GPIO7/IOX2D0/SMB2DSCL", "GPIO8/LKGPO1", "GPIO9/LKGPO2", "GPIO10/IOXHLD",
|
||||
"GPIO11/IOXHCK", "GPIO12/GSPICK/SMB5BSCL", "GPIO13/GSPIDO/SMB5BSDA",
|
||||
"GPIO14/GSPIDI/SMB5CSCL", "GPIO15/GSPICS/SMB5CSDA", "GPIO16/LKGPO0",
|
||||
"GPIO17/PSPI2DI/SMB4DEN","GPIO18/PSPI2D0/SMB4BSDA", "GPIO19/PSPI2CK/SMB4BSCL",
|
||||
"GPIO20/SMB4CSDA/SMB15SDA", "GPIO21/SMB4CSCL/SMB15SCL", "GPIO22/SMB4DSDA/SMB14SDA",
|
||||
"GPIO23/SMB4DSCL/SMB14SCL", "GPIO24/IOXHDO", "GPIO25/IOXHDI", "GPIO26/SMB5SDA",
|
||||
"GPIO27/SMB5SCL", "GPIO28/SMB4SDA", "GPIO29/SMB4SCL", "GPIO30/SMB3SDA",
|
||||
"GPIO31/SMB3SCL", "GPIO32/nSPI0CS1","SPI0D2", "SPI0D3", "GPIO37/SMB3CSDA",
|
||||
"GPIO38/SMB3CSCL", "GPIO39/SMB3BSDA", "GPIO40/SMB3BSCL", "GPIO41/BSPRXD",
|
||||
"GPO42/BSPTXD/STRAP11", "GPIO43/RXD1/JTMS2/BU1RXD", "GPIO44/nCTS1/JTDI2/BU1CTS",
|
||||
"GPIO45/nDCD1/JTDO2", "GPIO46/nDSR1/JTCK2", "GPIO47/nRI1/JCP_RDY2",
|
||||
"GPIO48/TXD2/BSPTXD", "GPIO49/RXD2/BSPRXD", "GPIO50/nCTS2", "GPO51/nRTS2/STRAP2",
|
||||
"GPIO52/nDCD2", "GPO53/nDTR2_BOUT2/STRAP1", "GPIO54/nDSR2", "GPIO55/nRI2",
|
||||
"GPIO56/R1RXERR", "GPIO57/R1MDC", "GPIO58/R1MDIO", "GPIO59/SMB3DSDA",
|
||||
"GPIO60/SMB3DSCL", "GPO61/nDTR1_BOUT1/STRAP6", "GPO62/nRTST1/STRAP5",
|
||||
"GPO63/TXD1/STRAP4", "GPIO64/FANIN0", "GPIO65/FANIN1", "GPIO66/FANIN2",
|
||||
"GPIO67/FANIN3", "GPIO68/FANIN4", "GPIO69/FANIN5", "GPIO70/FANIN6", "GPIO71/FANIN7",
|
||||
"GPIO72/FANIN8", "GPIO73/FANIN9", "GPIO74/FANIN10", "GPIO75/FANIN11",
|
||||
"GPIO76/FANIN12", "GPIO77/FANIN13","GPIO78/FANIN14", "GPIO79/FANIN15",
|
||||
"GPIO80/PWM0", "GPIO81/PWM1", "GPIO82/PWM2", "GPIO83/PWM3", "GPIO84/R2TXD0",
|
||||
"GPIO85/R2TXD1", "GPIO86/R2TXEN", "GPIO87/R2RXD0", "GPIO88/R2RXD1", "GPIO89/R2CRSDV",
|
||||
"GPIO90/R2RXERR", "GPIO91/R2MDC", "GPIO92/R2MDIO", "GPIO93/GA20/SMB5DSCL",
|
||||
"GPIO94/nKBRST/SMB5DSDA", "GPIO95/nLRESET/nESPIRST", "GPIO96/RG1TXD0",
|
||||
"GPIO97/RG1TXD1", "GPIO98/RG1TXD2", "GPIO99/RG1TXD3","GPIO100/RG1TXC",
|
||||
"GPIO101/RG1TXCTL", "GPIO102/RG1RXD0", "GPIO103/RG1RXD1", "GPIO104/RG1RXD2",
|
||||
"GPIO105/RG1RXD3", "GPIO106/RG1RXC", "GPIO107/RG1RXCTL", "GPIO108/RG1MDC",
|
||||
"GPIO109/RG1MDIO", "GPIO110/RG2TXD0/DDRV0", "GPIO111/RG2TXD1/DDRV1",
|
||||
"GPIO112/RG2TXD2/DDRV2", "GPIO113/RG2TXD3/DDRV3", "GPIO114/SMB0SCL",
|
||||
"GPIO115/SMB0SDA", "GPIO116/SMB1SCL", "GPIO117/SMB1SDA", "GPIO118/SMB2SCL",
|
||||
"GPIO119/SMB2SDA", "GPIO120/SMB2CSDA", "GPIO121/SMB2CSCL", "GPIO122/SMB2BSDA",
|
||||
"GPIO123/SMB2BSCL", "GPIO124/SMB1CSDA", "GPIO125/SMB1CSCL","GPIO126/SMB1BSDA",
|
||||
"GPIO127/SMB1BSCL", "GPIO128/SMB8SCL", "GPIO129/SMB8SDA", "GPIO130/SMB9SCL",
|
||||
"GPIO131/SMB9SDA", "GPIO132/SMB10SCL", "GPIO133/SMB10SDA","GPIO134/SMB11SCL",
|
||||
"GPIO135/SMB11SDA", "GPIO136/SD1DT0", "GPIO137/SD1DT1", "GPIO138/SD1DT2",
|
||||
"GPIO139/SD1DT3", "GPIO140/SD1CLK", "GPIO141/SD1WP", "GPIO142/SD1CMD",
|
||||
"GPIO143/SD1CD/SD1PWR", "GPIO144/PWM4", "GPIO145/PWM5", "GPIO146/PWM6",
|
||||
"GPIO147/PWM7", "GPIO148/MMCDT4", "GPIO149/MMCDT5", "GPIO150/MMCDT6",
|
||||
"GPIO151/MMCDT7", "GPIO152/MMCCLK", "GPIO153/MMCWP", "GPIO154/MMCCMD",
|
||||
"GPIO155/nMMCCD/nMMCRST", "GPIO156/MMCDT0", "GPIO157/MMCDT1", "GPIO158/MMCDT2",
|
||||
"GPIO159/MMCDT3", "GPIO160/CLKOUT/RNGOSCOUT", "GPIO161/nLFRAME/nESPICS",
|
||||
"GPIO162/SERIRQ", "GPIO163/LCLK/ESPICLK", "GPIO164/LAD0/ESPI_IO0",
|
||||
"GPIO165/LAD1/ESPI_IO1", "GPIO166/LAD2/ESPI_IO2", "GPIO167/LAD3/ESPI_IO3",
|
||||
"GPIO168/nCLKRUN/nESPIALERT", "GPIO169/nSCIPME", "GPIO170/nSMI", "GPIO171/SMB6SCL",
|
||||
"GPIO172/SMB6SDA", "GPIO173/SMB7SCL", "GPIO174/SMB7SDA", "GPIO175/PSPI1CK/FANIN19",
|
||||
"GPIO176/PSPI1DO/FANIN18", "GPIO177/PSPI1DI/FANIN17", "GPIO178/R1TXD0",
|
||||
"GPIO179/R1TXD1", "GPIO180/R1TXEN", "GPIO181/R1RXD0", "GPIO182/R1RXD1",
|
||||
"GPIO183/SPI3CK", "GPO184/SPI3D0/STRAP9", "GPO185/SPI3D1/STRAP10",
|
||||
"GPIO186/nSPI3CS0", "GPIO187/nSPI3CS1", "GPIO188/SPI3D2/nSPI3CS2",
|
||||
"GPIO189/SPI3D3/nSPI3CS3", "GPIO190/nPRD_SMI", "GPIO191", "GPIO192", "GPIO193/R1CRSDV",
|
||||
"GPIO194/SMB0BSCL", "GPIO195/SMB0BSDA", "GPIO196/SMB0CSCL", "GPIO197/SMB0DEN",
|
||||
"GPIO198/SMB0DSDA", "GPIO199/SMB0DSCL", "GPIO200/R2CK", "GPIO201/R1CK",
|
||||
"GPIO202/SMB0CSDA", "GPIO203/FANIN16", "GPIO204/DDC2SCL", "GPIO205/DDC2SDA",
|
||||
"GPIO206/HSYNC2", "GPIO207/VSYNC2", "GPIO208/RG2TXC/DVCK", "GPIO209/RG2TXCTL/DDRV4",
|
||||
"GPIO210/RG2RXD0/DDRV5", "GPIO211/RG2RXD1/DDRV6", "GPIO212/RG2RXD2/DDRV7",
|
||||
"GPIO213/RG2RXD3/DDRV8", "GPIO214/RG2RXC/DDRV9", "GPIO215/RG2RXCTL/DDRV10",
|
||||
"GPIO216/RG2MDC/DDRV11", "GPIO217/RG2MDIO/DVHSYNC", "GPIO218/nWDO1",
|
||||
"GPIO219/nWDO2", "GPIO220/SMB12SCL", "GPIO221/SMB12SDA", "GPIO222/SMB13SCL",
|
||||
"GPIO223/SMB13SDA", "GPIO224/SPIXCK", "GPO225/SPIXD0/STRAP12", "GPO226/SPIXD1/STRAP13",
|
||||
"GPIO227/nSPIXCS0", "GPIO228/nSPIXCS1", "GPO229/SPIXD2/STRAP3", "GPIO230/SPIXD3",
|
||||
"GPIO231/nCLKREQ", "GPI255/DACOSEL"
|
||||
|
||||
Optional Properties:
|
||||
bias-disable, bias-pull-down, bias-pull-up, input-enable,
|
||||
input-disable, output-high, output-low, drive-push-pull,
|
||||
drive-open-drain, input-debounce, slew-rate, drive-strength
|
||||
|
||||
slew-rate valid arguments are:
|
||||
<0> - slow
|
||||
<1> - fast
|
||||
drive-strength valid arguments are:
|
||||
<2> - 2mA
|
||||
<4> - 4mA
|
||||
<8> - 8mA
|
||||
<12> - 12mA
|
||||
<16> - 16mA
|
||||
<24> - 24mA
|
||||
|
||||
For example, pinctrl might have pinmux subnodes like the following:
|
||||
|
||||
gpio0_iox1d1_pin: gpio0-iox1d1-pin {
|
||||
pins = "GPIO0/IOX1DI";
|
||||
output-high;
|
||||
};
|
||||
gpio0_iox1ck_pin: gpio0-iox1ck-pin {
|
||||
pins = "GPIO2/IOX1CK";
|
||||
output_high;
|
||||
};
|
||||
|
||||
=== Pin Group Subnode ===
|
||||
|
||||
Required pin group subnode-properties:
|
||||
- groups : A string containing the name of the group to mux.
|
||||
- function: A string containing the name of the function to mux to the
|
||||
group.
|
||||
|
||||
The following are the list of the available groups and functions :
|
||||
smb0, smb0b, smb0c, smb0d, smb0den, smb1, smb1b, smb1c, smb1d,
|
||||
smb2, smb2b, smb2c, smb2d, smb3, smb3b, smb3c, smb3d, smb4, smb4b,
|
||||
smb4c, smb4d, smb4den, smb5, smb5b, smb5c, smb5d, ga20kbc, smb6,
|
||||
smb7, smb8, smb9, smb10, smb11, smb12, smb13, smb14, smb15, fanin0,
|
||||
fanin1, fanin2, fanin3, fanin4, fanin5, fanin6, fanin7, fanin8,
|
||||
fanin9, fanin10, fanin11 fanin12 fanin13, fanin14, fanin15, faninx,
|
||||
pwm0, pwm1, pwm2, pwm3, pwm4, pwm5, pwm6, pwm7, rg1, rg1mdio, rg2,
|
||||
rg2mdio, ddr, uart1, uart2, bmcuart0a, bmcuart0b, bmcuart1, iox1,
|
||||
iox2, ioxh, gspi, mmc, mmcwp, mmccd, mmcrst, mmc8, r1, r1err, r1md,
|
||||
r2, r2err, r2md, sd1, sd1pwr, wdog1, wdog2, scipme, sci, serirq,
|
||||
jtag2, spix, spixcs1, pspi1, pspi2, ddc, clkreq, clkout, spi3, spi3cs1,
|
||||
spi3quad, spi3cs2, spi3cs3, spi0cs1, lpc, lpcclk, espi, lkgpo0, lkgpo1,
|
||||
lkgpo2, nprd_smi
|
||||
|
||||
For example, pinctrl might have group subnodes like the following:
|
||||
r1err_pins: r1err-pins {
|
||||
groups = "r1err";
|
||||
function = "r1err";
|
||||
};
|
||||
r1md_pins: r1md-pins {
|
||||
groups = "r1md";
|
||||
function = "r1md";
|
||||
};
|
||||
r1_pins: r1-pins {
|
||||
groups = "r1";
|
||||
function = "r1";
|
||||
};
|
||||
|
||||
Examples
|
||||
========
|
||||
pinctrl: pinctrl@f0800000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "nuvoton,npcm750-pinctrl";
|
||||
ranges = <0 0xf0010000 0x8000>;
|
||||
|
||||
gpio0: gpio@f0010000 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
reg = <0x0 0x80>;
|
||||
interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
|
||||
gpio-ranges = <&pinctrl 0 0 32>;
|
||||
};
|
||||
|
||||
....
|
||||
|
||||
gpio7: gpio@f0017000 {
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
reg = <0x7000 0x80>;
|
||||
interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
|
||||
gpio-ranges = <&pinctrl 0 224 32>;
|
||||
};
|
||||
|
||||
gpio0_iox1d1_pin: gpio0-iox1d1-pin {
|
||||
pins = "GPIO0/IOX1DI";
|
||||
output-high;
|
||||
};
|
||||
|
||||
iox1_pins: iox1-pins {
|
||||
groups = "iox1";
|
||||
function = "iox1";
|
||||
};
|
||||
iox2_pins: iox2-pins {
|
||||
groups = "iox2";
|
||||
function = "iox2";
|
||||
};
|
||||
|
||||
....
|
||||
|
||||
clkreq_pins: clkreq-pins {
|
||||
groups = "clkreq";
|
||||
function = "clkreq";
|
||||
};
|
||||
};
|
@ -19,6 +19,7 @@ PMIC's from Qualcomm.
|
||||
"qcom,pm8998-gpio"
|
||||
"qcom,pma8084-gpio"
|
||||
"qcom,pmi8994-gpio"
|
||||
"qcom,pms405-gpio"
|
||||
|
||||
And must contain either "qcom,spmi-gpio" or "qcom,ssbi-gpio"
|
||||
if the device is on an spmi bus or an ssbi bus respectively
|
||||
@ -91,6 +92,7 @@ to specify in a pin configuration subnode:
|
||||
gpio1-gpio26 for pm8998
|
||||
gpio1-gpio22 for pma8084
|
||||
gpio1-gpio10 for pmi8994
|
||||
gpio1-gpio11 for pms405
|
||||
|
||||
- function:
|
||||
Usage: required
|
||||
|
@ -0,0 +1,199 @@
|
||||
Qualcomm QCS404 TLMM block
|
||||
|
||||
This binding describes the Top Level Mode Multiplexer block found in the
|
||||
QCS404 platform.
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: must be "qcom,qcs404-pinctrl"
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: the base address and size of the north, south and east TLMM
|
||||
tiles.
|
||||
|
||||
- reg-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Defintiion: names for the cells of reg, must contain "north", "south"
|
||||
and "east".
|
||||
|
||||
- interrupts:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: should specify the TLMM summary IRQ.
|
||||
|
||||
- interrupt-controller:
|
||||
Usage: required
|
||||
Value type: <none>
|
||||
Definition: identifies this node as an interrupt controller
|
||||
|
||||
- #interrupt-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: must be 2. Specifying the pin number and flags, as defined
|
||||
in <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
- gpio-controller:
|
||||
Usage: required
|
||||
Value type: <none>
|
||||
Definition: identifies this node as a gpio controller
|
||||
|
||||
- #gpio-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: must be 2. Specifying the pin number and flags, as defined
|
||||
in <dt-bindings/gpio/gpio.h>
|
||||
|
||||
- gpio-ranges:
|
||||
Usage: required
|
||||
Definition: see ../gpio/gpio.txt
|
||||
|
||||
Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
|
||||
a general description of GPIO and interrupt bindings.
|
||||
|
||||
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".
|
||||
|
||||
The pin configuration nodes act as a container for an arbitrary number of
|
||||
subnodes. Each of these subnodes represents some desired configuration for a
|
||||
pin, a group, or a list of pins or groups. This configuration can include the
|
||||
mux function to select on those pin(s)/group(s), and various pin configuration
|
||||
parameters, such as pull-up, drive strength, etc.
|
||||
|
||||
|
||||
PIN CONFIGURATION NODES:
|
||||
|
||||
The name of each subnode is not important; all subnodes should be enumerated
|
||||
and processed purely based on their content.
|
||||
|
||||
Each subnode only affects those parameters that are explicitly listed. In
|
||||
other words, a subnode that lists a mux function but no pin configuration
|
||||
parameters implies no information about any pin configuration parameters.
|
||||
Similarly, a pin subnode that describes a pullup parameter implies no
|
||||
information about e.g. the mux function.
|
||||
|
||||
|
||||
The following generic properties as defined in pinctrl-bindings.txt are valid
|
||||
to specify in a pin configuration subnode:
|
||||
|
||||
- pins:
|
||||
Usage: required
|
||||
Value type: <string-array>
|
||||
Definition: List of gpio pins affected by the properties specified in
|
||||
this subnode.
|
||||
|
||||
Valid pins are:
|
||||
gpio0-gpio119
|
||||
Supports mux, bias and drive-strength
|
||||
|
||||
sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk, sdc2_cmd,
|
||||
sdc2_data
|
||||
Supports bias and drive-strength
|
||||
|
||||
ufs_reset
|
||||
Supports bias and drive-strength
|
||||
|
||||
- function:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: Specify the alternative function to be configured for the
|
||||
specified pins. Functions are only valid for gpio pins.
|
||||
Valid values are:
|
||||
|
||||
gpio, hdmi_tx, hdmi_ddc, blsp_uart_tx_a2, blsp_spi2, m_voc,
|
||||
qdss_cti_trig_in_a0, blsp_uart_rx_a2, qdss_tracectl_a,
|
||||
blsp_uart2, aud_cdc, blsp_i2c_sda_a2, qdss_tracedata_a,
|
||||
blsp_i2c_scl_a2, qdss_tracectl_b, qdss_cti_trig_in_b0,
|
||||
blsp_uart1, blsp_spi_mosi_a1, blsp_spi_miso_a1,
|
||||
qdss_tracedata_b, blsp_i2c1, blsp_spi_cs_n_a1, gcc_plltest,
|
||||
blsp_spi_clk_a1, rgb_data0, blsp_uart5, blsp_spi5,
|
||||
adsp_ext, rgb_data1, prng_rosc, rgb_data2, blsp_i2c5,
|
||||
gcc_gp1_clk_b, rgb_data3, gcc_gp2_clk_b, blsp_spi0,
|
||||
blsp_uart0, gcc_gp3_clk_b, blsp_i2c0, qdss_traceclk_b,
|
||||
pcie_clk, nfc_irq, blsp_spi4, nfc_dwl, audio_ts, rgb_data4,
|
||||
spi_lcd, blsp_uart_tx_b2, gcc_gp3_clk_a, rgb_data5,
|
||||
blsp_uart_rx_b2, blsp_i2c_sda_b2, blsp_i2c_scl_b2,
|
||||
pwm_led11, i2s_3_data0_a, ebi2_lcd, i2s_3_data1_a,
|
||||
i2s_3_data2_a, atest_char, pwm_led3, i2s_3_data3_a,
|
||||
pwm_led4, i2s_4, ebi2_a, dsd_clk_b, pwm_led5, pwm_led6,
|
||||
pwm_led7, pwm_led8, pwm_led24, spkr_dac0, blsp_i2c4,
|
||||
pwm_led9, pwm_led10, spdifrx_opt, pwm_led12, pwm_led13,
|
||||
pwm_led14, wlan1_adc1, rgb_data_b0, pwm_led15,
|
||||
blsp_spi_mosi_b1, wlan1_adc0, rgb_data_b1, pwm_led16,
|
||||
blsp_spi_miso_b1, qdss_cti_trig_out_b0, wlan2_adc1,
|
||||
rgb_data_b2, pwm_led17, blsp_spi_cs_n_b1, wlan2_adc0,
|
||||
rgb_data_b3, pwm_led18, blsp_spi_clk_b1, rgb_data_b4,
|
||||
pwm_led19, ext_mclk1_b, qdss_traceclk_a, rgb_data_b5,
|
||||
pwm_led20, atest_char3, i2s_3_sck_b, ldo_update, bimc_dte0,
|
||||
rgb_hsync, pwm_led21, i2s_3_ws_b, dbg_out, rgb_vsync,
|
||||
i2s_3_data0_b, ldo_en, hdmi_dtest, rgb_de, i2s_3_data1_b,
|
||||
hdmi_lbk9, rgb_clk, atest_char1, i2s_3_data2_b, ebi_cdc,
|
||||
hdmi_lbk8, rgb_mdp, atest_char0, i2s_3_data3_b, hdmi_lbk7,
|
||||
rgb_data_b6, rgb_data_b7, hdmi_lbk6, rgmii_int, cri_trng1,
|
||||
rgmii_wol, cri_trng0, gcc_tlmm, rgmii_ck, rgmii_tx,
|
||||
hdmi_lbk5, hdmi_pixel, hdmi_rcv, hdmi_lbk4, rgmii_ctl,
|
||||
ext_lpass, rgmii_rx, cri_trng, hdmi_lbk3, hdmi_lbk2,
|
||||
qdss_cti_trig_out_b1, rgmii_mdio, hdmi_lbk1, rgmii_mdc,
|
||||
hdmi_lbk0, ir_in, wsa_en, rgb_data6, rgb_data7,
|
||||
atest_char2, ebi_ch0, blsp_uart3, blsp_spi3, sd_write,
|
||||
blsp_i2c3, gcc_gp1_clk_a, qdss_cti_trig_in_b1,
|
||||
gcc_gp2_clk_a, ext_mclk0, mclk_in1, i2s_1, dsd_clk_a,
|
||||
qdss_cti_trig_in_a1, rgmi_dll1, pwm_led22, pwm_led23,
|
||||
qdss_cti_trig_out_a0, rgmi_dll2, pwm_led1,
|
||||
qdss_cti_trig_out_a1, pwm_led2, i2s_2, pll_bist,
|
||||
ext_mclk1_a, mclk_in2, bimc_dte1, i2s_3_sck_a, i2s_3_ws_a
|
||||
|
||||
- bias-disable:
|
||||
Usage: optional
|
||||
Value type: <none>
|
||||
Definition: The specified pins should be configued as no pull.
|
||||
|
||||
- bias-pull-down:
|
||||
Usage: optional
|
||||
Value type: <none>
|
||||
Definition: The specified pins should be configued as pull down.
|
||||
|
||||
- bias-pull-up:
|
||||
Usage: optional
|
||||
Value type: <none>
|
||||
Definition: The specified pins should be configued as pull up.
|
||||
|
||||
- output-high:
|
||||
Usage: optional
|
||||
Value type: <none>
|
||||
Definition: The specified pins are configured in output mode, driven
|
||||
high.
|
||||
Not valid for sdc pins.
|
||||
|
||||
- output-low:
|
||||
Usage: optional
|
||||
Value type: <none>
|
||||
Definition: The specified pins are configured in output mode, driven
|
||||
low.
|
||||
Not valid for sdc pins.
|
||||
|
||||
- drive-strength:
|
||||
Usage: optional
|
||||
Value type: <u32>
|
||||
Definition: Selects the drive strength for the specified pins, in mA.
|
||||
Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
|
||||
|
||||
Example:
|
||||
|
||||
tlmm: pinctrl@1000000 {
|
||||
compatible = "qcom,qcs404-pinctrl";
|
||||
reg = <0x01000000 0x200000>,
|
||||
<0x01300000 0x200000>,
|
||||
<0x07b00000 0x200000>;
|
||||
reg-names = "south", "north", "east";
|
||||
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&tlmm 0 0 120>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
@ -0,0 +1,191 @@
|
||||
Qualcomm Technologies, Inc. SDM660 TLMM block
|
||||
|
||||
This binding describes the Top Level Mode Multiplexer block found in the
|
||||
SDM660 platform.
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: must be "qcom,sdm660-pinctrl" or
|
||||
"qcom,sdm630-pinctrl".
|
||||
|
||||
- reg:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: the base address and size of the north, center and south
|
||||
TLMM tiles.
|
||||
|
||||
- reg-names:
|
||||
Usage: required
|
||||
Value type: <stringlist>
|
||||
Definition: names for the cells of reg, must contain "north", "center"
|
||||
and "south".
|
||||
|
||||
- interrupts:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: should specify the TLMM summary IRQ.
|
||||
|
||||
- interrupt-controller:
|
||||
Usage: required
|
||||
Value type: <none>
|
||||
Definition: identifies this node as an interrupt controller
|
||||
|
||||
- #interrupt-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: must be 2. Specifying the pin number and flags, as defined
|
||||
in <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
- gpio-controller:
|
||||
Usage: required
|
||||
Value type: <none>
|
||||
Definition: identifies this node as a gpio controller
|
||||
|
||||
- gpio-ranges:
|
||||
Usage: required
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: Specifies the mapping between gpio controller and
|
||||
pin-controller pins.
|
||||
|
||||
- #gpio-cells:
|
||||
Usage: required
|
||||
Value type: <u32>
|
||||
Definition: must be 2. Specifying the pin number and flags, as defined
|
||||
in <dt-bindings/gpio/gpio.h>
|
||||
|
||||
Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
|
||||
a general description of GPIO and interrupt bindings.
|
||||
|
||||
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".
|
||||
|
||||
The pin configuration nodes act as a container for an arbitrary number of
|
||||
subnodes. Each of these subnodes represents some desired configuration for a
|
||||
pin, a group, or a list of pins or groups. This configuration can include the
|
||||
mux function to select on those pin(s)/group(s), and various pin configuration
|
||||
parameters, such as pull-up, drive strength, etc.
|
||||
|
||||
|
||||
PIN CONFIGURATION NODES:
|
||||
|
||||
The name of each subnode is not important; all subnodes should be enumerated
|
||||
and processed purely based on their content.
|
||||
|
||||
Each subnode only affects those parameters that are explicitly listed. In
|
||||
other words, a subnode that lists a mux function but no pin configuration
|
||||
parameters implies no information about any pin configuration parameters.
|
||||
Similarly, a pin subnode that describes a pullup parameter implies no
|
||||
information about e.g. the mux function.
|
||||
|
||||
|
||||
The following generic properties as defined in pinctrl-bindings.txt are valid
|
||||
to specify in a pin configuration subnode:
|
||||
|
||||
- pins:
|
||||
Usage: required
|
||||
Value type: <string-array>
|
||||
Definition: List of gpio pins affected by the properties specified in
|
||||
this subnode. Valid pins are:
|
||||
gpio0-gpio113,
|
||||
Supports mux, bias and drive-strength
|
||||
sdc1_clk, sdc1_cmd, sdc1_data sdc2_clk, sdc2_cmd, sdc2_data sdc1_rclk,
|
||||
Supports bias and drive-strength
|
||||
|
||||
- function:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: Specify the alternative function to be configured for the
|
||||
specified pins. Functions are only valid for gpio pins.
|
||||
Valid values are:
|
||||
adsp_ext, agera_pll, atest_char, atest_char0, atest_char1,
|
||||
atest_char2, atest_char3, atest_gpsadc0, atest_gpsadc1,
|
||||
atest_tsens, atest_tsens2, atest_usb1, atest_usb10,
|
||||
atest_usb11, atest_usb12, atest_usb13, atest_usb2,
|
||||
atest_usb20, atest_usb21, atest_usb22, atest_usb23,
|
||||
audio_ref, bimc_dte0, bimc_dte1, blsp_i2c1, blsp_i2c2,
|
||||
blsp_i2c3, blsp_i2c4, blsp_i2c5, blsp_i2c6, blsp_i2c7,
|
||||
blsp_i2c8_a, blsp_i2c8_b, blsp_spi1, blsp_spi2, blsp_spi3,
|
||||
blsp_spi3_cs1, blsp_spi3_cs2, blsp_spi4, blsp_spi5,
|
||||
blsp_spi6, blsp_spi7, blsp_spi8_a, blsp_spi8_b,
|
||||
blsp_spi8_cs1, blsp_spi8_cs2, blsp_uart1, blsp_uart2,
|
||||
blsp_uart5, blsp_uart6_a, blsp_uart6_b, blsp_uim1,
|
||||
blsp_uim2, blsp_uim5, blsp_uim6, cam_mclk, cci_async,
|
||||
cci_i2c, cri_trng, cri_trng0, cri_trng1, dbg_out, ddr_bist,
|
||||
gcc_gp1, gcc_gp2, gcc_gp3, gpio, gps_tx_a, gps_tx_b, gps_tx_c,
|
||||
isense_dbg, jitter_bist, ldo_en, ldo_update, m_voc, mdp_vsync,
|
||||
mdss_vsync0, mdss_vsync1, mdss_vsync2, mdss_vsync3, mss_lte,
|
||||
nav_pps_a, nav_pps_b, nav_pps_c, pa_indicator, phase_flag0,
|
||||
phase_flag1, phase_flag10, phase_flag11, phase_flag12,
|
||||
phase_flag13, phase_flag14, phase_flag15, phase_flag16,
|
||||
phase_flag17, phase_flag18, phase_flag19, phase_flag2,
|
||||
phase_flag20, phase_flag21, phase_flag22, phase_flag23,
|
||||
phase_flag24, phase_flag25, phase_flag26, phase_flag27,
|
||||
phase_flag28, phase_flag29, phase_flag3, phase_flag30,
|
||||
phase_flag31, phase_flag4, phase_flag5, phase_flag6,
|
||||
phase_flag7, phase_flag8, phase_flag9, pll_bypassnl,
|
||||
pll_reset, pri_mi2s, pri_mi2s_ws, prng_rosc, pwr_crypto,
|
||||
pwr_modem, pwr_nav, qdss_cti0_a, qdss_cti0_b, qdss_cti1_a,
|
||||
qdss_cti1_b, qdss_gpio, qdss_gpio0, qdss_gpio1, qdss_gpio10,
|
||||
qdss_gpio11, qdss_gpio12, qdss_gpio13, qdss_gpio14, qdss_gpio15,
|
||||
qdss_gpio2, qdss_gpio3, qdss_gpio4, qdss_gpio5, qdss_gpio6,
|
||||
qdss_gpio7, qdss_gpio8, qdss_gpio9, qlink_enable, qlink_request,
|
||||
qspi_clk, qspi_cs, qspi_data0, qspi_data1, qspi_data2,
|
||||
qspi_data3, qspi_resetn, sec_mi2s, sndwire_clk, sndwire_data,
|
||||
sp_cmu, ssc_irq, tgu_ch0, tgu_ch1, tsense_pwm1, tsense_pwm2,
|
||||
uim1_clk, uim1_data, uim1_present, uim1_reset, uim2_clk,
|
||||
uim2_data, uim2_present, uim2_reset, uim_batt, vfr_1,
|
||||
vsense_clkout, vsense_data0, vsense_data1, vsense_mode,
|
||||
wlan1_adc0, wlan1_adc1, wlan2_adc0, wlan2_adc1
|
||||
|
||||
- bias-disable:
|
||||
Usage: optional
|
||||
Value type: <none>
|
||||
Definition: The specified pins should be configued as no pull.
|
||||
|
||||
- bias-pull-down:
|
||||
Usage: optional
|
||||
Value type: <none>
|
||||
Definition: The specified pins should be configued as pull down.
|
||||
|
||||
- bias-pull-up:
|
||||
Usage: optional
|
||||
Value type: <none>
|
||||
Definition: The specified pins should be configued as pull up.
|
||||
|
||||
- output-high:
|
||||
Usage: optional
|
||||
Value type: <none>
|
||||
Definition: The specified pins are configured in output mode, driven
|
||||
high.
|
||||
Not valid for sdc pins.
|
||||
|
||||
- output-low:
|
||||
Usage: optional
|
||||
Value type: <none>
|
||||
Definition: The specified pins are configured in output mode, driven
|
||||
low.
|
||||
Not valid for sdc pins.
|
||||
|
||||
- drive-strength:
|
||||
Usage: optional
|
||||
Value type: <u32>
|
||||
Definition: Selects the drive strength for the specified pins, in mA.
|
||||
Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
|
||||
|
||||
Example:
|
||||
|
||||
tlmm: pinctrl@3100000 {
|
||||
compatible = "qcom,sdm660-pinctrl";
|
||||
reg = <0x3100000 0x200000>,
|
||||
<0x3500000 0x200000>,
|
||||
<0x3900000 0x200000>;
|
||||
reg-names = "south", "center", "north";
|
||||
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
|
||||
gpio-controller;
|
||||
gpio-ranges = <&tlmm 0 0 114>;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
@ -14,8 +14,11 @@ Required Properties:
|
||||
- "renesas,pfc-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7740": for R8A7740 (R-Mobile A1) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7743": for R8A7743 (RZ/G1M) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7744": for R8A7744 (RZ/G1N) 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-r8a774a1": for R8A774A1 (RZ/G2M) compatible pin-controller.
|
||||
- "renesas,pfc-r8a774c0": for R8A774C0 (RZ/G2E) 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.
|
||||
|
@ -0,0 +1,153 @@
|
||||
Renesas RZ/N1 SoC Pinctrl node description.
|
||||
|
||||
Pin controller node
|
||||
-------------------
|
||||
Required properties:
|
||||
- compatible: SoC-specific compatible string "renesas,<soc-specific>-pinctrl"
|
||||
followed by "renesas,rzn1-pinctrl" as fallback. The SoC-specific compatible
|
||||
strings must be one of:
|
||||
"renesas,r9a06g032-pinctrl" for RZ/N1D
|
||||
"renesas,r9a06g033-pinctrl" for RZ/N1S
|
||||
- reg: Address base and length of the memory area where the pin controller
|
||||
hardware is mapped to.
|
||||
- clocks: phandle for the clock, see the description of clock-names below.
|
||||
- clock-names: Contains the name of the clock:
|
||||
"bus", the bus clock, sometimes described as pclk, for register accesses.
|
||||
|
||||
Example:
|
||||
pinctrl: pin-controller@40067000 {
|
||||
compatible = "renesas,r9a06g032-pinctrl", "renesas,rzn1-pinctrl";
|
||||
reg = <0x40067000 0x1000>, <0x51000000 0x480>;
|
||||
clocks = <&sysctrl R9A06G032_HCLK_PINCONFIG>;
|
||||
clock-names = "bus";
|
||||
};
|
||||
|
||||
Sub-nodes
|
||||
---------
|
||||
|
||||
The child nodes of the pin controller node describe a pin multiplexing
|
||||
function.
|
||||
|
||||
- Pin multiplexing sub-nodes:
|
||||
A pin multiplexing sub-node describes how to configure a set of
|
||||
(or a single) pin in some desired alternate function mode.
|
||||
A single sub-node may define several pin configurations.
|
||||
Please refer to pinctrl-bindings.txt to get to know more on generic
|
||||
pin properties usage.
|
||||
|
||||
The allowed generic formats for a pin multiplexing sub-node are the
|
||||
following ones:
|
||||
|
||||
node-1 {
|
||||
pinmux = <PIN_ID_AND_MUX>, <PIN_ID_AND_MUX>, ... ;
|
||||
GENERIC_PINCONFIG;
|
||||
};
|
||||
|
||||
node-2 {
|
||||
sub-node-1 {
|
||||
pinmux = <PIN_ID_AND_MUX>, <PIN_ID_AND_MUX>, ... ;
|
||||
GENERIC_PINCONFIG;
|
||||
};
|
||||
|
||||
sub-node-2 {
|
||||
pinmux = <PIN_ID_AND_MUX>, <PIN_ID_AND_MUX>, ... ;
|
||||
GENERIC_PINCONFIG;
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
sub-node-n {
|
||||
pinmux = <PIN_ID_AND_MUX>, <PIN_ID_AND_MUX>, ... ;
|
||||
GENERIC_PINCONFIG;
|
||||
};
|
||||
};
|
||||
|
||||
node-3 {
|
||||
pinmux = <PIN_ID_AND_MUX>, <PIN_ID_AND_MUX>, ... ;
|
||||
GENERIC_PINCONFIG;
|
||||
|
||||
sub-node-1 {
|
||||
pinmux = <PIN_ID_AND_MUX>, <PIN_ID_AND_MUX>, ... ;
|
||||
GENERIC_PINCONFIG;
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
sub-node-n {
|
||||
pinmux = <PIN_ID_AND_MUX>, <PIN_ID_AND_MUX>, ... ;
|
||||
GENERIC_PINCONFIG;
|
||||
};
|
||||
};
|
||||
|
||||
Use the latter two formats when pins part of the same logical group need to
|
||||
have different generic pin configuration flags applied. Note that the generic
|
||||
pinconfig in node-3 does not apply to the sub-nodes.
|
||||
|
||||
Client sub-nodes shall refer to pin multiplexing sub-nodes using the phandle
|
||||
of the most external one.
|
||||
|
||||
Eg.
|
||||
|
||||
client-1 {
|
||||
...
|
||||
pinctrl-0 = <&node-1>;
|
||||
...
|
||||
};
|
||||
|
||||
client-2 {
|
||||
...
|
||||
pinctrl-0 = <&node-2>;
|
||||
...
|
||||
};
|
||||
|
||||
Required properties:
|
||||
- pinmux:
|
||||
integer array representing pin number and pin multiplexing configuration.
|
||||
When a pin has to be configured in alternate function mode, use this
|
||||
property to identify the pin by its global index, and provide its
|
||||
alternate function configuration number along with it.
|
||||
When multiple pins are required to be configured as part of the same
|
||||
alternate function they shall be specified as members of the same
|
||||
argument list of a single "pinmux" property.
|
||||
Integers values in the "pinmux" argument list are assembled as:
|
||||
(PIN | MUX_FUNC << 8)
|
||||
where PIN directly corresponds to the pl_gpio pin number and MUX_FUNC is
|
||||
one of the alternate function identifiers defined in:
|
||||
<include/dt-bindings/pinctrl/rzn1-pinctrl.h>
|
||||
These identifiers collapse the IO Multiplex Configuration Level 1 and
|
||||
Level 2 numbers that are detailed in the hardware reference manual into a
|
||||
single number. The identifiers for Level 2 are simply offset by 10.
|
||||
Additional identifiers are provided to specify the MDIO source peripheral.
|
||||
|
||||
Optional generic pinconf properties:
|
||||
- bias-disable - disable any pin bias
|
||||
- bias-pull-up - pull up the pin with 50 KOhm
|
||||
- bias-pull-down - pull down the pin with 50 KOhm
|
||||
- bias-high-impedance - high impedance mode
|
||||
- drive-strength - sink or source at most 4, 6, 8 or 12 mA
|
||||
|
||||
Example:
|
||||
A serial communication interface with a TX output pin and an RX input pin.
|
||||
|
||||
&pinctrl {
|
||||
pins_uart0: pins_uart0 {
|
||||
pinmux = <
|
||||
RZN1_PINMUX(103, RZN1_FUNC_UART0_I) /* UART0_TXD */
|
||||
RZN1_PINMUX(104, RZN1_FUNC_UART0_I) /* UART0_RXD */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
Example 2:
|
||||
Here we set the pull up on the RXD pin of the UART.
|
||||
|
||||
&pinctrl {
|
||||
pins_uart0: pins_uart0 {
|
||||
pinmux = <RZN1_PINMUX(103, RZN1_FUNC_UART0_I)>; /* TXD */
|
||||
|
||||
pins_uart6_rx {
|
||||
pinmux = <RZN1_PINMUX(104, RZN1_FUNC_UART0_I)>; /* RXD */
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
};
|
@ -11519,15 +11519,12 @@ S: Maintained
|
||||
F: drivers/pinctrl/intel/
|
||||
|
||||
PIN CONTROLLER - MEDIATEK
|
||||
M: Sean Wang <sean.wang@mediatek.com>
|
||||
M: Sean Wang <sean.wang@kernel.org>
|
||||
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
|
||||
F: drivers/pinctrl/mediatek/
|
||||
|
||||
PIN CONTROLLER - QUALCOMM
|
||||
M: Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
@ -267,17 +267,6 @@ config GPIO_ICH
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config GPIO_INGENIC
|
||||
tristate "Ingenic JZ47xx SoCs GPIO support"
|
||||
depends on OF
|
||||
depends on MACH_INGENIC || COMPILE_TEST
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say yes here to support the GPIO functionality present on the
|
||||
JZ4740 and JZ4780 SoCs from Ingenic.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config GPIO_IOP
|
||||
tristate "Intel IOP GPIO"
|
||||
depends on ARCH_IOP32X || ARCH_IOP33X || COMPILE_TEST
|
||||
|
@ -57,7 +57,6 @@ obj-$(CONFIG_GPIO_GRGPIO) += gpio-grgpio.o
|
||||
obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o
|
||||
obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o
|
||||
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
|
||||
obj-$(CONFIG_GPIO_INGENIC) += gpio-ingenic.o
|
||||
obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
|
||||
obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
|
||||
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
|
||||
|
@ -1,392 +0,0 @@
|
||||
/*
|
||||
* Ingenic JZ47xx GPIO driver
|
||||
*
|
||||
* Copyright (c) 2017 Paul Cercueil <paul@crapouillou.net>
|
||||
*
|
||||
* License terms: GNU General Public License (GPL) version 2
|
||||
*/
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define GPIO_PIN 0x00
|
||||
#define GPIO_MSK 0x20
|
||||
|
||||
#define JZ4740_GPIO_DATA 0x10
|
||||
#define JZ4740_GPIO_SELECT 0x50
|
||||
#define JZ4740_GPIO_DIR 0x60
|
||||
#define JZ4740_GPIO_TRIG 0x70
|
||||
#define JZ4740_GPIO_FLAG 0x80
|
||||
|
||||
#define JZ4770_GPIO_INT 0x10
|
||||
#define JZ4770_GPIO_PAT1 0x30
|
||||
#define JZ4770_GPIO_PAT0 0x40
|
||||
#define JZ4770_GPIO_FLAG 0x50
|
||||
|
||||
#define REG_SET(x) ((x) + 0x4)
|
||||
#define REG_CLEAR(x) ((x) + 0x8)
|
||||
|
||||
enum jz_version {
|
||||
ID_JZ4740,
|
||||
ID_JZ4770,
|
||||
ID_JZ4780,
|
||||
};
|
||||
|
||||
struct ingenic_gpio_chip {
|
||||
struct regmap *map;
|
||||
struct gpio_chip gc;
|
||||
struct irq_chip irq_chip;
|
||||
unsigned int irq, reg_base;
|
||||
enum jz_version version;
|
||||
};
|
||||
|
||||
static u32 gpio_ingenic_read_reg(struct ingenic_gpio_chip *jzgc, u8 reg)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
regmap_read(jzgc->map, jzgc->reg_base + reg, &val);
|
||||
|
||||
return (u32) val;
|
||||
}
|
||||
|
||||
static void gpio_ingenic_set_bit(struct ingenic_gpio_chip *jzgc,
|
||||
u8 reg, u8 offset, bool set)
|
||||
{
|
||||
if (set)
|
||||
reg = REG_SET(reg);
|
||||
else
|
||||
reg = REG_CLEAR(reg);
|
||||
|
||||
regmap_write(jzgc->map, jzgc->reg_base + reg, BIT(offset));
|
||||
}
|
||||
|
||||
static inline bool gpio_get_value(struct ingenic_gpio_chip *jzgc, u8 offset)
|
||||
{
|
||||
unsigned int val = gpio_ingenic_read_reg(jzgc, GPIO_PIN);
|
||||
|
||||
return !!(val & BIT(offset));
|
||||
}
|
||||
|
||||
static void gpio_set_value(struct ingenic_gpio_chip *jzgc, u8 offset, int value)
|
||||
{
|
||||
if (jzgc->version >= ID_JZ4770)
|
||||
gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_PAT0, offset, !!value);
|
||||
else
|
||||
gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_DATA, offset, !!value);
|
||||
}
|
||||
|
||||
static void irq_set_type(struct ingenic_gpio_chip *jzgc,
|
||||
u8 offset, unsigned int type)
|
||||
{
|
||||
u8 reg1, reg2;
|
||||
|
||||
if (jzgc->version >= ID_JZ4770) {
|
||||
reg1 = JZ4770_GPIO_PAT1;
|
||||
reg2 = JZ4770_GPIO_PAT0;
|
||||
} else {
|
||||
reg1 = JZ4740_GPIO_TRIG;
|
||||
reg2 = JZ4740_GPIO_DIR;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
gpio_ingenic_set_bit(jzgc, reg2, offset, true);
|
||||
gpio_ingenic_set_bit(jzgc, reg1, offset, true);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
gpio_ingenic_set_bit(jzgc, reg2, offset, false);
|
||||
gpio_ingenic_set_bit(jzgc, reg1, offset, true);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
gpio_ingenic_set_bit(jzgc, reg2, offset, true);
|
||||
gpio_ingenic_set_bit(jzgc, reg1, offset, false);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
default:
|
||||
gpio_ingenic_set_bit(jzgc, reg2, offset, false);
|
||||
gpio_ingenic_set_bit(jzgc, reg1, offset, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ingenic_gpio_irq_mask(struct irq_data *irqd)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
|
||||
gpio_ingenic_set_bit(jzgc, GPIO_MSK, irqd->hwirq, true);
|
||||
}
|
||||
|
||||
static void ingenic_gpio_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
|
||||
gpio_ingenic_set_bit(jzgc, GPIO_MSK, irqd->hwirq, false);
|
||||
}
|
||||
|
||||
static void ingenic_gpio_irq_enable(struct irq_data *irqd)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
int irq = irqd->hwirq;
|
||||
|
||||
if (jzgc->version >= ID_JZ4770)
|
||||
gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_INT, irq, true);
|
||||
else
|
||||
gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, true);
|
||||
|
||||
ingenic_gpio_irq_unmask(irqd);
|
||||
}
|
||||
|
||||
static void ingenic_gpio_irq_disable(struct irq_data *irqd)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
int irq = irqd->hwirq;
|
||||
|
||||
ingenic_gpio_irq_mask(irqd);
|
||||
|
||||
if (jzgc->version >= ID_JZ4770)
|
||||
gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_INT, irq, false);
|
||||
else
|
||||
gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, false);
|
||||
}
|
||||
|
||||
static void ingenic_gpio_irq_ack(struct irq_data *irqd)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
int irq = irqd->hwirq;
|
||||
bool high;
|
||||
|
||||
if (irqd_get_trigger_type(irqd) == IRQ_TYPE_EDGE_BOTH) {
|
||||
/*
|
||||
* Switch to an interrupt for the opposite edge to the one that
|
||||
* triggered the interrupt being ACKed.
|
||||
*/
|
||||
high = gpio_get_value(jzgc, irq);
|
||||
if (high)
|
||||
irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_FALLING);
|
||||
else
|
||||
irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_RISING);
|
||||
}
|
||||
|
||||
if (jzgc->version >= ID_JZ4770)
|
||||
gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_FLAG, irq, false);
|
||||
else
|
||||
gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_DATA, irq, true);
|
||||
}
|
||||
|
||||
static int ingenic_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
irq_set_handler_locked(irqd, handle_edge_irq);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
irq_set_handler_locked(irqd, handle_level_irq);
|
||||
break;
|
||||
default:
|
||||
irq_set_handler_locked(irqd, handle_bad_irq);
|
||||
}
|
||||
|
||||
if (type == IRQ_TYPE_EDGE_BOTH) {
|
||||
/*
|
||||
* The hardware does not support interrupts on both edges. The
|
||||
* best we can do is to set up a single-edge interrupt and then
|
||||
* switch to the opposing edge when ACKing the interrupt.
|
||||
*/
|
||||
bool high = gpio_get_value(jzgc, irqd->hwirq);
|
||||
|
||||
type = high ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
|
||||
}
|
||||
|
||||
irq_set_type(jzgc, irqd->hwirq, type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ingenic_gpio_irq_set_wake(struct irq_data *irqd, unsigned int on)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
|
||||
return irq_set_irq_wake(jzgc->irq, on);
|
||||
}
|
||||
|
||||
static void ingenic_gpio_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
struct irq_chip *irq_chip = irq_data_get_irq_chip(&desc->irq_data);
|
||||
unsigned long flag, i;
|
||||
|
||||
chained_irq_enter(irq_chip, desc);
|
||||
|
||||
if (jzgc->version >= ID_JZ4770)
|
||||
flag = gpio_ingenic_read_reg(jzgc, JZ4770_GPIO_FLAG);
|
||||
else
|
||||
flag = gpio_ingenic_read_reg(jzgc, JZ4740_GPIO_FLAG);
|
||||
|
||||
for_each_set_bit(i, &flag, 32)
|
||||
generic_handle_irq(irq_linear_revmap(gc->irq.domain, i));
|
||||
chained_irq_exit(irq_chip, desc);
|
||||
}
|
||||
|
||||
static void ingenic_gpio_set(struct gpio_chip *gc,
|
||||
unsigned int offset, int value)
|
||||
{
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
|
||||
gpio_set_value(jzgc, offset, value);
|
||||
}
|
||||
|
||||
static int ingenic_gpio_get(struct gpio_chip *gc, unsigned int offset)
|
||||
{
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
|
||||
return (int) gpio_get_value(jzgc, offset);
|
||||
}
|
||||
|
||||
static int ingenic_gpio_direction_input(struct gpio_chip *gc,
|
||||
unsigned int offset)
|
||||
{
|
||||
return pinctrl_gpio_direction_input(gc->base + offset);
|
||||
}
|
||||
|
||||
static int ingenic_gpio_direction_output(struct gpio_chip *gc,
|
||||
unsigned int offset, int value)
|
||||
{
|
||||
ingenic_gpio_set(gc, offset, value);
|
||||
return pinctrl_gpio_direction_output(gc->base + offset);
|
||||
}
|
||||
|
||||
static const struct of_device_id ingenic_gpio_of_match[] = {
|
||||
{ .compatible = "ingenic,jz4740-gpio", .data = (void *)ID_JZ4740 },
|
||||
{ .compatible = "ingenic,jz4770-gpio", .data = (void *)ID_JZ4770 },
|
||||
{ .compatible = "ingenic,jz4780-gpio", .data = (void *)ID_JZ4780 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ingenic_gpio_of_match);
|
||||
|
||||
static int ingenic_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ingenic_gpio_chip *jzgc;
|
||||
u32 bank;
|
||||
int err;
|
||||
|
||||
jzgc = devm_kzalloc(dev, sizeof(*jzgc), GFP_KERNEL);
|
||||
if (!jzgc)
|
||||
return -ENOMEM;
|
||||
|
||||
jzgc->map = dev_get_drvdata(dev->parent);
|
||||
if (!jzgc->map) {
|
||||
dev_err(dev, "Cannot get parent regmap\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
err = of_property_read_u32(dev->of_node, "reg", &bank);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot read \"reg\" property: %i\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
jzgc->reg_base = bank * 0x100;
|
||||
|
||||
jzgc->gc.label = devm_kasprintf(dev, GFP_KERNEL, "GPIO%c", 'A' + bank);
|
||||
if (!jzgc->gc.label)
|
||||
return -ENOMEM;
|
||||
|
||||
/* DO NOT EXPAND THIS: FOR BACKWARD GPIO NUMBERSPACE COMPATIBIBILITY
|
||||
* ONLY: WORK TO TRANSITION CONSUMERS TO USE THE GPIO DESCRIPTOR API IN
|
||||
* <linux/gpio/consumer.h> INSTEAD.
|
||||
*/
|
||||
jzgc->gc.base = bank * 32;
|
||||
|
||||
jzgc->gc.ngpio = 32;
|
||||
jzgc->gc.parent = dev;
|
||||
jzgc->gc.of_node = dev->of_node;
|
||||
jzgc->gc.owner = THIS_MODULE;
|
||||
jzgc->version = (enum jz_version)of_device_get_match_data(dev);
|
||||
|
||||
jzgc->gc.set = ingenic_gpio_set;
|
||||
jzgc->gc.get = ingenic_gpio_get;
|
||||
jzgc->gc.direction_input = ingenic_gpio_direction_input;
|
||||
jzgc->gc.direction_output = ingenic_gpio_direction_output;
|
||||
|
||||
if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
|
||||
jzgc->gc.request = gpiochip_generic_request;
|
||||
jzgc->gc.free = gpiochip_generic_free;
|
||||
}
|
||||
|
||||
err = devm_gpiochip_add_data(dev, &jzgc->gc, jzgc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
jzgc->irq = irq_of_parse_and_map(dev->of_node, 0);
|
||||
if (!jzgc->irq)
|
||||
return -EINVAL;
|
||||
|
||||
jzgc->irq_chip.name = jzgc->gc.label;
|
||||
jzgc->irq_chip.irq_enable = ingenic_gpio_irq_enable;
|
||||
jzgc->irq_chip.irq_disable = ingenic_gpio_irq_disable;
|
||||
jzgc->irq_chip.irq_unmask = ingenic_gpio_irq_unmask;
|
||||
jzgc->irq_chip.irq_mask = ingenic_gpio_irq_mask;
|
||||
jzgc->irq_chip.irq_ack = ingenic_gpio_irq_ack;
|
||||
jzgc->irq_chip.irq_set_type = ingenic_gpio_irq_set_type;
|
||||
jzgc->irq_chip.irq_set_wake = ingenic_gpio_irq_set_wake;
|
||||
jzgc->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND;
|
||||
|
||||
err = gpiochip_irqchip_add(&jzgc->gc, &jzgc->irq_chip, 0,
|
||||
handle_level_irq, IRQ_TYPE_NONE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
gpiochip_set_chained_irqchip(&jzgc->gc, &jzgc->irq_chip,
|
||||
jzgc->irq, ingenic_gpio_irq_handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ingenic_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ingenic_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "gpio-ingenic",
|
||||
.of_match_table = of_match_ptr(ingenic_gpio_of_match),
|
||||
},
|
||||
.probe = ingenic_gpio_probe,
|
||||
.remove = ingenic_gpio_remove,
|
||||
};
|
||||
|
||||
static int __init ingenic_gpio_drv_register(void)
|
||||
{
|
||||
return platform_driver_register(&ingenic_gpio_driver);
|
||||
}
|
||||
subsys_initcall(ingenic_gpio_drv_register);
|
||||
|
||||
static void __exit ingenic_gpio_drv_unregister(void)
|
||||
{
|
||||
platform_driver_unregister(&ingenic_gpio_driver);
|
||||
}
|
||||
module_exit(ingenic_gpio_drv_unregister);
|
||||
|
||||
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
|
||||
MODULE_DESCRIPTION("Ingenic JZ47xx GPIO driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -12,7 +12,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
@ -195,6 +195,16 @@ config PINCTRL_RZA1
|
||||
help
|
||||
This selects pinctrl driver for Renesas RZ/A1 platforms.
|
||||
|
||||
config PINCTRL_RZN1
|
||||
bool "Renesas RZ/N1 pinctrl driver"
|
||||
depends on OF
|
||||
depends on ARCH_RZN1 || COMPILE_TEST
|
||||
select GENERIC_PINCTRL_GROUPS
|
||||
select GENERIC_PINMUX_FUNCTIONS
|
||||
select GENERIC_PINCONF
|
||||
help
|
||||
This selects pinctrl driver for Renesas RZ/N1 devices.
|
||||
|
||||
config PINCTRL_SINGLE
|
||||
tristate "One-register-per-pin type device tree based pinctrl driver"
|
||||
depends on OF
|
||||
@ -309,12 +319,14 @@ config PINCTRL_ZYNQ
|
||||
|
||||
config PINCTRL_INGENIC
|
||||
bool "Pinctrl driver for the Ingenic JZ47xx SoCs"
|
||||
default y
|
||||
default MACH_INGENIC
|
||||
depends on OF
|
||||
depends on MACH_INGENIC || COMPILE_TEST
|
||||
depends on MIPS || COMPILE_TEST
|
||||
select GENERIC_PINCONF
|
||||
select GENERIC_PINCTRL_GROUPS
|
||||
select GENERIC_PINMUX_FUNCTIONS
|
||||
select GPIOLIB
|
||||
select GPIOLIB_IRQCHIP
|
||||
select REGMAP_MMIO
|
||||
|
||||
config PINCTRL_RK805
|
||||
@ -346,6 +358,7 @@ source "drivers/pinctrl/freescale/Kconfig"
|
||||
source "drivers/pinctrl/intel/Kconfig"
|
||||
source "drivers/pinctrl/mvebu/Kconfig"
|
||||
source "drivers/pinctrl/nomadik/Kconfig"
|
||||
source "drivers/pinctrl/nuvoton/Kconfig"
|
||||
source "drivers/pinctrl/pxa/Kconfig"
|
||||
source "drivers/pinctrl/qcom/Kconfig"
|
||||
source "drivers/pinctrl/samsung/Kconfig"
|
||||
|
@ -27,6 +27,7 @@ obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o
|
||||
obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
|
||||
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
|
||||
obj-$(CONFIG_PINCTRL_RZA1) += pinctrl-rza1.o
|
||||
obj-$(CONFIG_PINCTRL_RZN1) += pinctrl-rzn1.o
|
||||
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
|
||||
obj-$(CONFIG_PINCTRL_SIRF) += sirf/
|
||||
obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o
|
||||
@ -51,6 +52,7 @@ obj-y += freescale/
|
||||
obj-$(CONFIG_X86) += intel/
|
||||
obj-y += mvebu/
|
||||
obj-y += nomadik/
|
||||
obj-$(CONFIG_ARCH_NPCM7XX) += nuvoton/
|
||||
obj-$(CONFIG_PINCTRL_PXA) += pxa/
|
||||
obj-$(CONFIG_ARCH_QCOM) += qcom/
|
||||
obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/
|
||||
|
@ -715,7 +715,7 @@ int aspeed_pin_config_set(struct pinctrl_dev *pctldev, unsigned int offset,
|
||||
|
||||
pmap = find_pinconf_map(param, MAP_TYPE_ARG, arg);
|
||||
|
||||
if (unlikely(WARN_ON(!pmap)))
|
||||
if (WARN_ON(!pmap))
|
||||
return -EINVAL;
|
||||
|
||||
val = pmap->val << pconf->bit;
|
||||
|
@ -73,6 +73,19 @@ config PINCTRL_CYGNUS_MUX
|
||||
configuration, with the exception that certain individual pins
|
||||
can be overridden to GPIO function
|
||||
|
||||
config PINCTRL_NS
|
||||
bool "Broadcom Northstar pins driver"
|
||||
depends on OF && (ARCH_BCM_5301X || COMPILE_TEST)
|
||||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
default ARCH_BCM_5301X
|
||||
help
|
||||
Say yes here to enable the Broadcom NS SoC pins driver.
|
||||
|
||||
The Broadcom Northstar pins driver supports muxing multi-purpose pins
|
||||
that can be used for various functions (e.g. SPI, I2C, UART) as well
|
||||
as GPIOs.
|
||||
|
||||
config PINCTRL_NSP_GPIO
|
||||
bool "Broadcom NSP GPIO (with PINCONF) driver"
|
||||
depends on OF_GPIO && (ARCH_BCM_NSP || COMPILE_TEST)
|
||||
|
@ -5,6 +5,7 @@ obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o
|
||||
obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
|
||||
obj-$(CONFIG_PINCTRL_IPROC_GPIO) += pinctrl-iproc-gpio.o
|
||||
obj-$(CONFIG_PINCTRL_CYGNUS_MUX) += pinctrl-cygnus-mux.o
|
||||
obj-$(CONFIG_PINCTRL_NS) += pinctrl-ns.o
|
||||
obj-$(CONFIG_PINCTRL_NSP_GPIO) += pinctrl-nsp-gpio.o
|
||||
obj-$(CONFIG_PINCTRL_NS2_MUX) += pinctrl-ns2-mux.o
|
||||
obj-$(CONFIG_PINCTRL_NSP_MUX) += pinctrl-nsp-mux.o
|
||||
|
372
drivers/pinctrl/bcm/pinctrl-ns.c
Normal file
372
drivers/pinctrl/bcm/pinctrl-ns.c
Normal file
@ -0,0 +1,372 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2018 Rafał Miłecki <rafal@milecki.pl>
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define FLAG_BCM4708 BIT(1)
|
||||
#define FLAG_BCM4709 BIT(2)
|
||||
#define FLAG_BCM53012 BIT(3)
|
||||
|
||||
struct ns_pinctrl {
|
||||
struct device *dev;
|
||||
unsigned int chipset_flag;
|
||||
struct pinctrl_dev *pctldev;
|
||||
void __iomem *base;
|
||||
|
||||
struct pinctrl_desc pctldesc;
|
||||
struct ns_pinctrl_group *groups;
|
||||
unsigned int num_groups;
|
||||
struct ns_pinctrl_function *functions;
|
||||
unsigned int num_functions;
|
||||
};
|
||||
|
||||
/*
|
||||
* Pins
|
||||
*/
|
||||
|
||||
static const struct pinctrl_pin_desc ns_pinctrl_pins[] = {
|
||||
{ 0, "spi_clk", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 1, "spi_ss", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 2, "spi_mosi", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 3, "spi_miso", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 4, "i2c_scl", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 5, "i2c_sda", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 6, "mdc", (void *)(FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 7, "mdio", (void *)(FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 8, "pwm0", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 9, "pwm1", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 10, "pwm2", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 11, "pwm3", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 12, "uart1_rx", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 13, "uart1_tx", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 14, "uart1_cts", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 15, "uart1_rts", (void *)(FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 16, "uart2_rx", (void *)(FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 17, "uart2_tx", (void *)(FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
/* TODO { ??, "xtal_out", (void *)(FLAG_BCM4709) }, */
|
||||
{ 22, "sdio_pwr", (void *)(FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
{ 23, "sdio_en_1p8v", (void *)(FLAG_BCM4709 | FLAG_BCM53012) },
|
||||
};
|
||||
|
||||
/*
|
||||
* Groups
|
||||
*/
|
||||
|
||||
struct ns_pinctrl_group {
|
||||
const char *name;
|
||||
const unsigned int *pins;
|
||||
const unsigned int num_pins;
|
||||
unsigned int chipsets;
|
||||
};
|
||||
|
||||
static const unsigned int spi_pins[] = { 0, 1, 2, 3 };
|
||||
static const unsigned int i2c_pins[] = { 4, 5 };
|
||||
static const unsigned int mdio_pins[] = { 6, 7 };
|
||||
static const unsigned int pwm0_pins[] = { 8 };
|
||||
static const unsigned int pwm1_pins[] = { 9 };
|
||||
static const unsigned int pwm2_pins[] = { 10 };
|
||||
static const unsigned int pwm3_pins[] = { 11 };
|
||||
static const unsigned int uart1_pins[] = { 12, 13, 14, 15 };
|
||||
static const unsigned int uart2_pins[] = { 16, 17 };
|
||||
static const unsigned int sdio_pwr_pins[] = { 22 };
|
||||
static const unsigned int sdio_1p8v_pins[] = { 23 };
|
||||
|
||||
#define NS_GROUP(_name, _pins, _chipsets) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.pins = _pins, \
|
||||
.num_pins = ARRAY_SIZE(_pins), \
|
||||
.chipsets = _chipsets, \
|
||||
}
|
||||
|
||||
static const struct ns_pinctrl_group ns_pinctrl_groups[] = {
|
||||
NS_GROUP("spi_grp", spi_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_GROUP("i2c_grp", i2c_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_GROUP("mdio_grp", mdio_pins, FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_GROUP("pwm0_grp", pwm0_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_GROUP("pwm1_grp", pwm1_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_GROUP("pwm2_grp", pwm2_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_GROUP("pwm3_grp", pwm3_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_GROUP("uart1_grp", uart1_pins, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_GROUP("uart2_grp", uart2_pins, FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_GROUP("sdio_pwr_grp", sdio_pwr_pins, FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_GROUP("sdio_1p8v_grp", sdio_1p8v_pins, FLAG_BCM4709 | FLAG_BCM53012),
|
||||
};
|
||||
|
||||
/*
|
||||
* Functions
|
||||
*/
|
||||
|
||||
struct ns_pinctrl_function {
|
||||
const char *name;
|
||||
const char * const *groups;
|
||||
const unsigned int num_groups;
|
||||
unsigned int chipsets;
|
||||
};
|
||||
|
||||
static const char * const spi_groups[] = { "spi_grp" };
|
||||
static const char * const i2c_groups[] = { "i2c_grp" };
|
||||
static const char * const mdio_groups[] = { "mdio_grp" };
|
||||
static const char * const pwm_groups[] = { "pwm0_grp", "pwm1_grp", "pwm2_grp",
|
||||
"pwm3_grp" };
|
||||
static const char * const uart1_groups[] = { "uart1_grp" };
|
||||
static const char * const uart2_groups[] = { "uart2_grp" };
|
||||
static const char * const sdio_groups[] = { "sdio_pwr_grp", "sdio_1p8v_grp" };
|
||||
|
||||
#define NS_FUNCTION(_name, _groups, _chipsets) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.groups = _groups, \
|
||||
.num_groups = ARRAY_SIZE(_groups), \
|
||||
.chipsets = _chipsets, \
|
||||
}
|
||||
|
||||
static const struct ns_pinctrl_function ns_pinctrl_functions[] = {
|
||||
NS_FUNCTION("spi", spi_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_FUNCTION("i2c", i2c_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_FUNCTION("mdio", mdio_groups, FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_FUNCTION("pwm", pwm_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_FUNCTION("uart1", uart1_groups, FLAG_BCM4708 | FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_FUNCTION("uart2", uart2_groups, FLAG_BCM4709 | FLAG_BCM53012),
|
||||
NS_FUNCTION("sdio", sdio_groups, FLAG_BCM4709 | FLAG_BCM53012),
|
||||
};
|
||||
|
||||
/*
|
||||
* Groups code
|
||||
*/
|
||||
|
||||
static int ns_pinctrl_get_groups_count(struct pinctrl_dev *pctrl_dev)
|
||||
{
|
||||
struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
|
||||
|
||||
return ns_pinctrl->num_groups;
|
||||
}
|
||||
|
||||
static const char *ns_pinctrl_get_group_name(struct pinctrl_dev *pctrl_dev,
|
||||
unsigned int selector)
|
||||
{
|
||||
struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
|
||||
|
||||
return ns_pinctrl->groups[selector].name;
|
||||
}
|
||||
|
||||
static int ns_pinctrl_get_group_pins(struct pinctrl_dev *pctrl_dev,
|
||||
unsigned int selector,
|
||||
const unsigned int **pins,
|
||||
unsigned int *num_pins)
|
||||
{
|
||||
struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
|
||||
|
||||
*pins = ns_pinctrl->groups[selector].pins;
|
||||
*num_pins = ns_pinctrl->groups[selector].num_pins;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops ns_pinctrl_ops = {
|
||||
.get_groups_count = ns_pinctrl_get_groups_count,
|
||||
.get_group_name = ns_pinctrl_get_group_name,
|
||||
.get_group_pins = ns_pinctrl_get_group_pins,
|
||||
.dt_node_to_map = pinconf_generic_dt_node_to_map_group,
|
||||
.dt_free_map = pinconf_generic_dt_free_map,
|
||||
};
|
||||
|
||||
/*
|
||||
* Functions code
|
||||
*/
|
||||
|
||||
static int ns_pinctrl_get_functions_count(struct pinctrl_dev *pctrl_dev)
|
||||
{
|
||||
struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
|
||||
|
||||
return ns_pinctrl->num_functions;
|
||||
}
|
||||
|
||||
static const char *ns_pinctrl_get_function_name(struct pinctrl_dev *pctrl_dev,
|
||||
unsigned int selector)
|
||||
{
|
||||
struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
|
||||
|
||||
return ns_pinctrl->functions[selector].name;
|
||||
}
|
||||
|
||||
static int ns_pinctrl_get_function_groups(struct pinctrl_dev *pctrl_dev,
|
||||
unsigned int selector,
|
||||
const char * const **groups,
|
||||
unsigned * const num_groups)
|
||||
{
|
||||
struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
|
||||
|
||||
*groups = ns_pinctrl->functions[selector].groups;
|
||||
*num_groups = ns_pinctrl->functions[selector].num_groups;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ns_pinctrl_set_mux(struct pinctrl_dev *pctrl_dev,
|
||||
unsigned int func_select,
|
||||
unsigned int grp_select)
|
||||
{
|
||||
struct ns_pinctrl *ns_pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
|
||||
u32 unset = 0;
|
||||
u32 tmp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ns_pinctrl->groups[grp_select].num_pins; i++) {
|
||||
int pin_number = ns_pinctrl->groups[grp_select].pins[i];
|
||||
|
||||
unset |= BIT(pin_number);
|
||||
}
|
||||
|
||||
tmp = readl(ns_pinctrl->base);
|
||||
tmp &= ~unset;
|
||||
writel(tmp, ns_pinctrl->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinmux_ops ns_pinctrl_pmxops = {
|
||||
.get_functions_count = ns_pinctrl_get_functions_count,
|
||||
.get_function_name = ns_pinctrl_get_function_name,
|
||||
.get_function_groups = ns_pinctrl_get_function_groups,
|
||||
.set_mux = ns_pinctrl_set_mux,
|
||||
};
|
||||
|
||||
/*
|
||||
* Controller code
|
||||
*/
|
||||
|
||||
static struct pinctrl_desc ns_pinctrl_desc = {
|
||||
.name = "pinctrl-ns",
|
||||
.pctlops = &ns_pinctrl_ops,
|
||||
.pmxops = &ns_pinctrl_pmxops,
|
||||
};
|
||||
|
||||
static const struct of_device_id ns_pinctrl_of_match_table[] = {
|
||||
{ .compatible = "brcm,bcm4708-pinmux", .data = (void *)FLAG_BCM4708, },
|
||||
{ .compatible = "brcm,bcm4709-pinmux", .data = (void *)FLAG_BCM4709, },
|
||||
{ .compatible = "brcm,bcm53012-pinmux", .data = (void *)FLAG_BCM53012, },
|
||||
{ }
|
||||
};
|
||||
|
||||
static int ns_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct of_device_id *of_id;
|
||||
struct ns_pinctrl *ns_pinctrl;
|
||||
struct pinctrl_desc *pctldesc;
|
||||
struct pinctrl_pin_desc *pin;
|
||||
struct ns_pinctrl_group *group;
|
||||
struct ns_pinctrl_function *function;
|
||||
struct resource *res;
|
||||
int i;
|
||||
|
||||
ns_pinctrl = devm_kzalloc(dev, sizeof(*ns_pinctrl), GFP_KERNEL);
|
||||
if (!ns_pinctrl)
|
||||
return -ENOMEM;
|
||||
pctldesc = &ns_pinctrl->pctldesc;
|
||||
platform_set_drvdata(pdev, ns_pinctrl);
|
||||
|
||||
/* Set basic properties */
|
||||
|
||||
ns_pinctrl->dev = dev;
|
||||
|
||||
of_id = of_match_device(ns_pinctrl_of_match_table, dev);
|
||||
if (!of_id)
|
||||
return -EINVAL;
|
||||
ns_pinctrl->chipset_flag = (uintptr_t)of_id->data;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
"cru_gpio_control");
|
||||
ns_pinctrl->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(ns_pinctrl->base)) {
|
||||
dev_err(dev, "Failed to map pinctrl regs\n");
|
||||
return PTR_ERR(ns_pinctrl->base);
|
||||
}
|
||||
|
||||
memcpy(pctldesc, &ns_pinctrl_desc, sizeof(*pctldesc));
|
||||
|
||||
/* Set pinctrl properties */
|
||||
|
||||
pctldesc->pins = devm_kcalloc(dev, ARRAY_SIZE(ns_pinctrl_pins),
|
||||
sizeof(struct pinctrl_pin_desc),
|
||||
GFP_KERNEL);
|
||||
if (!pctldesc->pins)
|
||||
return -ENOMEM;
|
||||
for (i = 0, pin = (struct pinctrl_pin_desc *)&pctldesc->pins[0];
|
||||
i < ARRAY_SIZE(ns_pinctrl_pins); i++) {
|
||||
const struct pinctrl_pin_desc *src = &ns_pinctrl_pins[i];
|
||||
unsigned int chipsets = (uintptr_t)src->drv_data;
|
||||
|
||||
if (chipsets & ns_pinctrl->chipset_flag) {
|
||||
memcpy(pin++, src, sizeof(*src));
|
||||
pctldesc->npins++;
|
||||
}
|
||||
}
|
||||
|
||||
ns_pinctrl->groups = devm_kcalloc(dev, ARRAY_SIZE(ns_pinctrl_groups),
|
||||
sizeof(struct ns_pinctrl_group),
|
||||
GFP_KERNEL);
|
||||
if (!ns_pinctrl->groups)
|
||||
return -ENOMEM;
|
||||
for (i = 0, group = &ns_pinctrl->groups[0];
|
||||
i < ARRAY_SIZE(ns_pinctrl_groups); i++) {
|
||||
const struct ns_pinctrl_group *src = &ns_pinctrl_groups[i];
|
||||
|
||||
if (src->chipsets & ns_pinctrl->chipset_flag) {
|
||||
memcpy(group++, src, sizeof(*src));
|
||||
ns_pinctrl->num_groups++;
|
||||
}
|
||||
}
|
||||
|
||||
ns_pinctrl->functions = devm_kcalloc(dev,
|
||||
ARRAY_SIZE(ns_pinctrl_functions),
|
||||
sizeof(struct ns_pinctrl_function),
|
||||
GFP_KERNEL);
|
||||
if (!ns_pinctrl->functions)
|
||||
return -ENOMEM;
|
||||
for (i = 0, function = &ns_pinctrl->functions[0];
|
||||
i < ARRAY_SIZE(ns_pinctrl_functions); i++) {
|
||||
const struct ns_pinctrl_function *src = &ns_pinctrl_functions[i];
|
||||
|
||||
if (src->chipsets & ns_pinctrl->chipset_flag) {
|
||||
memcpy(function++, src, sizeof(*src));
|
||||
ns_pinctrl->num_functions++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Register */
|
||||
|
||||
ns_pinctrl->pctldev = devm_pinctrl_register(dev, pctldesc, ns_pinctrl);
|
||||
if (IS_ERR(ns_pinctrl->pctldev)) {
|
||||
dev_err(dev, "Failed to register pinctrl\n");
|
||||
return PTR_ERR(ns_pinctrl->pctldev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ns_pinctrl_driver = {
|
||||
.probe = ns_pinctrl_probe,
|
||||
.driver = {
|
||||
.name = "ns-pinmux",
|
||||
.of_match_table = ns_pinctrl_of_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(ns_pinctrl_driver);
|
||||
|
||||
MODULE_AUTHOR("Rafał Miłecki");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DEVICE_TABLE(of, ns_pinctrl_of_match_table);
|
@ -64,16 +64,14 @@ static int berlin_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrl_dev,
|
||||
ret = of_property_read_string(node, "function", &function_name);
|
||||
if (ret) {
|
||||
dev_err(pctrl->dev,
|
||||
"missing function property in node %s\n",
|
||||
node->name);
|
||||
"missing function property in node %pOFn\n", node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ngroups = of_property_count_strings(node, "groups");
|
||||
if (ngroups < 0) {
|
||||
dev_err(pctrl->dev,
|
||||
"missing groups property in node %s\n",
|
||||
node->name);
|
||||
"missing groups property in node %pOFn\n", node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -550,7 +550,7 @@ static void __maybe_unused madera_pin_dbg_show(struct pinctrl_dev *pctldev,
|
||||
seq_printf(s, " DRV=%umA", madera_pin_unmake_drv_str(priv, conf[1]));
|
||||
|
||||
if (conf[0] & MADERA_GP1_IP_CFG_MASK)
|
||||
seq_puts(s, "SCHMITT");
|
||||
seq_puts(s, " SCHMITT");
|
||||
}
|
||||
|
||||
|
||||
@ -608,7 +608,7 @@ static int madera_mux_set_mux(struct pinctrl_dev *pctldev,
|
||||
unsigned int n_chip_groups = priv->chip->n_pin_groups;
|
||||
const char *func_name = madera_mux_funcs[selector].name;
|
||||
unsigned int reg;
|
||||
int i, ret;
|
||||
int i, ret = 0;
|
||||
|
||||
dev_dbg(priv->dev, "%s selecting %u (%s) for group %u (%s)\n",
|
||||
__func__, selector, func_name, group,
|
||||
@ -801,7 +801,7 @@ static int madera_pin_conf_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
result = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
*config = pinconf_to_config_packed(param, result);
|
||||
@ -905,7 +905,7 @@ static int madera_pin_conf_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
conf[1] &= ~MADERA_GP1_DIR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
++configs;
|
||||
@ -971,10 +971,10 @@ static int madera_pin_conf_group_set(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
static const struct pinconf_ops madera_pin_conf_ops = {
|
||||
.is_generic = true,
|
||||
.pin_config_get = madera_pin_conf_get,
|
||||
.pin_config_set = madera_pin_conf_set,
|
||||
.pin_config_group_set = madera_pin_conf_group_set,
|
||||
|
||||
};
|
||||
|
||||
static struct pinctrl_desc madera_pin_desc = {
|
||||
|
@ -627,7 +627,7 @@ static int pinctrl_generic_group_name_to_selector(struct pinctrl_dev *pctldev,
|
||||
while (selector < ngroups) {
|
||||
const char *gname = ops->get_group_name(pctldev, selector);
|
||||
|
||||
if (!strcmp(function, gname))
|
||||
if (gname && !strcmp(function, gname))
|
||||
return selector;
|
||||
|
||||
selector++;
|
||||
@ -743,7 +743,7 @@ int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
|
||||
while (group_selector < ngroups) {
|
||||
const char *gname = pctlops->get_group_name(pctldev,
|
||||
group_selector);
|
||||
if (!strcmp(gname, pin_group)) {
|
||||
if (gname && !strcmp(gname, pin_group)) {
|
||||
dev_dbg(pctldev->dev,
|
||||
"found group selector %u for %s\n",
|
||||
group_selector,
|
||||
|
@ -69,8 +69,7 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
*/
|
||||
grp = imx_pinctrl_find_group_by_name(pctldev, np->name);
|
||||
if (!grp) {
|
||||
dev_err(ipctl->dev, "unable to find group for node %s\n",
|
||||
np->name);
|
||||
dev_err(ipctl->dev, "unable to find group for node %pOFn\n", np);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -434,7 +433,7 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
|
||||
int i;
|
||||
u32 config;
|
||||
|
||||
dev_dbg(ipctl->dev, "group(%d): %s\n", index, np->name);
|
||||
dev_dbg(ipctl->dev, "group(%d): %pOFn\n", index, np);
|
||||
|
||||
if (info->flags & SHARE_MUX_CONF_REG)
|
||||
pin_size = FSL_PIN_SHARE_SIZE;
|
||||
@ -544,7 +543,7 @@ static int imx_pinctrl_parse_functions(struct device_node *np,
|
||||
struct group_desc *grp;
|
||||
u32 i = 0;
|
||||
|
||||
dev_dbg(pctl->dev, "parse function(%d): %s\n", index, np->name);
|
||||
dev_dbg(pctl->dev, "parse function(%d): %pOFn\n", index, np);
|
||||
|
||||
func = pinmux_generic_get_function(pctl, index);
|
||||
if (!func)
|
||||
|
@ -233,8 +233,8 @@ static int imx1_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
*/
|
||||
grp = imx1_pinctrl_find_group_by_name(info, np->name);
|
||||
if (!grp) {
|
||||
dev_err(info->dev, "unable to find group for node %s\n",
|
||||
np->name);
|
||||
dev_err(info->dev, "unable to find group for node %pOFn\n",
|
||||
np);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -466,7 +466,7 @@ static int imx1_pinctrl_parse_groups(struct device_node *np,
|
||||
const __be32 *list;
|
||||
int i;
|
||||
|
||||
dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
|
||||
dev_dbg(info->dev, "group(%d): %pOFn\n", index, np);
|
||||
|
||||
/* Initialise group */
|
||||
grp->name = np->name;
|
||||
@ -477,8 +477,8 @@ static int imx1_pinctrl_parse_groups(struct device_node *np,
|
||||
list = of_get_property(np, "fsl,pins", &size);
|
||||
/* we do not check return since it's safe node passed down */
|
||||
if (!size || size % 12) {
|
||||
dev_notice(info->dev, "Not a valid fsl,pins property (%s)\n",
|
||||
np->name);
|
||||
dev_notice(info->dev, "Not a valid fsl,pins property (%pOFn)\n",
|
||||
np);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -513,7 +513,7 @@ static int imx1_pinctrl_parse_functions(struct device_node *np,
|
||||
static u32 grp_index;
|
||||
u32 i = 0;
|
||||
|
||||
dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
|
||||
dev_dbg(info->dev, "parse function(%d): %pOFn\n", index, np);
|
||||
|
||||
func = &info->functions[index];
|
||||
|
||||
|
@ -556,4 +556,3 @@ err:
|
||||
iounmap(d->base);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mxs_pinctrl_probe);
|
||||
|
@ -6,18 +6,19 @@
|
||||
* Author: Mathias Nyman <mathias.nyman@linux.intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
@ -682,7 +683,7 @@ static const struct pinctrl_pin_desc byt_ncore_pins[] = {
|
||||
PINCTRL_PIN(27, "GPIO_NCORE27"),
|
||||
};
|
||||
|
||||
static unsigned const byt_ncore_pins_map[BYT_NGPIO_NCORE] = {
|
||||
static const unsigned int byt_ncore_pins_map[BYT_NGPIO_NCORE] = {
|
||||
19, 18, 17, 20, 21, 22, 24, 25, 23, 16,
|
||||
14, 15, 12, 26, 27, 1, 4, 8, 11, 0,
|
||||
3, 6, 10, 13, 2, 5, 9, 7,
|
||||
@ -926,7 +927,7 @@ static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned offset)
|
||||
static u32 byt_get_gpio_mux(struct byt_gpio *vg, unsigned int offset)
|
||||
{
|
||||
/* SCORE pin 92-93 */
|
||||
if (!strcmp(vg->soc_data->uid, BYT_SCORE_ACPI_UID) &&
|
||||
@ -1310,7 +1311,7 @@ static const struct pinctrl_desc byt_pinctrl_desc = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
static int byt_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct byt_gpio *vg = gpiochip_get_data(chip);
|
||||
void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
|
||||
@ -1324,7 +1325,7 @@ static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
return !!(val & BYT_LEVEL);
|
||||
}
|
||||
|
||||
static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
static void byt_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
|
||||
{
|
||||
struct byt_gpio *vg = gpiochip_get_data(chip);
|
||||
void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
|
||||
@ -1358,9 +1359,9 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
|
||||
raw_spin_unlock_irqrestore(&vg->lock, flags);
|
||||
|
||||
if (!(value & BYT_OUTPUT_EN))
|
||||
return GPIOF_DIR_OUT;
|
||||
return 0;
|
||||
if (!(value & BYT_INPUT_EN))
|
||||
return GPIOF_DIR_IN;
|
||||
return 1;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1495,7 +1496,7 @@ static void byt_irq_ack(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct byt_gpio *vg = gpiochip_get_data(gc);
|
||||
unsigned offset = irqd_to_hwirq(d);
|
||||
unsigned int offset = irqd_to_hwirq(d);
|
||||
void __iomem *reg;
|
||||
|
||||
reg = byt_gpio_reg(vg, offset, BYT_INT_STAT_REG);
|
||||
@ -1519,7 +1520,7 @@ static void byt_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct byt_gpio *vg = gpiochip_get_data(gc);
|
||||
unsigned offset = irqd_to_hwirq(d);
|
||||
unsigned int offset = irqd_to_hwirq(d);
|
||||
unsigned long flags;
|
||||
void __iomem *reg;
|
||||
u32 value;
|
||||
@ -1775,13 +1776,11 @@ static const struct acpi_device_id byt_gpio_acpi_match[] = {
|
||||
{ "INT33FC", (kernel_ulong_t)byt_soc_data },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
|
||||
|
||||
static int byt_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct byt_pinctrl_soc_data *soc_data = NULL;
|
||||
const struct byt_pinctrl_soc_data **soc_table;
|
||||
const struct acpi_device_id *acpi_id;
|
||||
struct acpi_device *acpi_dev;
|
||||
struct byt_gpio *vg;
|
||||
int i, ret;
|
||||
@ -1790,11 +1789,7 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
|
||||
if (!acpi_dev)
|
||||
return -ENODEV;
|
||||
|
||||
acpi_id = acpi_match_device(byt_gpio_acpi_match, &pdev->dev);
|
||||
if (!acpi_id)
|
||||
return -ENODEV;
|
||||
|
||||
soc_table = (const struct byt_pinctrl_soc_data **)acpi_id->driver_data;
|
||||
soc_table = (const struct byt_pinctrl_soc_data **)device_get_match_data(&pdev->dev);
|
||||
|
||||
for (i = 0; soc_table[i]; i++) {
|
||||
if (!strcmp(acpi_dev->pnp.unique_id, soc_table[i]->uid)) {
|
||||
|
@ -6,10 +6,10 @@
|
||||
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-intel.h"
|
||||
@ -117,17 +117,17 @@ static const struct pinctrl_pin_desc bxt_north_pins[] = {
|
||||
PINCTRL_PIN(82, "TDO"),
|
||||
};
|
||||
|
||||
static const unsigned bxt_north_pwm0_pins[] = { 34 };
|
||||
static const unsigned bxt_north_pwm1_pins[] = { 35 };
|
||||
static const unsigned bxt_north_pwm2_pins[] = { 36 };
|
||||
static const unsigned bxt_north_pwm3_pins[] = { 37 };
|
||||
static const unsigned bxt_north_uart0_pins[] = { 38, 39, 40, 41 };
|
||||
static const unsigned bxt_north_uart1_pins[] = { 42, 43, 44, 45 };
|
||||
static const unsigned bxt_north_uart2_pins[] = { 46, 47, 48, 49 };
|
||||
static const unsigned bxt_north_uart0b_pins[] = { 50, 51, 52, 53 };
|
||||
static const unsigned bxt_north_uart1b_pins[] = { 54, 55, 56, 57 };
|
||||
static const unsigned bxt_north_uart2b_pins[] = { 58, 59, 60, 61 };
|
||||
static const unsigned bxt_north_uart3_pins[] = { 58, 59, 60, 61 };
|
||||
static const unsigned int bxt_north_pwm0_pins[] = { 34 };
|
||||
static const unsigned int bxt_north_pwm1_pins[] = { 35 };
|
||||
static const unsigned int bxt_north_pwm2_pins[] = { 36 };
|
||||
static const unsigned int bxt_north_pwm3_pins[] = { 37 };
|
||||
static const unsigned int bxt_north_uart0_pins[] = { 38, 39, 40, 41 };
|
||||
static const unsigned int bxt_north_uart1_pins[] = { 42, 43, 44, 45 };
|
||||
static const unsigned int bxt_north_uart2_pins[] = { 46, 47, 48, 49 };
|
||||
static const unsigned int bxt_north_uart0b_pins[] = { 50, 51, 52, 53 };
|
||||
static const unsigned int bxt_north_uart1b_pins[] = { 54, 55, 56, 57 };
|
||||
static const unsigned int bxt_north_uart2b_pins[] = { 58, 59, 60, 61 };
|
||||
static const unsigned int bxt_north_uart3_pins[] = { 58, 59, 60, 61 };
|
||||
|
||||
static const struct intel_pingroup bxt_north_groups[] = {
|
||||
PIN_GROUP("pwm0_grp", bxt_north_pwm0_pins, 1),
|
||||
@ -260,12 +260,12 @@ static const struct pinctrl_pin_desc bxt_northwest_pins[] = {
|
||||
PINCTRL_PIN(71, "GP_SSP_2_TXD"),
|
||||
};
|
||||
|
||||
static const unsigned bxt_northwest_ssp0_pins[] = { 53, 54, 55, 56, 57, 58 };
|
||||
static const unsigned bxt_northwest_ssp1_pins[] = {
|
||||
static const unsigned int bxt_northwest_ssp0_pins[] = { 53, 54, 55, 56, 57, 58 };
|
||||
static const unsigned int bxt_northwest_ssp1_pins[] = {
|
||||
59, 60, 61, 62, 63, 64, 65
|
||||
};
|
||||
static const unsigned bxt_northwest_ssp2_pins[] = { 66, 67, 68, 69, 70, 71 };
|
||||
static const unsigned bxt_northwest_uart3_pins[] = { 67, 68, 69, 70 };
|
||||
static const unsigned int bxt_northwest_ssp2_pins[] = { 66, 67, 68, 69, 70, 71 };
|
||||
static const unsigned int bxt_northwest_uart3_pins[] = { 67, 68, 69, 70 };
|
||||
|
||||
static const struct intel_pingroup bxt_northwest_groups[] = {
|
||||
PIN_GROUP("ssp0_grp", bxt_northwest_ssp0_pins, 1),
|
||||
@ -347,17 +347,17 @@ static const struct pinctrl_pin_desc bxt_west_pins[] = {
|
||||
PINCTRL_PIN(41, "OSC_CLK_OUT_3"),
|
||||
};
|
||||
|
||||
static const unsigned bxt_west_i2c0_pins[] = { 0, 1 };
|
||||
static const unsigned bxt_west_i2c1_pins[] = { 2, 3 };
|
||||
static const unsigned bxt_west_i2c2_pins[] = { 4, 5 };
|
||||
static const unsigned bxt_west_i2c3_pins[] = { 6, 7 };
|
||||
static const unsigned bxt_west_i2c4_pins[] = { 8, 9 };
|
||||
static const unsigned bxt_west_i2c5_pins[] = { 10, 11 };
|
||||
static const unsigned bxt_west_i2c6_pins[] = { 12, 13 };
|
||||
static const unsigned bxt_west_i2c7_pins[] = { 14, 15 };
|
||||
static const unsigned bxt_west_i2c5b_pins[] = { 16, 17 };
|
||||
static const unsigned bxt_west_i2c6b_pins[] = { 18, 19 };
|
||||
static const unsigned bxt_west_i2c7b_pins[] = { 20, 21 };
|
||||
static const unsigned int bxt_west_i2c0_pins[] = { 0, 1 };
|
||||
static const unsigned int bxt_west_i2c1_pins[] = { 2, 3 };
|
||||
static const unsigned int bxt_west_i2c2_pins[] = { 4, 5 };
|
||||
static const unsigned int bxt_west_i2c3_pins[] = { 6, 7 };
|
||||
static const unsigned int bxt_west_i2c4_pins[] = { 8, 9 };
|
||||
static const unsigned int bxt_west_i2c5_pins[] = { 10, 11 };
|
||||
static const unsigned int bxt_west_i2c6_pins[] = { 12, 13 };
|
||||
static const unsigned int bxt_west_i2c7_pins[] = { 14, 15 };
|
||||
static const unsigned int bxt_west_i2c5b_pins[] = { 16, 17 };
|
||||
static const unsigned int bxt_west_i2c6b_pins[] = { 18, 19 };
|
||||
static const unsigned int bxt_west_i2c7b_pins[] = { 20, 21 };
|
||||
|
||||
static const struct intel_pingroup bxt_west_groups[] = {
|
||||
PIN_GROUP("i2c0_grp", bxt_west_i2c0_pins, 1),
|
||||
@ -443,13 +443,13 @@ static const struct pinctrl_pin_desc bxt_southwest_pins[] = {
|
||||
PINCTRL_PIN(30, "SDCARD_LVL_WP"),
|
||||
};
|
||||
|
||||
static const unsigned bxt_southwest_emmc0_pins[] = {
|
||||
static const unsigned int bxt_southwest_emmc0_pins[] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 26,
|
||||
};
|
||||
static const unsigned bxt_southwest_sdio_pins[] = {
|
||||
static const unsigned int bxt_southwest_sdio_pins[] = {
|
||||
10, 11, 12, 13, 14, 15, 27,
|
||||
};
|
||||
static const unsigned bxt_southwest_sdcard_pins[] = {
|
||||
static const unsigned int bxt_southwest_sdcard_pins[] = {
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 28, 29, 30,
|
||||
};
|
||||
|
||||
@ -611,13 +611,13 @@ static const struct pinctrl_pin_desc apl_north_pins[] = {
|
||||
PINCTRL_PIN(77, "SVID0_CLK"),
|
||||
};
|
||||
|
||||
static const unsigned apl_north_pwm0_pins[] = { 34 };
|
||||
static const unsigned apl_north_pwm1_pins[] = { 35 };
|
||||
static const unsigned apl_north_pwm2_pins[] = { 36 };
|
||||
static const unsigned apl_north_pwm3_pins[] = { 37 };
|
||||
static const unsigned apl_north_uart0_pins[] = { 38, 39, 40, 41 };
|
||||
static const unsigned apl_north_uart1_pins[] = { 42, 43, 44, 45 };
|
||||
static const unsigned apl_north_uart2_pins[] = { 46, 47, 48, 49 };
|
||||
static const unsigned int apl_north_pwm0_pins[] = { 34 };
|
||||
static const unsigned int apl_north_pwm1_pins[] = { 35 };
|
||||
static const unsigned int apl_north_pwm2_pins[] = { 36 };
|
||||
static const unsigned int apl_north_pwm3_pins[] = { 37 };
|
||||
static const unsigned int apl_north_uart0_pins[] = { 38, 39, 40, 41 };
|
||||
static const unsigned int apl_north_uart1_pins[] = { 42, 43, 44, 45 };
|
||||
static const unsigned int apl_north_uart2_pins[] = { 46, 47, 48, 49 };
|
||||
|
||||
static const struct intel_pingroup apl_north_groups[] = {
|
||||
PIN_GROUP("pwm0_grp", apl_north_pwm0_pins, 1),
|
||||
@ -743,10 +743,10 @@ static const struct pinctrl_pin_desc apl_northwest_pins[] = {
|
||||
PINCTRL_PIN(76, "GP_SSP_2_TXD"),
|
||||
};
|
||||
|
||||
static const unsigned apl_northwest_ssp0_pins[] = { 61, 62, 63, 64, 65 };
|
||||
static const unsigned apl_northwest_ssp1_pins[] = { 66, 67, 68, 69, 70 };
|
||||
static const unsigned apl_northwest_ssp2_pins[] = { 71, 72, 73, 74, 75, 76 };
|
||||
static const unsigned apl_northwest_uart3_pins[] = { 67, 68, 69, 70 };
|
||||
static const unsigned int apl_northwest_ssp0_pins[] = { 61, 62, 63, 64, 65 };
|
||||
static const unsigned int apl_northwest_ssp1_pins[] = { 66, 67, 68, 69, 70 };
|
||||
static const unsigned int apl_northwest_ssp2_pins[] = { 71, 72, 73, 74, 75, 76 };
|
||||
static const unsigned int apl_northwest_uart3_pins[] = { 67, 68, 69, 70 };
|
||||
|
||||
static const struct intel_pingroup apl_northwest_groups[] = {
|
||||
PIN_GROUP("ssp0_grp", apl_northwest_ssp0_pins, 1),
|
||||
@ -833,15 +833,15 @@ static const struct pinctrl_pin_desc apl_west_pins[] = {
|
||||
PINCTRL_PIN(46, "SUSPWRDNACK"),
|
||||
};
|
||||
|
||||
static const unsigned apl_west_i2c0_pins[] = { 0, 1 };
|
||||
static const unsigned apl_west_i2c1_pins[] = { 2, 3 };
|
||||
static const unsigned apl_west_i2c2_pins[] = { 4, 5 };
|
||||
static const unsigned apl_west_i2c3_pins[] = { 6, 7 };
|
||||
static const unsigned apl_west_i2c4_pins[] = { 8, 9 };
|
||||
static const unsigned apl_west_i2c5_pins[] = { 10, 11 };
|
||||
static const unsigned apl_west_i2c6_pins[] = { 12, 13 };
|
||||
static const unsigned apl_west_i2c7_pins[] = { 14, 15 };
|
||||
static const unsigned apl_west_uart2_pins[] = { 20, 21, 22, 34 };
|
||||
static const unsigned int apl_west_i2c0_pins[] = { 0, 1 };
|
||||
static const unsigned int apl_west_i2c1_pins[] = { 2, 3 };
|
||||
static const unsigned int apl_west_i2c2_pins[] = { 4, 5 };
|
||||
static const unsigned int apl_west_i2c3_pins[] = { 6, 7 };
|
||||
static const unsigned int apl_west_i2c4_pins[] = { 8, 9 };
|
||||
static const unsigned int apl_west_i2c5_pins[] = { 10, 11 };
|
||||
static const unsigned int apl_west_i2c6_pins[] = { 12, 13 };
|
||||
static const unsigned int apl_west_i2c7_pins[] = { 14, 15 };
|
||||
static const unsigned int apl_west_uart2_pins[] = { 20, 21, 22, 34 };
|
||||
|
||||
static const struct intel_pingroup apl_west_groups[] = {
|
||||
PIN_GROUP("i2c0_grp", apl_west_i2c0_pins, 1),
|
||||
@ -939,16 +939,16 @@ static const struct pinctrl_pin_desc apl_southwest_pins[] = {
|
||||
PINCTRL_PIN(42, "LPC_FRAMEB"),
|
||||
};
|
||||
|
||||
static const unsigned apl_southwest_emmc0_pins[] = {
|
||||
static const unsigned int apl_southwest_emmc0_pins[] = {
|
||||
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 29,
|
||||
};
|
||||
static const unsigned apl_southwest_sdio_pins[] = {
|
||||
static const unsigned int apl_southwest_sdio_pins[] = {
|
||||
14, 15, 16, 17, 18, 19, 30,
|
||||
};
|
||||
static const unsigned apl_southwest_sdcard_pins[] = {
|
||||
static const unsigned int apl_southwest_sdcard_pins[] = {
|
||||
20, 21, 22, 23, 24, 25, 26, 27, 28,
|
||||
};
|
||||
static const unsigned apl_southwest_i2c7_pins[] = { 32, 33 };
|
||||
static const unsigned int apl_southwest_i2c7_pins[] = { 32, 33 };
|
||||
|
||||
static const struct intel_pingroup apl_southwest_groups[] = {
|
||||
PIN_GROUP("emmc0_grp", apl_southwest_emmc0_pins, 1),
|
||||
@ -1008,50 +1008,10 @@ static const struct platform_device_id bxt_pinctrl_platform_ids[] = {
|
||||
|
||||
static int bxt_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct intel_pinctrl_soc_data *soc_data = NULL;
|
||||
const struct intel_pinctrl_soc_data **soc_table;
|
||||
struct acpi_device *adev;
|
||||
int i;
|
||||
|
||||
adev = ACPI_COMPANION(&pdev->dev);
|
||||
if (adev) {
|
||||
const struct acpi_device_id *id;
|
||||
|
||||
id = acpi_match_device(bxt_pinctrl_acpi_match, &pdev->dev);
|
||||
if (!id)
|
||||
return -ENODEV;
|
||||
|
||||
soc_table = (const struct intel_pinctrl_soc_data **)
|
||||
id->driver_data;
|
||||
|
||||
for (i = 0; soc_table[i]; i++) {
|
||||
if (!strcmp(adev->pnp.unique_id, soc_table[i]->uid)) {
|
||||
soc_data = soc_table[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const struct platform_device_id *pid;
|
||||
|
||||
pid = platform_get_device_id(pdev);
|
||||
if (!pid)
|
||||
return -ENODEV;
|
||||
|
||||
soc_table = (const struct intel_pinctrl_soc_data **)
|
||||
pid->driver_data;
|
||||
soc_data = soc_table[pdev->id];
|
||||
}
|
||||
|
||||
if (!soc_data)
|
||||
return -ENODEV;
|
||||
|
||||
return intel_pinctrl_probe(pdev, soc_data);
|
||||
return intel_pinctrl_probe_by_uid(pdev);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops bxt_pinctrl_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend,
|
||||
intel_pinctrl_resume)
|
||||
};
|
||||
static INTEL_PINCTRL_PM_OPS(bxt_pinctrl_pm_ops);
|
||||
|
||||
static struct platform_driver bxt_pinctrl_driver = {
|
||||
.probe = bxt_pinctrl_probe,
|
||||
|
@ -7,10 +7,10 @@
|
||||
* Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-intel.h"
|
||||
@ -835,21 +835,10 @@ MODULE_DEVICE_TABLE(acpi, cnl_pinctrl_acpi_match);
|
||||
|
||||
static int cnl_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct intel_pinctrl_soc_data *soc_data;
|
||||
const struct acpi_device_id *id;
|
||||
|
||||
id = acpi_match_device(cnl_pinctrl_acpi_match, &pdev->dev);
|
||||
if (!id || !id->driver_data)
|
||||
return -ENODEV;
|
||||
|
||||
soc_data = (const struct intel_pinctrl_soc_data *)id->driver_data;
|
||||
return intel_pinctrl_probe(pdev, soc_data);
|
||||
return intel_pinctrl_probe_by_hid(pdev);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops cnl_pinctrl_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend,
|
||||
intel_pinctrl_resume)
|
||||
};
|
||||
static INTEL_PINCTRL_PM_OPS(cnl_pinctrl_pm_ops);
|
||||
|
||||
static struct platform_driver cnl_pinctrl_driver = {
|
||||
.probe = cnl_pinctrl_probe,
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-intel.h"
|
||||
@ -335,10 +335,7 @@ static int cdf_pinctrl_probe(struct platform_device *pdev)
|
||||
return intel_pinctrl_probe(pdev, &cdf_soc_data);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops cdf_pinctrl_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend,
|
||||
intel_pinctrl_resume)
|
||||
};
|
||||
static INTEL_PINCTRL_PM_OPS(cdf_pinctrl_pm_ops);
|
||||
|
||||
static const struct acpi_device_id cdf_pinctrl_acpi_match[] = {
|
||||
{ "INTC3001" },
|
||||
|
@ -10,19 +10,20 @@
|
||||
* Alan Cox <alan@linux.intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "pinctrl-intel.h"
|
||||
|
||||
#define CHV_INTSTAT 0x300
|
||||
#define CHV_INTMASK 0x380
|
||||
@ -73,7 +74,7 @@
|
||||
* @invert_oe: Invert OE for this pin
|
||||
*/
|
||||
struct chv_alternate_function {
|
||||
unsigned pin;
|
||||
unsigned int pin;
|
||||
u8 mode;
|
||||
bool invert_oe;
|
||||
};
|
||||
@ -90,33 +91,21 @@ struct chv_alternate_function {
|
||||
*/
|
||||
struct chv_pingroup {
|
||||
const char *name;
|
||||
const unsigned *pins;
|
||||
const unsigned int *pins;
|
||||
size_t npins;
|
||||
struct chv_alternate_function altfunc;
|
||||
const struct chv_alternate_function *overrides;
|
||||
size_t noverrides;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct chv_function - A CHV pinmux function
|
||||
* @name: Name of the function
|
||||
* @groups: An array of groups for this function
|
||||
* @ngroups: Number of groups in @groups
|
||||
*/
|
||||
struct chv_function {
|
||||
const char *name;
|
||||
const char * const *groups;
|
||||
size_t ngroups;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct chv_gpio_pinrange - A range of pins that can be used as GPIOs
|
||||
* @base: Start pin number
|
||||
* @npins: Number of pins in this range
|
||||
*/
|
||||
struct chv_gpio_pinrange {
|
||||
unsigned base;
|
||||
unsigned npins;
|
||||
unsigned int base;
|
||||
unsigned int npins;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -131,6 +120,7 @@ struct chv_gpio_pinrange {
|
||||
* @gpio_ranges: An array of GPIO ranges in this community
|
||||
* @ngpio_ranges: Number of GPIO ranges
|
||||
* @nirqs: Total number of IRQs this community can generate
|
||||
* @acpi_space_id: An address space ID for ACPI OpRegion handler
|
||||
*/
|
||||
struct chv_community {
|
||||
const char *uid;
|
||||
@ -138,7 +128,7 @@ struct chv_community {
|
||||
size_t npins;
|
||||
const struct chv_pingroup *groups;
|
||||
size_t ngroups;
|
||||
const struct chv_function *functions;
|
||||
const struct intel_function *functions;
|
||||
size_t nfunctions;
|
||||
const struct chv_gpio_pinrange *gpio_ranges;
|
||||
size_t ngpio_ranges;
|
||||
@ -161,6 +151,8 @@ struct chv_pin_context {
|
||||
* @intr_lines: Stores mapping between 16 HW interrupt wires and GPIO
|
||||
* offset (in GPIO number space)
|
||||
* @community: Community this pinctrl instance represents
|
||||
* @saved_intmask: Interrupt mask saved for system sleep
|
||||
* @saved_pin_context: Pointer to a context of the pins saved for system sleep
|
||||
*
|
||||
* The first group in @groups is expected to contain all pins that can be
|
||||
* used as GPIOs.
|
||||
@ -184,7 +176,7 @@ struct chv_pinctrl {
|
||||
.invert_oe = (i), \
|
||||
}
|
||||
|
||||
#define PIN_GROUP(n, p, m, i) \
|
||||
#define PIN_GROUP_WITH_ALT(n, p, m, i) \
|
||||
{ \
|
||||
.name = (n), \
|
||||
.pins = (p), \
|
||||
@ -204,13 +196,6 @@ struct chv_pinctrl {
|
||||
.noverrides = ARRAY_SIZE((o)), \
|
||||
}
|
||||
|
||||
#define FUNCTION(n, g) \
|
||||
{ \
|
||||
.name = (n), \
|
||||
.groups = (g), \
|
||||
.ngroups = ARRAY_SIZE((g)), \
|
||||
}
|
||||
|
||||
#define GPIO_PINRANGE(start, end) \
|
||||
{ \
|
||||
.base = (start), \
|
||||
@ -282,7 +267,6 @@ static const struct pinctrl_pin_desc southwest_pins[] = {
|
||||
PINCTRL_PIN(97, "GP_SSP_2_TXD"),
|
||||
};
|
||||
|
||||
static const unsigned southwest_fspi_pins[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
|
||||
static const unsigned southwest_uart0_pins[] = { 16, 20 };
|
||||
static const unsigned southwest_uart1_pins[] = { 15, 16, 18, 20 };
|
||||
static const unsigned southwest_uart2_pins[] = { 17, 19, 21, 22 };
|
||||
@ -298,7 +282,6 @@ static const unsigned southwest_i2c4_pins[] = { 46, 50 };
|
||||
static const unsigned southwest_i2c5_pins[] = { 45, 48 };
|
||||
static const unsigned southwest_i2c6_pins[] = { 47, 51 };
|
||||
static const unsigned southwest_i2c_nfc_pins[] = { 49, 52 };
|
||||
static const unsigned southwest_smbus_pins[] = { 79, 81, 82 };
|
||||
static const unsigned southwest_spi3_pins[] = { 76, 79, 80, 81, 82 };
|
||||
|
||||
/* LPE I2S TXD pins need to have invert_oe set */
|
||||
@ -318,18 +301,18 @@ static const struct chv_alternate_function southwest_spi3_altfuncs[] = {
|
||||
};
|
||||
|
||||
static const struct chv_pingroup southwest_groups[] = {
|
||||
PIN_GROUP("uart0_grp", southwest_uart0_pins, 2, false),
|
||||
PIN_GROUP("uart1_grp", southwest_uart1_pins, 1, false),
|
||||
PIN_GROUP("uart2_grp", southwest_uart2_pins, 1, false),
|
||||
PIN_GROUP("hda_grp", southwest_hda_pins, 2, false),
|
||||
PIN_GROUP("i2c0_grp", southwest_i2c0_pins, 1, true),
|
||||
PIN_GROUP("i2c1_grp", southwest_i2c1_pins, 1, true),
|
||||
PIN_GROUP("i2c2_grp", southwest_i2c2_pins, 1, true),
|
||||
PIN_GROUP("i2c3_grp", southwest_i2c3_pins, 1, true),
|
||||
PIN_GROUP("i2c4_grp", southwest_i2c4_pins, 1, true),
|
||||
PIN_GROUP("i2c5_grp", southwest_i2c5_pins, 1, true),
|
||||
PIN_GROUP("i2c6_grp", southwest_i2c6_pins, 1, true),
|
||||
PIN_GROUP("i2c_nfc_grp", southwest_i2c_nfc_pins, 2, true),
|
||||
PIN_GROUP_WITH_ALT("uart0_grp", southwest_uart0_pins, 2, false),
|
||||
PIN_GROUP_WITH_ALT("uart1_grp", southwest_uart1_pins, 1, false),
|
||||
PIN_GROUP_WITH_ALT("uart2_grp", southwest_uart2_pins, 1, false),
|
||||
PIN_GROUP_WITH_ALT("hda_grp", southwest_hda_pins, 2, false),
|
||||
PIN_GROUP_WITH_ALT("i2c0_grp", southwest_i2c0_pins, 1, true),
|
||||
PIN_GROUP_WITH_ALT("i2c1_grp", southwest_i2c1_pins, 1, true),
|
||||
PIN_GROUP_WITH_ALT("i2c2_grp", southwest_i2c2_pins, 1, true),
|
||||
PIN_GROUP_WITH_ALT("i2c3_grp", southwest_i2c3_pins, 1, true),
|
||||
PIN_GROUP_WITH_ALT("i2c4_grp", southwest_i2c4_pins, 1, true),
|
||||
PIN_GROUP_WITH_ALT("i2c5_grp", southwest_i2c5_pins, 1, true),
|
||||
PIN_GROUP_WITH_ALT("i2c6_grp", southwest_i2c6_pins, 1, true),
|
||||
PIN_GROUP_WITH_ALT("i2c_nfc_grp", southwest_i2c_nfc_pins, 2, true),
|
||||
|
||||
PIN_GROUP_WITH_OVERRIDE("lpe_grp", southwest_lpe_pins, 1, false,
|
||||
southwest_lpe_altfuncs),
|
||||
@ -356,7 +339,7 @@ static const char * const southwest_spi3_groups[] = { "spi3_grp" };
|
||||
* Only do pinmuxing for certain LPSS devices for now. Rest of the pins are
|
||||
* enabled only as GPIOs.
|
||||
*/
|
||||
static const struct chv_function southwest_functions[] = {
|
||||
static const struct intel_function southwest_functions[] = {
|
||||
FUNCTION("uart0", southwest_uart0_groups),
|
||||
FUNCTION("uart1", southwest_uart1_groups),
|
||||
FUNCTION("uart2", southwest_uart2_groups),
|
||||
@ -610,13 +593,13 @@ static const unsigned southeast_spi1_pins[] = { 60, 61, 62, 64, 66 };
|
||||
static const unsigned southeast_spi2_pins[] = { 2, 3, 4, 6, 7 };
|
||||
|
||||
static const struct chv_pingroup southeast_groups[] = {
|
||||
PIN_GROUP("pwm0_grp", southeast_pwm0_pins, 1, false),
|
||||
PIN_GROUP("pwm1_grp", southeast_pwm1_pins, 1, false),
|
||||
PIN_GROUP("sdmmc1_grp", southeast_sdmmc1_pins, 1, false),
|
||||
PIN_GROUP("sdmmc2_grp", southeast_sdmmc2_pins, 1, false),
|
||||
PIN_GROUP("sdmmc3_grp", southeast_sdmmc3_pins, 1, false),
|
||||
PIN_GROUP("spi1_grp", southeast_spi1_pins, 1, false),
|
||||
PIN_GROUP("spi2_grp", southeast_spi2_pins, 4, false),
|
||||
PIN_GROUP_WITH_ALT("pwm0_grp", southeast_pwm0_pins, 1, false),
|
||||
PIN_GROUP_WITH_ALT("pwm1_grp", southeast_pwm1_pins, 1, false),
|
||||
PIN_GROUP_WITH_ALT("sdmmc1_grp", southeast_sdmmc1_pins, 1, false),
|
||||
PIN_GROUP_WITH_ALT("sdmmc2_grp", southeast_sdmmc2_pins, 1, false),
|
||||
PIN_GROUP_WITH_ALT("sdmmc3_grp", southeast_sdmmc3_pins, 1, false),
|
||||
PIN_GROUP_WITH_ALT("spi1_grp", southeast_spi1_pins, 1, false),
|
||||
PIN_GROUP_WITH_ALT("spi2_grp", southeast_spi2_pins, 4, false),
|
||||
};
|
||||
|
||||
static const char * const southeast_pwm0_groups[] = { "pwm0_grp" };
|
||||
@ -627,7 +610,7 @@ static const char * const southeast_sdmmc3_groups[] = { "sdmmc3_grp" };
|
||||
static const char * const southeast_spi1_groups[] = { "spi1_grp" };
|
||||
static const char * const southeast_spi2_groups[] = { "spi2_grp" };
|
||||
|
||||
static const struct chv_function southeast_functions[] = {
|
||||
static const struct intel_function southeast_functions[] = {
|
||||
FUNCTION("pwm0", southeast_pwm0_groups),
|
||||
FUNCTION("pwm1", southeast_pwm1_groups),
|
||||
FUNCTION("sdmmc1", southeast_sdmmc1_groups),
|
||||
@ -678,11 +661,11 @@ static const struct chv_community *chv_communities[] = {
|
||||
*/
|
||||
static DEFINE_RAW_SPINLOCK(chv_lock);
|
||||
|
||||
static void __iomem *chv_padreg(struct chv_pinctrl *pctrl, unsigned offset,
|
||||
unsigned reg)
|
||||
static void __iomem *chv_padreg(struct chv_pinctrl *pctrl, unsigned int offset,
|
||||
unsigned int reg)
|
||||
{
|
||||
unsigned family_no = offset / MAX_FAMILY_PAD_GPIO_NO;
|
||||
unsigned pad_no = offset % MAX_FAMILY_PAD_GPIO_NO;
|
||||
unsigned int family_no = offset / MAX_FAMILY_PAD_GPIO_NO;
|
||||
unsigned int pad_no = offset % MAX_FAMILY_PAD_GPIO_NO;
|
||||
|
||||
offset = FAMILY_PAD_REGS_OFF + FAMILY_PAD_REGS_SIZE * family_no +
|
||||
GPIO_REGS_SIZE * pad_no;
|
||||
@ -698,7 +681,7 @@ static void chv_writel(u32 value, void __iomem *reg)
|
||||
}
|
||||
|
||||
/* When Pad Cfg is locked, driver can only change GPIOTXState or GPIORXState */
|
||||
static bool chv_pad_locked(struct chv_pinctrl *pctrl, unsigned offset)
|
||||
static bool chv_pad_locked(struct chv_pinctrl *pctrl, unsigned int offset)
|
||||
{
|
||||
void __iomem *reg;
|
||||
|
||||
@ -714,15 +697,15 @@ static int chv_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
}
|
||||
|
||||
static const char *chv_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned group)
|
||||
unsigned int group)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pctrl->community->groups[group].name;
|
||||
}
|
||||
|
||||
static int chv_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
|
||||
const unsigned **pins, unsigned *npins)
|
||||
static int chv_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
|
||||
const unsigned int **pins, unsigned int *npins)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
@ -732,7 +715,7 @@ static int chv_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
|
||||
}
|
||||
|
||||
static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
|
||||
unsigned offset)
|
||||
unsigned int offset)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned long flags;
|
||||
@ -779,7 +762,7 @@ static int chv_get_functions_count(struct pinctrl_dev *pctldev)
|
||||
}
|
||||
|
||||
static const char *chv_get_function_name(struct pinctrl_dev *pctldev,
|
||||
unsigned function)
|
||||
unsigned int function)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
@ -787,9 +770,9 @@ static const char *chv_get_function_name(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
static int chv_get_function_groups(struct pinctrl_dev *pctldev,
|
||||
unsigned function,
|
||||
unsigned int function,
|
||||
const char * const **groups,
|
||||
unsigned * const ngroups)
|
||||
unsigned int * const ngroups)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
@ -798,8 +781,8 @@ static int chv_get_function_groups(struct pinctrl_dev *pctldev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned function,
|
||||
unsigned group)
|
||||
static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev,
|
||||
unsigned int function, unsigned int group)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct chv_pingroup *grp;
|
||||
@ -865,7 +848,7 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned function,
|
||||
|
||||
static int chv_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned offset)
|
||||
unsigned int offset)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned long flags;
|
||||
@ -925,7 +908,7 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
|
||||
static void chv_gpio_disable_free(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned offset)
|
||||
unsigned int offset)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned long flags;
|
||||
@ -943,7 +926,7 @@ static void chv_gpio_disable_free(struct pinctrl_dev *pctldev,
|
||||
|
||||
static int chv_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned offset, bool input)
|
||||
unsigned int offset, bool input)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
void __iomem *reg = chv_padreg(pctrl, offset, CHV_PADCTRL0);
|
||||
@ -974,7 +957,7 @@ static const struct pinmux_ops chv_pinmux_ops = {
|
||||
.gpio_set_direction = chv_gpio_set_direction,
|
||||
};
|
||||
|
||||
static int chv_config_get(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *config)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
@ -1054,7 +1037,7 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin,
|
||||
static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned int pin,
|
||||
enum pin_config_param param, u32 arg)
|
||||
{
|
||||
void __iomem *reg = chv_padreg(pctrl, pin, CHV_PADCTRL0);
|
||||
@ -1141,8 +1124,8 @@ static int chv_config_set_oden(struct chv_pinctrl *pctrl, unsigned int pin,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chv_config_set(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
unsigned long *configs, unsigned nconfigs)
|
||||
static int chv_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *configs, unsigned int nconfigs)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
enum pin_config_param param;
|
||||
@ -1243,7 +1226,7 @@ static struct pinctrl_desc chv_pinctrl_desc = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int chv_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
static int chv_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
|
||||
unsigned long flags;
|
||||
@ -1261,7 +1244,7 @@ static int chv_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
return !!(ctrl0 & CHV_PADCTRL0_GPIORXSTATE);
|
||||
}
|
||||
|
||||
static void chv_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
static void chv_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
|
||||
unsigned long flags;
|
||||
@ -1283,7 +1266,7 @@ static void chv_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
raw_spin_unlock_irqrestore(&chv_lock, flags);
|
||||
}
|
||||
|
||||
static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
|
||||
u32 ctrl0, direction;
|
||||
@ -1299,12 +1282,12 @@ static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
||||
return direction != CHV_PADCTRL0_GPIOCFG_GPO;
|
||||
}
|
||||
|
||||
static int chv_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
static int chv_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
return pinctrl_gpio_direction_input(chip->base + offset);
|
||||
}
|
||||
|
||||
static int chv_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
|
||||
static int chv_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
chv_gpio_set(chip, offset, value);
|
||||
@ -1388,7 +1371,7 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
|
||||
if (irqd_get_trigger_type(d) == IRQ_TYPE_NONE) {
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
|
||||
unsigned pin = irqd_to_hwirq(d);
|
||||
unsigned int pin = irqd_to_hwirq(d);
|
||||
irq_flow_handler_t handler;
|
||||
unsigned long flags;
|
||||
u32 intsel, value;
|
||||
@ -1415,11 +1398,11 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
|
||||
static int chv_gpio_irq_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
|
||||
unsigned pin = irqd_to_hwirq(d);
|
||||
unsigned int pin = irqd_to_hwirq(d);
|
||||
unsigned long flags;
|
||||
u32 value;
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-intel.h"
|
||||
@ -262,10 +262,7 @@ static int dnv_pinctrl_probe(struct platform_device *pdev)
|
||||
return intel_pinctrl_probe(pdev, &dnv_soc_data);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops dnv_pinctrl_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend,
|
||||
intel_pinctrl_resume)
|
||||
};
|
||||
static INTEL_PINCTRL_PM_OPS(dnv_pinctrl_pm_ops);
|
||||
|
||||
static const struct acpi_device_id dnv_pinctrl_acpi_match[] = {
|
||||
{ "INTC3000" },
|
||||
|
@ -6,17 +6,17 @@
|
||||
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-intel.h"
|
||||
|
||||
#define GLK_PAD_OWN 0x020
|
||||
#define GLK_HOSTSW_OWN 0x0b0
|
||||
#define GLK_PADCFGLOCK 0x080
|
||||
#define GLK_HOSTSW_OWN 0x0b0
|
||||
#define GLK_GPI_IE 0x110
|
||||
|
||||
#define GLK_COMMUNITY(s, e) \
|
||||
@ -58,16 +58,16 @@ static const struct pinctrl_pin_desc glk_northwest_pins[] = {
|
||||
PINCTRL_PIN(23, "GPIO_23"),
|
||||
PINCTRL_PIN(24, "GPIO_24"),
|
||||
PINCTRL_PIN(25, "GPIO_25"),
|
||||
PINCTRL_PIN(26, "GPIO_26"),
|
||||
PINCTRL_PIN(27, "GPIO_27"),
|
||||
PINCTRL_PIN(28, "GPIO_28"),
|
||||
PINCTRL_PIN(29, "GPIO_29"),
|
||||
PINCTRL_PIN(30, "GPIO_30"),
|
||||
PINCTRL_PIN(31, "GPIO_31"),
|
||||
PINCTRL_PIN(32, "GPIO_32"),
|
||||
PINCTRL_PIN(33, "GPIO_33"),
|
||||
PINCTRL_PIN(34, "GPIO_34"),
|
||||
PINCTRL_PIN(35, "GPIO_35"),
|
||||
PINCTRL_PIN(26, "ISH_GPIO_0"),
|
||||
PINCTRL_PIN(27, "ISH_GPIO_1"),
|
||||
PINCTRL_PIN(28, "ISH_GPIO_2"),
|
||||
PINCTRL_PIN(29, "ISH_GPIO_3"),
|
||||
PINCTRL_PIN(30, "ISH_GPIO_4"),
|
||||
PINCTRL_PIN(31, "ISH_GPIO_5"),
|
||||
PINCTRL_PIN(32, "ISH_GPIO_6"),
|
||||
PINCTRL_PIN(33, "ISH_GPIO_7"),
|
||||
PINCTRL_PIN(34, "ISH_GPIO_8"),
|
||||
PINCTRL_PIN(35, "ISH_GPIO_9"),
|
||||
PINCTRL_PIN(36, "GPIO_36"),
|
||||
PINCTRL_PIN(37, "GPIO_37"),
|
||||
PINCTRL_PIN(38, "GPIO_38"),
|
||||
@ -195,12 +195,12 @@ static const struct pinctrl_pin_desc glk_north_pins[] = {
|
||||
PINCTRL_PIN(5, "LPSS_SPI_0_FS1"),
|
||||
PINCTRL_PIN(6, "LPSS_SPI_0_RXD"),
|
||||
PINCTRL_PIN(7, "LPSS_SPI_0_TXD"),
|
||||
PINCTRL_PIN(8, "LPSS_SPI_1_CLK"),
|
||||
PINCTRL_PIN(9, "LPSS_SPI_1_FS0"),
|
||||
PINCTRL_PIN(10, "LPSS_SPI_1_FS1"),
|
||||
PINCTRL_PIN(11, "LPSS_SPI_1_FS2"),
|
||||
PINCTRL_PIN(12, "LPSS_SPI_1_RXD"),
|
||||
PINCTRL_PIN(13, "LPSS_SPI_1_TXD"),
|
||||
PINCTRL_PIN(8, "LPSS_SPI_2_CLK"),
|
||||
PINCTRL_PIN(9, "LPSS_SPI_2_FS0"),
|
||||
PINCTRL_PIN(10, "LPSS_SPI_2_FS1"),
|
||||
PINCTRL_PIN(11, "LPSS_SPI_2_FS2"),
|
||||
PINCTRL_PIN(12, "LPSS_SPI_2_RXD"),
|
||||
PINCTRL_PIN(13, "LPSS_SPI_2_TXD"),
|
||||
PINCTRL_PIN(14, "FST_SPI_CS0_B"),
|
||||
PINCTRL_PIN(15, "FST_SPI_CS1_B"),
|
||||
PINCTRL_PIN(16, "FST_SPI_MOSI_IO0"),
|
||||
@ -215,8 +215,8 @@ static const struct pinctrl_pin_desc glk_north_pins[] = {
|
||||
PINCTRL_PIN(25, "PMU_SLP_S3_B"),
|
||||
PINCTRL_PIN(26, "PMU_SLP_S4_B"),
|
||||
PINCTRL_PIN(27, "SUSPWRDNACK"),
|
||||
PINCTRL_PIN(28, "EMMC_PWR_EN_B"),
|
||||
PINCTRL_PIN(29, "PMU_AC_PRESENT"),
|
||||
PINCTRL_PIN(28, "EMMC_DNX_PWR_EN_B"),
|
||||
PINCTRL_PIN(29, "GPIO_105"),
|
||||
PINCTRL_PIN(30, "PMU_BATLOW_B"),
|
||||
PINCTRL_PIN(31, "PMU_RESETBUTTON_B"),
|
||||
PINCTRL_PIN(32, "PMU_SUSCLK"),
|
||||
@ -449,42 +449,15 @@ static const struct intel_pinctrl_soc_data *glk_pinctrl_soc_data[] = {
|
||||
};
|
||||
|
||||
static const struct acpi_device_id glk_pinctrl_acpi_match[] = {
|
||||
{ "INT3453" },
|
||||
{ "INT3453", (kernel_ulong_t)glk_pinctrl_soc_data },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, glk_pinctrl_acpi_match);
|
||||
|
||||
static int glk_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct intel_pinctrl_soc_data *soc_data = NULL;
|
||||
struct acpi_device *adev;
|
||||
int i;
|
||||
|
||||
adev = ACPI_COMPANION(&pdev->dev);
|
||||
if (!adev)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; glk_pinctrl_soc_data[i]; i++) {
|
||||
if (!strcmp(adev->pnp.unique_id,
|
||||
glk_pinctrl_soc_data[i]->uid)) {
|
||||
soc_data = glk_pinctrl_soc_data[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!soc_data)
|
||||
return -ENODEV;
|
||||
|
||||
return intel_pinctrl_probe(pdev, soc_data);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops glk_pinctrl_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend,
|
||||
intel_pinctrl_resume)
|
||||
};
|
||||
static INTEL_PINCTRL_PM_OPS(glk_pinctrl_pm_ops);
|
||||
|
||||
static struct platform_driver glk_pinctrl_driver = {
|
||||
.probe = glk_pinctrl_probe,
|
||||
.probe = intel_pinctrl_probe_by_uid,
|
||||
.driver = {
|
||||
.name = "geminilake-pinctrl",
|
||||
.acpi_match_table = glk_pinctrl_acpi_match,
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-intel.h"
|
||||
@ -408,10 +408,7 @@ static int icl_pinctrl_probe(struct platform_device *pdev)
|
||||
return intel_pinctrl_probe(pdev, &icllp_soc_data);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops icl_pinctrl_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend,
|
||||
intel_pinctrl_resume)
|
||||
};
|
||||
static INTEL_PINCTRL_PM_OPS(icl_pinctrl_pm_ops);
|
||||
|
||||
static const struct acpi_device_id icl_pinctrl_acpi_match[] = {
|
||||
{ "INT3455" },
|
||||
|
@ -7,11 +7,14 @@
|
||||
* Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
@ -115,7 +118,7 @@ struct intel_pinctrl {
|
||||
#define padgroup_offset(g, p) ((p) - (g)->base)
|
||||
|
||||
static struct intel_community *intel_get_community(struct intel_pinctrl *pctrl,
|
||||
unsigned pin)
|
||||
unsigned int pin)
|
||||
{
|
||||
struct intel_community *community;
|
||||
int i;
|
||||
@ -133,7 +136,7 @@ static struct intel_community *intel_get_community(struct intel_pinctrl *pctrl,
|
||||
|
||||
static const struct intel_padgroup *
|
||||
intel_community_get_padgroup(const struct intel_community *community,
|
||||
unsigned pin)
|
||||
unsigned int pin)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -147,11 +150,11 @@ intel_community_get_padgroup(const struct intel_community *community,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl, unsigned pin,
|
||||
unsigned reg)
|
||||
static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl,
|
||||
unsigned int pin, unsigned int reg)
|
||||
{
|
||||
const struct intel_community *community;
|
||||
unsigned padno;
|
||||
unsigned int padno;
|
||||
size_t nregs;
|
||||
|
||||
community = intel_get_community(pctrl, pin);
|
||||
@ -167,11 +170,11 @@ static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl, unsigned pin,
|
||||
return community->pad_regs + reg + padno * nregs * 4;
|
||||
}
|
||||
|
||||
static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
|
||||
static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
{
|
||||
const struct intel_community *community;
|
||||
const struct intel_padgroup *padgrp;
|
||||
unsigned gpp, offset, gpp_offset;
|
||||
unsigned int gpp, offset, gpp_offset;
|
||||
void __iomem *padown;
|
||||
|
||||
community = intel_get_community(pctrl, pin);
|
||||
@ -192,11 +195,11 @@ static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
|
||||
return !(readl(padown) & PADOWN_MASK(gpp_offset));
|
||||
}
|
||||
|
||||
static bool intel_pad_acpi_mode(struct intel_pinctrl *pctrl, unsigned pin)
|
||||
static bool intel_pad_acpi_mode(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
{
|
||||
const struct intel_community *community;
|
||||
const struct intel_padgroup *padgrp;
|
||||
unsigned offset, gpp_offset;
|
||||
unsigned int offset, gpp_offset;
|
||||
void __iomem *hostown;
|
||||
|
||||
community = intel_get_community(pctrl, pin);
|
||||
@ -216,11 +219,11 @@ static bool intel_pad_acpi_mode(struct intel_pinctrl *pctrl, unsigned pin)
|
||||
return !(readl(hostown) & BIT(gpp_offset));
|
||||
}
|
||||
|
||||
static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned pin)
|
||||
static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
{
|
||||
struct intel_community *community;
|
||||
const struct intel_padgroup *padgrp;
|
||||
unsigned offset, gpp_offset;
|
||||
unsigned int offset, gpp_offset;
|
||||
u32 value;
|
||||
|
||||
community = intel_get_community(pctrl, pin);
|
||||
@ -253,7 +256,7 @@ static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned pin)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool intel_pad_usable(struct intel_pinctrl *pctrl, unsigned pin)
|
||||
static bool intel_pad_usable(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
{
|
||||
return intel_pad_owned_by_host(pctrl, pin) &&
|
||||
!intel_pad_locked(pctrl, pin);
|
||||
@ -267,15 +270,15 @@ static int intel_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
}
|
||||
|
||||
static const char *intel_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned group)
|
||||
unsigned int group)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pctrl->soc->groups[group].name;
|
||||
}
|
||||
|
||||
static int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
|
||||
const unsigned **pins, unsigned *npins)
|
||||
static int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
|
||||
const unsigned int **pins, unsigned int *npins)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
@ -285,7 +288,7 @@ static int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
|
||||
}
|
||||
|
||||
static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
|
||||
unsigned pin)
|
||||
unsigned int pin)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
void __iomem *padcfg;
|
||||
@ -344,7 +347,7 @@ static int intel_get_functions_count(struct pinctrl_dev *pctldev)
|
||||
}
|
||||
|
||||
static const char *intel_get_function_name(struct pinctrl_dev *pctldev,
|
||||
unsigned function)
|
||||
unsigned int function)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
@ -352,9 +355,9 @@ static const char *intel_get_function_name(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
static int intel_get_function_groups(struct pinctrl_dev *pctldev,
|
||||
unsigned function,
|
||||
unsigned int function,
|
||||
const char * const **groups,
|
||||
unsigned * const ngroups)
|
||||
unsigned int * const ngroups)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
@ -363,8 +366,8 @@ static int intel_get_function_groups(struct pinctrl_dev *pctldev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned function,
|
||||
unsigned group)
|
||||
static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev,
|
||||
unsigned int function, unsigned int group)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct intel_pingroup *grp = &pctrl->soc->groups[group];
|
||||
@ -436,7 +439,7 @@ static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
|
||||
|
||||
static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned pin)
|
||||
unsigned int pin)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
void __iomem *padcfg0;
|
||||
@ -461,7 +464,7 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
|
||||
static int intel_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned pin, bool input)
|
||||
unsigned int pin, bool input)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
void __iomem *padcfg0;
|
||||
@ -486,7 +489,7 @@ static const struct pinmux_ops intel_pinmux_ops = {
|
||||
.gpio_set_direction = intel_gpio_set_direction,
|
||||
};
|
||||
|
||||
static int intel_config_get(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
static int intel_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *config)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
@ -575,11 +578,11 @@ static int intel_config_get(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin,
|
||||
static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
|
||||
unsigned long config)
|
||||
{
|
||||
unsigned param = pinconf_to_config_param(config);
|
||||
unsigned arg = pinconf_to_config_argument(config);
|
||||
unsigned int param = pinconf_to_config_param(config);
|
||||
unsigned int arg = pinconf_to_config_argument(config);
|
||||
const struct intel_community *community;
|
||||
void __iomem *padcfg1;
|
||||
unsigned long flags;
|
||||
@ -653,8 +656,8 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int intel_config_set_debounce(struct intel_pinctrl *pctrl, unsigned pin,
|
||||
unsigned debounce)
|
||||
static int intel_config_set_debounce(struct intel_pinctrl *pctrl,
|
||||
unsigned int pin, unsigned int debounce)
|
||||
{
|
||||
void __iomem *padcfg0, *padcfg2;
|
||||
unsigned long flags;
|
||||
@ -700,8 +703,8 @@ exit_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int intel_config_set(struct pinctrl_dev *pctldev, unsigned pin,
|
||||
unsigned long *configs, unsigned nconfigs)
|
||||
static int intel_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *configs, unsigned int nconfigs)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
int i, ret;
|
||||
@ -751,14 +754,14 @@ static const struct pinctrl_desc intel_pinctrl_desc = {
|
||||
* intel_gpio_to_pin() - Translate from GPIO offset to pin number
|
||||
* @pctrl: Pinctrl structure
|
||||
* @offset: GPIO offset from gpiolib
|
||||
* @commmunity: Community is filled here if not %NULL
|
||||
* @community: Community is filled here if not %NULL
|
||||
* @padgrp: Pad group is filled here if not %NULL
|
||||
*
|
||||
* When coming through gpiolib irqchip, the GPIO offset is not
|
||||
* automatically translated to pinctrl pin number. This function can be
|
||||
* used to find out the corresponding pinctrl pin.
|
||||
*/
|
||||
static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned offset,
|
||||
static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned int offset,
|
||||
const struct intel_community **community,
|
||||
const struct intel_padgroup **padgrp)
|
||||
{
|
||||
@ -792,7 +795,7 @@ static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned offset,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
static int intel_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
|
||||
void __iomem *reg;
|
||||
@ -814,7 +817,8 @@ static int intel_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
return !!(padcfg0 & PADCFG0_GPIORXSTATE);
|
||||
}
|
||||
|
||||
static void intel_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
static void intel_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
|
||||
unsigned long flags;
|
||||
@ -863,12 +867,12 @@ static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
|
||||
return !!(padcfg0 & PADCFG0_GPIOTXDIS);
|
||||
}
|
||||
|
||||
static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
static int intel_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
return pinctrl_gpio_direction_input(chip->base + offset);
|
||||
}
|
||||
|
||||
static int intel_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
|
||||
static int intel_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
|
||||
int value)
|
||||
{
|
||||
intel_gpio_set(chip, offset, value);
|
||||
@ -897,7 +901,7 @@ static void intel_gpio_irq_ack(struct irq_data *d)
|
||||
|
||||
pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
|
||||
if (pin >= 0) {
|
||||
unsigned gpp, gpp_offset, is_offset;
|
||||
unsigned int gpp, gpp_offset, is_offset;
|
||||
|
||||
gpp = padgrp->reg_num;
|
||||
gpp_offset = padgroup_offset(padgrp, pin);
|
||||
@ -919,7 +923,7 @@ static void intel_gpio_irq_enable(struct irq_data *d)
|
||||
|
||||
pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
|
||||
if (pin >= 0) {
|
||||
unsigned gpp, gpp_offset, is_offset;
|
||||
unsigned int gpp, gpp_offset, is_offset;
|
||||
unsigned long flags;
|
||||
u32 value;
|
||||
|
||||
@ -948,7 +952,7 @@ static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
|
||||
|
||||
pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
|
||||
if (pin >= 0) {
|
||||
unsigned gpp, gpp_offset;
|
||||
unsigned int gpp, gpp_offset;
|
||||
unsigned long flags;
|
||||
void __iomem *reg;
|
||||
u32 value;
|
||||
@ -979,11 +983,11 @@ static void intel_gpio_irq_unmask(struct irq_data *d)
|
||||
intel_gpio_irq_mask_unmask(d, false);
|
||||
}
|
||||
|
||||
static int intel_gpio_irq_type(struct irq_data *d, unsigned type)
|
||||
static int intel_gpio_irq_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
|
||||
unsigned pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
|
||||
unsigned int pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
|
||||
unsigned long flags;
|
||||
void __iomem *reg;
|
||||
u32 value;
|
||||
@ -1040,7 +1044,7 @@ static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
|
||||
unsigned pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
|
||||
unsigned int pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
|
||||
|
||||
if (on)
|
||||
enable_irq_wake(pctrl->irq);
|
||||
@ -1135,7 +1139,7 @@ static int intel_gpio_add_pin_ranges(struct intel_pinctrl *pctrl,
|
||||
static unsigned intel_gpio_ngpio(const struct intel_pinctrl *pctrl)
|
||||
{
|
||||
const struct intel_community *community;
|
||||
unsigned ngpio = 0;
|
||||
unsigned int ngpio = 0;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
@ -1211,8 +1215,8 @@ static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
|
||||
struct intel_community *community)
|
||||
{
|
||||
struct intel_padgroup *gpps;
|
||||
unsigned npins = community->npins;
|
||||
unsigned padown_num = 0;
|
||||
unsigned int npins = community->npins;
|
||||
unsigned int padown_num = 0;
|
||||
size_t ngpps, i;
|
||||
|
||||
if (community->gpps)
|
||||
@ -1228,7 +1232,7 @@ static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
|
||||
if (community->gpps) {
|
||||
gpps[i] = community->gpps[i];
|
||||
} else {
|
||||
unsigned gpp_size = community->gpp_size;
|
||||
unsigned int gpp_size = community->gpp_size;
|
||||
|
||||
gpps[i].reg_num = i;
|
||||
gpps[i].base = community->pin_base + i * gpp_size;
|
||||
@ -1398,8 +1402,52 @@ int intel_pinctrl_probe(struct platform_device *pdev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_pinctrl_probe);
|
||||
|
||||
int intel_pinctrl_probe_by_hid(struct platform_device *pdev)
|
||||
{
|
||||
const struct intel_pinctrl_soc_data *data;
|
||||
|
||||
data = device_get_match_data(&pdev->dev);
|
||||
return intel_pinctrl_probe(pdev, data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_pinctrl_probe_by_hid);
|
||||
|
||||
int intel_pinctrl_probe_by_uid(struct platform_device *pdev)
|
||||
{
|
||||
const struct intel_pinctrl_soc_data *data = NULL;
|
||||
const struct intel_pinctrl_soc_data **table;
|
||||
struct acpi_device *adev;
|
||||
unsigned int i;
|
||||
|
||||
adev = ACPI_COMPANION(&pdev->dev);
|
||||
if (adev) {
|
||||
const void *match = device_get_match_data(&pdev->dev);
|
||||
|
||||
table = (const struct intel_pinctrl_soc_data **)match;
|
||||
for (i = 0; table[i]; i++) {
|
||||
if (!strcmp(adev->pnp.unique_id, table[i]->uid)) {
|
||||
data = table[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const struct platform_device_id *id;
|
||||
|
||||
id = platform_get_device_id(pdev);
|
||||
if (!id)
|
||||
return -ENODEV;
|
||||
|
||||
table = (const struct intel_pinctrl_soc_data **)id->driver_data;
|
||||
data = table[pdev->id];
|
||||
}
|
||||
if (!data)
|
||||
return -ENODEV;
|
||||
|
||||
return intel_pinctrl_probe(pdev, data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_pinctrl_probe_by_uid);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned pin)
|
||||
static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int pin)
|
||||
{
|
||||
const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin);
|
||||
|
||||
@ -1450,7 +1498,7 @@ int intel_pinctrl_suspend(struct device *dev)
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
struct intel_community *community = &pctrl->communities[i];
|
||||
void __iomem *base;
|
||||
unsigned gpp;
|
||||
unsigned int gpp;
|
||||
|
||||
base = community->regs + community->ie_offset;
|
||||
for (gpp = 0; gpp < community->ngpps; gpp++)
|
||||
@ -1468,7 +1516,7 @@ static void intel_gpio_irq_init(struct intel_pinctrl *pctrl)
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
const struct intel_community *community;
|
||||
void __iomem *base;
|
||||
unsigned gpp;
|
||||
unsigned int gpp;
|
||||
|
||||
community = &pctrl->communities[i];
|
||||
base = community->regs;
|
||||
@ -1532,7 +1580,7 @@ int intel_pinctrl_resume(struct device *dev)
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
struct intel_community *community = &pctrl->communities[i];
|
||||
void __iomem *base;
|
||||
unsigned gpp;
|
||||
unsigned int gpp;
|
||||
|
||||
base = community->regs + community->ie_offset;
|
||||
for (gpp = 0; gpp < community->ngpps; gpp++) {
|
||||
|
@ -10,6 +10,8 @@
|
||||
#ifndef PINCTRL_INTEL_H
|
||||
#define PINCTRL_INTEL_H
|
||||
|
||||
#include <linux/pm.h>
|
||||
|
||||
struct pinctrl_pin_desc;
|
||||
struct platform_device;
|
||||
struct device;
|
||||
@ -25,10 +27,10 @@ struct device;
|
||||
*/
|
||||
struct intel_pingroup {
|
||||
const char *name;
|
||||
const unsigned *pins;
|
||||
const unsigned int *pins;
|
||||
size_t npins;
|
||||
unsigned short mode;
|
||||
const unsigned *modes;
|
||||
const unsigned int *modes;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -56,11 +58,11 @@ struct intel_function {
|
||||
* to specify them.
|
||||
*/
|
||||
struct intel_padgroup {
|
||||
unsigned reg_num;
|
||||
unsigned base;
|
||||
unsigned size;
|
||||
unsigned int reg_num;
|
||||
unsigned int base;
|
||||
unsigned int size;
|
||||
int gpio_base;
|
||||
unsigned padown_num;
|
||||
unsigned int padown_num;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -96,17 +98,17 @@ struct intel_padgroup {
|
||||
* pass custom @gpps and @ngpps instead.
|
||||
*/
|
||||
struct intel_community {
|
||||
unsigned barno;
|
||||
unsigned padown_offset;
|
||||
unsigned padcfglock_offset;
|
||||
unsigned hostown_offset;
|
||||
unsigned is_offset;
|
||||
unsigned ie_offset;
|
||||
unsigned pin_base;
|
||||
unsigned gpp_size;
|
||||
unsigned gpp_num_padown_regs;
|
||||
unsigned int barno;
|
||||
unsigned int padown_offset;
|
||||
unsigned int padcfglock_offset;
|
||||
unsigned int hostown_offset;
|
||||
unsigned int is_offset;
|
||||
unsigned int ie_offset;
|
||||
unsigned int pin_base;
|
||||
unsigned int gpp_size;
|
||||
unsigned int gpp_num_padown_regs;
|
||||
size_t npins;
|
||||
unsigned features;
|
||||
unsigned int features;
|
||||
const struct intel_padgroup *gpps;
|
||||
size_t ngpps;
|
||||
/* Reserved for the core driver */
|
||||
@ -173,9 +175,17 @@ struct intel_pinctrl_soc_data {
|
||||
|
||||
int intel_pinctrl_probe(struct platform_device *pdev,
|
||||
const struct intel_pinctrl_soc_data *soc_data);
|
||||
int intel_pinctrl_probe_by_hid(struct platform_device *pdev);
|
||||
int intel_pinctrl_probe_by_uid(struct platform_device *pdev);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int intel_pinctrl_suspend(struct device *dev);
|
||||
int intel_pinctrl_resume(struct device *dev);
|
||||
#endif
|
||||
|
||||
#define INTEL_PINCTRL_PM_OPS(_name) \
|
||||
const struct dev_pm_ops _name = { \
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend, intel_pinctrl_resume) \
|
||||
}
|
||||
|
||||
#endif /* PINCTRL_INTEL_H */
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-intel.h"
|
||||
@ -313,10 +313,7 @@ static int lbg_pinctrl_probe(struct platform_device *pdev)
|
||||
return intel_pinctrl_probe(pdev, &lbg_soc_data);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops lbg_pinctrl_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend,
|
||||
intel_pinctrl_resume)
|
||||
};
|
||||
static INTEL_PINCTRL_PM_OPS(lbg_pinctrl_pm_ops);
|
||||
|
||||
static const struct acpi_device_id lbg_pinctrl_acpi_match[] = {
|
||||
{ "INT3536" },
|
||||
|
@ -476,6 +476,34 @@ static void __iomem *mrfld_get_bufcfg(struct mrfld_pinctrl *mp, unsigned int pin
|
||||
return family->regs + BUFCFG_OFFSET + bufno * 4;
|
||||
}
|
||||
|
||||
static int mrfld_read_bufcfg(struct mrfld_pinctrl *mp, unsigned int pin, u32 *value)
|
||||
{
|
||||
void __iomem *bufcfg;
|
||||
|
||||
if (!mrfld_buf_available(mp, pin))
|
||||
return -EBUSY;
|
||||
|
||||
bufcfg = mrfld_get_bufcfg(mp, pin);
|
||||
*value = readl(bufcfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mrfld_update_bufcfg(struct mrfld_pinctrl *mp, unsigned int pin,
|
||||
u32 bits, u32 mask)
|
||||
{
|
||||
void __iomem *bufcfg;
|
||||
u32 value;
|
||||
|
||||
bufcfg = mrfld_get_bufcfg(mp, pin);
|
||||
value = readl(bufcfg);
|
||||
|
||||
value &= ~mask;
|
||||
value |= bits & mask;
|
||||
|
||||
writel(value, bufcfg);
|
||||
}
|
||||
|
||||
static int mrfld_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
|
||||
@ -505,17 +533,15 @@ static void mrfld_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
|
||||
unsigned int pin)
|
||||
{
|
||||
struct mrfld_pinctrl *mp = pinctrl_dev_get_drvdata(pctldev);
|
||||
void __iomem *bufcfg;
|
||||
u32 value, mode;
|
||||
int ret;
|
||||
|
||||
if (!mrfld_buf_available(mp, pin)) {
|
||||
ret = mrfld_read_bufcfg(mp, pin, &value);
|
||||
if (ret) {
|
||||
seq_puts(s, "not available");
|
||||
return;
|
||||
}
|
||||
|
||||
bufcfg = mrfld_get_bufcfg(mp, pin);
|
||||
value = readl(bufcfg);
|
||||
|
||||
mode = (value & BUFCFG_PINMODE_MASK) >> BUFCFG_PINMODE_SHIFT;
|
||||
if (!mode)
|
||||
seq_puts(s, "GPIO ");
|
||||
@ -559,21 +585,6 @@ static int mrfld_get_function_groups(struct pinctrl_dev *pctldev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mrfld_update_bufcfg(struct mrfld_pinctrl *mp, unsigned int pin,
|
||||
u32 bits, u32 mask)
|
||||
{
|
||||
void __iomem *bufcfg;
|
||||
u32 value;
|
||||
|
||||
bufcfg = mrfld_get_bufcfg(mp, pin);
|
||||
value = readl(bufcfg);
|
||||
|
||||
value &= ~mask;
|
||||
value |= bits & mask;
|
||||
|
||||
writel(value, bufcfg);
|
||||
}
|
||||
|
||||
static int mrfld_pinmux_set_mux(struct pinctrl_dev *pctldev,
|
||||
unsigned int function,
|
||||
unsigned int group)
|
||||
@ -637,11 +648,12 @@ static int mrfld_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
enum pin_config_param param = pinconf_to_config_param(*config);
|
||||
u32 value, term;
|
||||
u16 arg = 0;
|
||||
int ret;
|
||||
|
||||
if (!mrfld_buf_available(mp, pin))
|
||||
ret = mrfld_read_bufcfg(mp, pin, &value);
|
||||
if (ret)
|
||||
return -ENOTSUPP;
|
||||
|
||||
value = readl(mrfld_get_bufcfg(mp, pin));
|
||||
term = (value & BUFCFG_PUPD_VAL_MASK) >> BUFCFG_PUPD_VAL_SHIFT;
|
||||
|
||||
switch (param) {
|
||||
|
@ -7,10 +7,10 @@
|
||||
* Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-intel.h"
|
||||
@ -593,21 +593,10 @@ MODULE_DEVICE_TABLE(acpi, spt_pinctrl_acpi_match);
|
||||
|
||||
static int spt_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct intel_pinctrl_soc_data *soc_data;
|
||||
const struct acpi_device_id *id;
|
||||
|
||||
id = acpi_match_device(spt_pinctrl_acpi_match, &pdev->dev);
|
||||
if (!id || !id->driver_data)
|
||||
return -ENODEV;
|
||||
|
||||
soc_data = (const struct intel_pinctrl_soc_data *)id->driver_data;
|
||||
return intel_pinctrl_probe(pdev, soc_data);
|
||||
return intel_pinctrl_probe_by_hid(pdev);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops spt_pinctrl_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(intel_pinctrl_suspend,
|
||||
intel_pinctrl_resume)
|
||||
};
|
||||
static INTEL_PINCTRL_PM_OPS(spt_pinctrl_pm_ops);
|
||||
|
||||
static struct platform_driver spt_pinctrl_driver = {
|
||||
.probe = spt_pinctrl_probe,
|
||||
|
@ -3,7 +3,8 @@ menu "MediaTek pinctrl drivers"
|
||||
|
||||
config EINT_MTK
|
||||
bool "MediaTek External Interrupt Support"
|
||||
depends on PINCTRL_MTK || PINCTRL_MT7622 || COMPILE_TEST
|
||||
depends on PINCTRL_MTK || PINCTRL_MTK_MOORE || COMPILE_TEST
|
||||
select GPIOLIB
|
||||
select IRQ_DOMAIN
|
||||
|
||||
config PINCTRL_MTK
|
||||
@ -15,6 +16,24 @@ config PINCTRL_MTK
|
||||
select EINT_MTK
|
||||
select OF_GPIO
|
||||
|
||||
config PINCTRL_MTK_MOORE
|
||||
bool "MediaTek Moore Core that implements generic binding"
|
||||
depends on OF
|
||||
select GENERIC_PINCONF
|
||||
select GENERIC_PINCTRL_GROUPS
|
||||
select GENERIC_PINMUX_FUNCTIONS
|
||||
select GPIOLIB
|
||||
select OF_GPIO
|
||||
|
||||
config PINCTRL_MTK_PARIS
|
||||
bool "MediaTek Paris Core that implements vendor binding"
|
||||
depends on OF
|
||||
select PINMUX
|
||||
select GENERIC_PINCONF
|
||||
select GPIOLIB
|
||||
select EINT_MTK
|
||||
select OF_GPIO
|
||||
|
||||
# For ARMv7 SoCs
|
||||
config PINCTRL_MT2701
|
||||
bool "Mediatek MT2701 pin control"
|
||||
@ -23,6 +42,12 @@ config PINCTRL_MT2701
|
||||
default MACH_MT2701
|
||||
select PINCTRL_MTK
|
||||
|
||||
config PINCTRL_MT7623
|
||||
bool "Mediatek MT7623 pin control with generic binding"
|
||||
depends on MACH_MT7623 || COMPILE_TEST
|
||||
depends on PINCTRL_MTK_MOORE
|
||||
default y
|
||||
|
||||
config PINCTRL_MT8135
|
||||
bool "Mediatek MT8135 pin control"
|
||||
depends on MACH_MT8135 || COMPILE_TEST
|
||||
@ -45,15 +70,18 @@ config PINCTRL_MT2712
|
||||
default ARM64 && ARCH_MEDIATEK
|
||||
select PINCTRL_MTK
|
||||
|
||||
config PINCTRL_MT7622
|
||||
bool "MediaTek MT7622 pin control"
|
||||
config PINCTRL_MT6765
|
||||
bool "Mediatek MT6765 pin control"
|
||||
depends on OF
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
select GENERIC_PINCONF
|
||||
select GENERIC_PINCTRL_GROUPS
|
||||
select GENERIC_PINMUX_FUNCTIONS
|
||||
select GPIOLIB
|
||||
select OF_GPIO
|
||||
default ARM64 && ARCH_MEDIATEK
|
||||
select PINCTRL_MTK_PARIS
|
||||
|
||||
config PINCTRL_MT7622
|
||||
bool "MediaTek MT7622 pin control"
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
depends on PINCTRL_MTK_MOORE
|
||||
default y
|
||||
|
||||
config PINCTRL_MT8173
|
||||
bool "Mediatek MT8173 pin control"
|
||||
@ -62,6 +90,13 @@ config PINCTRL_MT8173
|
||||
default ARM64 && ARCH_MEDIATEK
|
||||
select PINCTRL_MTK
|
||||
|
||||
config PINCTRL_MT8183
|
||||
bool "Mediatek MT8183 pin control"
|
||||
depends on OF
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
default ARM64 && ARCH_MEDIATEK
|
||||
select PINCTRL_MTK_PARIS
|
||||
|
||||
# For PMIC
|
||||
config PINCTRL_MT6397
|
||||
bool "Mediatek MT6397 pin control"
|
||||
|
@ -2,12 +2,17 @@
|
||||
# Core
|
||||
obj-$(CONFIG_EINT_MTK) += mtk-eint.o
|
||||
obj-$(CONFIG_PINCTRL_MTK) += pinctrl-mtk-common.o
|
||||
obj-$(CONFIG_PINCTRL_MTK_MOORE) += pinctrl-moore.o pinctrl-mtk-common-v2.o
|
||||
obj-$(CONFIG_PINCTRL_MTK_PARIS) += pinctrl-paris.o pinctrl-mtk-common-v2.o
|
||||
|
||||
# SoC Drivers
|
||||
obj-$(CONFIG_PINCTRL_MT2701) += pinctrl-mt2701.o
|
||||
obj-$(CONFIG_PINCTRL_MT2712) += pinctrl-mt2712.o
|
||||
obj-$(CONFIG_PINCTRL_MT8135) += pinctrl-mt8135.o
|
||||
obj-$(CONFIG_PINCTRL_MT8127) += pinctrl-mt8127.o
|
||||
obj-$(CONFIG_PINCTRL_MT6765) += pinctrl-mt6765.o
|
||||
obj-$(CONFIG_PINCTRL_MT7622) += pinctrl-mt7622.o
|
||||
obj-$(CONFIG_PINCTRL_MT7623) += pinctrl-mt7623.o
|
||||
obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o
|
||||
obj-$(CONFIG_PINCTRL_MT8183) += pinctrl-mt8183.o
|
||||
obj-$(CONFIG_PINCTRL_MT6397) += pinctrl-mt6397.o
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
@ -92,13 +92,13 @@ 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,
|
||||
static inline 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)
|
||||
static inline int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
690
drivers/pinctrl/mediatek/pinctrl-moore.c
Normal file
690
drivers/pinctrl/mediatek/pinctrl-moore.c
Normal file
@ -0,0 +1,690 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* MediaTek Pinctrl Moore Driver, which implement the generic dt-binding
|
||||
* pinctrl-bindings.txt for MediaTek SoC.
|
||||
*
|
||||
* Copyright (C) 2017-2018 MediaTek Inc.
|
||||
* Author: Sean Wang <sean.wang@mediatek.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
#include "pinctrl-moore.h"
|
||||
|
||||
#define PINCTRL_PINCTRL_DEV KBUILD_MODNAME
|
||||
|
||||
/* Custom pinconf parameters */
|
||||
#define MTK_PIN_CONFIG_TDSEL (PIN_CONFIG_END + 1)
|
||||
#define MTK_PIN_CONFIG_RDSEL (PIN_CONFIG_END + 2)
|
||||
#define MTK_PIN_CONFIG_PU_ADV (PIN_CONFIG_END + 3)
|
||||
#define MTK_PIN_CONFIG_PD_ADV (PIN_CONFIG_END + 4)
|
||||
|
||||
static const struct pinconf_generic_params mtk_custom_bindings[] = {
|
||||
{"mediatek,tdsel", MTK_PIN_CONFIG_TDSEL, 0},
|
||||
{"mediatek,rdsel", MTK_PIN_CONFIG_RDSEL, 0},
|
||||
{"mediatek,pull-up-adv", MTK_PIN_CONFIG_PU_ADV, 1},
|
||||
{"mediatek,pull-down-adv", MTK_PIN_CONFIG_PD_ADV, 1},
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static const struct pin_config_item mtk_conf_items[] = {
|
||||
PCONFDUMP(MTK_PIN_CONFIG_TDSEL, "tdsel", NULL, true),
|
||||
PCONFDUMP(MTK_PIN_CONFIG_RDSEL, "rdsel", NULL, true),
|
||||
PCONFDUMP(MTK_PIN_CONFIG_PU_ADV, "pu-adv", NULL, true),
|
||||
PCONFDUMP(MTK_PIN_CONFIG_PD_ADV, "pd-adv", NULL, true),
|
||||
};
|
||||
#endif
|
||||
|
||||
static int mtk_pinmux_set_mux(struct pinctrl_dev *pctldev,
|
||||
unsigned int selector, unsigned int group)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct function_desc *func;
|
||||
struct group_desc *grp;
|
||||
int i;
|
||||
|
||||
func = pinmux_generic_get_function(pctldev, selector);
|
||||
if (!func)
|
||||
return -EINVAL;
|
||||
|
||||
grp = pinctrl_generic_get_group(pctldev, group);
|
||||
if (!grp)
|
||||
return -EINVAL;
|
||||
|
||||
dev_dbg(pctldev->dev, "enable function %s group %s\n",
|
||||
func->name, grp->name);
|
||||
|
||||
for (i = 0; i < grp->num_pins; i++) {
|
||||
const struct mtk_pin_desc *desc;
|
||||
int *pin_modes = grp->data;
|
||||
int pin = grp->pins[i];
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
|
||||
|
||||
mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
|
||||
pin_modes[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned int pin)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct mtk_pin_desc *desc;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
|
||||
|
||||
return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
|
||||
hw->soc->gpio_m);
|
||||
}
|
||||
|
||||
static int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned int pin, bool input)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct mtk_pin_desc *desc;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
|
||||
|
||||
/* hardware would take 0 as input direction */
|
||||
return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !input);
|
||||
}
|
||||
|
||||
static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
|
||||
unsigned int pin, unsigned long *config)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
u32 param = pinconf_to_config_param(*config);
|
||||
int val, val2, err, reg, ret = 1;
|
||||
const struct mtk_pin_desc *desc;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
if (hw->soc->bias_disable_get) {
|
||||
err = hw->soc->bias_disable_get(hw, desc, &ret);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
if (hw->soc->bias_get) {
|
||||
err = hw->soc->bias_get(hw, desc, 1, &ret);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
if (hw->soc->bias_get) {
|
||||
err = hw->soc->bias_get(hw, desc, 0, &ret);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
case PIN_CONFIG_OUTPUT_ENABLE:
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* HW takes input mode as zero; output mode as non-zero */
|
||||
if ((val && param == PIN_CONFIG_INPUT_ENABLE) ||
|
||||
(!val && param == PIN_CONFIG_OUTPUT_ENABLE))
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &val2);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (val || !val2)
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
if (hw->soc->drive_get) {
|
||||
err = hw->soc->drive_get(hw, desc, &ret);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
err = -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case MTK_PIN_CONFIG_TDSEL:
|
||||
case MTK_PIN_CONFIG_RDSEL:
|
||||
reg = (param == MTK_PIN_CONFIG_TDSEL) ?
|
||||
PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, reg, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ret = val;
|
||||
|
||||
break;
|
||||
case MTK_PIN_CONFIG_PU_ADV:
|
||||
case MTK_PIN_CONFIG_PD_ADV:
|
||||
if (hw->soc->adv_pull_get) {
|
||||
bool pullup;
|
||||
|
||||
pullup = param == MTK_PIN_CONFIG_PU_ADV;
|
||||
err = hw->soc->adv_pull_get(hw, desc, pullup, &ret);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
*config = pinconf_to_config_packed(param, ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *configs, unsigned int num_configs)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct mtk_pin_desc *desc;
|
||||
u32 reg, param, arg;
|
||||
int cfg, err = 0;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
|
||||
|
||||
for (cfg = 0; cfg < num_configs; cfg++) {
|
||||
param = pinconf_to_config_param(configs[cfg]);
|
||||
arg = pinconf_to_config_argument(configs[cfg]);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
if (hw->soc->bias_disable_set) {
|
||||
err = hw->soc->bias_disable_set(hw, desc);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
if (hw->soc->bias_set) {
|
||||
err = hw->soc->bias_set(hw, desc, 1);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
if (hw->soc->bias_set) {
|
||||
err = hw->soc->bias_set(hw, desc, 0);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT_ENABLE:
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
|
||||
MTK_DISABLE);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
|
||||
MTK_OUTPUT);
|
||||
if (err)
|
||||
goto err;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
|
||||
if (hw->soc->ies_present) {
|
||||
mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES,
|
||||
MTK_ENABLE);
|
||||
}
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
|
||||
MTK_INPUT);
|
||||
if (err)
|
||||
goto err;
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR,
|
||||
arg);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
|
||||
MTK_OUTPUT);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO,
|
||||
arg);
|
||||
if (err)
|
||||
goto err;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
/* arg = 1: Input mode & SMT enable ;
|
||||
* arg = 0: Output mode & SMT disable
|
||||
*/
|
||||
arg = arg ? 2 : 1;
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
|
||||
arg & 1);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
|
||||
!!(arg & 2));
|
||||
if (err)
|
||||
goto err;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
if (hw->soc->drive_set) {
|
||||
err = hw->soc->drive_set(hw, desc, arg);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
err = -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case MTK_PIN_CONFIG_TDSEL:
|
||||
case MTK_PIN_CONFIG_RDSEL:
|
||||
reg = (param == MTK_PIN_CONFIG_TDSEL) ?
|
||||
PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, reg, arg);
|
||||
if (err)
|
||||
goto err;
|
||||
break;
|
||||
case MTK_PIN_CONFIG_PU_ADV:
|
||||
case MTK_PIN_CONFIG_PD_ADV:
|
||||
if (hw->soc->adv_pull_set) {
|
||||
bool pullup;
|
||||
|
||||
pullup = param == MTK_PIN_CONFIG_PU_ADV;
|
||||
err = hw->soc->adv_pull_set(hw, desc, pullup,
|
||||
arg);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
err = -ENOTSUPP;
|
||||
}
|
||||
}
|
||||
err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mtk_pinconf_group_get(struct pinctrl_dev *pctldev,
|
||||
unsigned int group, unsigned long *config)
|
||||
{
|
||||
const unsigned int *pins;
|
||||
unsigned int i, npins, old = 0;
|
||||
int ret;
|
||||
|
||||
ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < npins; i++) {
|
||||
if (mtk_pinconf_get(pctldev, pins[i], config))
|
||||
return -ENOTSUPP;
|
||||
|
||||
/* configs do not match between two pins */
|
||||
if (i && old != *config)
|
||||
return -ENOTSUPP;
|
||||
|
||||
old = *config;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_pinconf_group_set(struct pinctrl_dev *pctldev,
|
||||
unsigned int group, unsigned long *configs,
|
||||
unsigned int num_configs)
|
||||
{
|
||||
const unsigned int *pins;
|
||||
unsigned int i, npins;
|
||||
int ret;
|
||||
|
||||
ret = pinctrl_generic_get_group_pins(pctldev, group, &pins, &npins);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < npins; i++) {
|
||||
ret = mtk_pinconf_set(pctldev, pins[i], configs, num_configs);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops mtk_pctlops = {
|
||||
.get_groups_count = pinctrl_generic_get_group_count,
|
||||
.get_group_name = pinctrl_generic_get_group_name,
|
||||
.get_group_pins = pinctrl_generic_get_group_pins,
|
||||
.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
|
||||
.dt_free_map = pinconf_generic_dt_free_map,
|
||||
};
|
||||
|
||||
static const struct pinmux_ops mtk_pmxops = {
|
||||
.get_functions_count = pinmux_generic_get_function_count,
|
||||
.get_function_name = pinmux_generic_get_function_name,
|
||||
.get_function_groups = pinmux_generic_get_function_groups,
|
||||
.set_mux = mtk_pinmux_set_mux,
|
||||
.gpio_request_enable = mtk_pinmux_gpio_request_enable,
|
||||
.gpio_set_direction = mtk_pinmux_gpio_set_direction,
|
||||
.strict = true,
|
||||
};
|
||||
|
||||
static const struct pinconf_ops mtk_confops = {
|
||||
.is_generic = true,
|
||||
.pin_config_get = mtk_pinconf_get,
|
||||
.pin_config_set = mtk_pinconf_set,
|
||||
.pin_config_group_get = mtk_pinconf_group_get,
|
||||
.pin_config_group_set = mtk_pinconf_group_set,
|
||||
.pin_config_config_dbg_show = pinconf_generic_dump_config,
|
||||
};
|
||||
|
||||
static struct pinctrl_desc mtk_desc = {
|
||||
.name = PINCTRL_PINCTRL_DEV,
|
||||
.pctlops = &mtk_pctlops,
|
||||
.pmxops = &mtk_pmxops,
|
||||
.confops = &mtk_confops,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio)
|
||||
{
|
||||
struct mtk_pinctrl *hw = gpiochip_get_data(chip);
|
||||
const struct mtk_pin_desc *desc;
|
||||
int value, err;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return !!value;
|
||||
}
|
||||
|
||||
static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)
|
||||
{
|
||||
struct mtk_pinctrl *hw = gpiochip_get_data(chip);
|
||||
const struct mtk_pin_desc *desc;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
|
||||
|
||||
mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value);
|
||||
}
|
||||
|
||||
static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
|
||||
{
|
||||
return pinctrl_gpio_direction_input(chip->base + gpio);
|
||||
}
|
||||
|
||||
static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
|
||||
int value)
|
||||
{
|
||||
mtk_gpio_set(chip, gpio, value);
|
||||
|
||||
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);
|
||||
const struct mtk_pin_desc *desc;
|
||||
|
||||
if (!hw->eint)
|
||||
return -ENOTSUPP;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset];
|
||||
|
||||
if (desc->eint.eint_n == (u16)EINT_NA)
|
||||
return -ENOTSUPP;
|
||||
|
||||
return mtk_eint_find_irq(hw->eint, desc->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);
|
||||
const struct mtk_pin_desc *desc;
|
||||
u32 debounce;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset];
|
||||
|
||||
if (!hw->eint ||
|
||||
pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE ||
|
||||
desc->eint.eint_n == (u16)EINT_NA)
|
||||
return -ENOTSUPP;
|
||||
|
||||
debounce = pinconf_to_config_argument(config);
|
||||
|
||||
return mtk_eint_set_debounce(hw->eint, desc->eint.eint_n, debounce);
|
||||
}
|
||||
|
||||
static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
|
||||
{
|
||||
struct gpio_chip *chip = &hw->chip;
|
||||
int ret;
|
||||
|
||||
chip->label = PINCTRL_PINCTRL_DEV;
|
||||
chip->parent = hw->dev;
|
||||
chip->request = gpiochip_generic_request;
|
||||
chip->free = gpiochip_generic_free;
|
||||
chip->direction_input = mtk_gpio_direction_input;
|
||||
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;
|
||||
chip->of_gpio_n_cells = 2;
|
||||
|
||||
ret = gpiochip_add_data(chip, hw);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Just for backward compatible for these old pinctrl nodes without
|
||||
* "gpio-ranges" property. Otherwise, called 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.
|
||||
*/
|
||||
if (!of_find_property(np, "gpio-ranges", NULL)) {
|
||||
ret = gpiochip_add_pin_range(chip, dev_name(hw->dev), 0, 0,
|
||||
chip->ngpio);
|
||||
if (ret < 0) {
|
||||
gpiochip_remove(chip);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_build_groups(struct mtk_pinctrl *hw)
|
||||
{
|
||||
int err, i;
|
||||
|
||||
for (i = 0; i < hw->soc->ngrps; i++) {
|
||||
const struct group_desc *group = hw->soc->grps + i;
|
||||
|
||||
err = pinctrl_generic_add_group(hw->pctrl, group->name,
|
||||
group->pins, group->num_pins,
|
||||
group->data);
|
||||
if (err < 0) {
|
||||
dev_err(hw->dev, "Failed to register group %s\n",
|
||||
group->name);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_build_functions(struct mtk_pinctrl *hw)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < hw->soc->nfuncs ; i++) {
|
||||
const struct function_desc *func = hw->soc->funcs + i;
|
||||
|
||||
err = pinmux_generic_add_function(hw->pctrl, func->name,
|
||||
func->group_names,
|
||||
func->num_group_names,
|
||||
func->data);
|
||||
if (err < 0) {
|
||||
dev_err(hw->dev, "Failed to register function %s\n",
|
||||
func->name);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_moore_pinctrl_probe(struct platform_device *pdev,
|
||||
const struct mtk_pin_soc *soc)
|
||||
{
|
||||
struct pinctrl_pin_desc *pins;
|
||||
struct resource *res;
|
||||
struct mtk_pinctrl *hw;
|
||||
int err, i;
|
||||
|
||||
hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
|
||||
if (!hw)
|
||||
return -ENOMEM;
|
||||
|
||||
hw->soc = soc;
|
||||
hw->dev = &pdev->dev;
|
||||
|
||||
if (!hw->soc->nbase_names) {
|
||||
dev_err(&pdev->dev,
|
||||
"SoC should be assigned at least one register base\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hw->base = devm_kmalloc_array(&pdev->dev, hw->soc->nbase_names,
|
||||
sizeof(*hw->base), GFP_KERNEL);
|
||||
if (!hw->base)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < hw->soc->nbase_names; i++) {
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
hw->soc->base_names[i]);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "missing IO resource\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
hw->base[i] = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(hw->base[i]))
|
||||
return PTR_ERR(hw->base[i]);
|
||||
}
|
||||
|
||||
hw->nbase = hw->soc->nbase_names;
|
||||
|
||||
/* Copy from internal struct mtk_pin_desc to register to the core */
|
||||
pins = devm_kmalloc_array(&pdev->dev, hw->soc->npins, sizeof(*pins),
|
||||
GFP_KERNEL);
|
||||
if (!pins)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < hw->soc->npins; i++) {
|
||||
pins[i].number = hw->soc->pins[i].number;
|
||||
pins[i].name = hw->soc->pins[i].name;
|
||||
}
|
||||
|
||||
/* Setup pins descriptions per SoC types */
|
||||
mtk_desc.pins = (const struct pinctrl_pin_desc *)pins;
|
||||
mtk_desc.npins = hw->soc->npins;
|
||||
mtk_desc.num_custom_params = ARRAY_SIZE(mtk_custom_bindings);
|
||||
mtk_desc.custom_params = mtk_custom_bindings;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
mtk_desc.custom_conf_items = mtk_conf_items;
|
||||
#endif
|
||||
|
||||
err = devm_pinctrl_register_and_init(&pdev->dev, &mtk_desc, hw,
|
||||
&hw->pctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Setup groups descriptions per SoC types */
|
||||
err = mtk_build_groups(hw);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to build groups\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Setup functions descriptions per SoC types */
|
||||
err = mtk_build_functions(hw);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to build functions\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* For able to make pinctrl_claim_hogs, we must not enable pinctrl
|
||||
* until all groups and functions are being added one.
|
||||
*/
|
||||
err = pinctrl_enable(hw->pctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_build_eint(hw, pdev);
|
||||
if (err)
|
||||
dev_warn(&pdev->dev,
|
||||
"Failed to add EINT, but pinctrl still can work\n");
|
||||
|
||||
/* Build gpiochip should be after pinctrl_enable is done */
|
||||
err = mtk_build_gpiochip(hw, pdev->dev.of_node);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to add gpio_chip\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, hw);
|
||||
|
||||
return 0;
|
||||
}
|
51
drivers/pinctrl/mediatek/pinctrl-moore.h
Normal file
51
drivers/pinctrl/mediatek/pinctrl-moore.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2017-2018 MediaTek Inc.
|
||||
*
|
||||
* Author: Sean Wang <sean.wang@mediatek.com>
|
||||
*
|
||||
*/
|
||||
#ifndef __PINCTRL_MOORE_H
|
||||
#define __PINCTRL_MOORE_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
|
||||
#include "../core.h"
|
||||
#include "../pinconf.h"
|
||||
#include "../pinmux.h"
|
||||
#include "mtk-eint.h"
|
||||
#include "pinctrl-mtk-common-v2.h"
|
||||
|
||||
#define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), }
|
||||
|
||||
#define MTK_PIN(_number, _name, _eint_m, _eint_n, _drv_n) { \
|
||||
.number = _number, \
|
||||
.name = _name, \
|
||||
.eint = { \
|
||||
.eint_m = _eint_m, \
|
||||
.eint_n = _eint_n, \
|
||||
}, \
|
||||
.drv_n = _drv_n, \
|
||||
.funcs = NULL, \
|
||||
}
|
||||
|
||||
#define PINCTRL_PIN_GROUP(name, id) \
|
||||
{ \
|
||||
name, \
|
||||
id##_pins, \
|
||||
ARRAY_SIZE(id##_pins), \
|
||||
id##_funcs, \
|
||||
}
|
||||
|
||||
int mtk_moore_pinctrl_probe(struct platform_device *pdev,
|
||||
const struct mtk_pin_soc *soc);
|
||||
|
||||
#endif /* __PINCTRL_MOORE_H */
|
1108
drivers/pinctrl/mediatek/pinctrl-mt6765.c
Normal file
1108
drivers/pinctrl/mediatek/pinctrl-mt6765.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1441
drivers/pinctrl/mediatek/pinctrl-mt7623.c
Normal file
1441
drivers/pinctrl/mediatek/pinctrl-mt7623.c
Normal file
File diff suppressed because it is too large
Load Diff
544
drivers/pinctrl/mediatek/pinctrl-mt8183.c
Normal file
544
drivers/pinctrl/mediatek/pinctrl-mt8183.c
Normal file
@ -0,0 +1,544 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2018 MediaTek Inc.
|
||||
*
|
||||
* Author: Zhiyong Tao <zhiyong.tao@mediatek.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pinctrl-mtk-mt8183.h"
|
||||
#include "pinctrl-paris.h"
|
||||
|
||||
/* MT8183 have multiple bases to program pin configuration listed as the below:
|
||||
* iocfg[0]:0x10005000, iocfg[1]:0x11F20000, iocfg[2]:0x11E80000,
|
||||
* iocfg[3]:0x11E70000, iocfg[4]:0x11E90000, iocfg[5]:0x11D30000,
|
||||
* iocfg[6]:0x11D20000, iocfg[7]:0x11C50000, iocfg[8]:0x11F30000.
|
||||
* _i_based could be used to indicate what base the pin should be mapped into.
|
||||
*/
|
||||
|
||||
#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, _x_bits) \
|
||||
PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \
|
||||
_x_bits, 32, 0)
|
||||
|
||||
#define PINS_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, _x_bits) \
|
||||
PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \
|
||||
_x_bits, 32, 1)
|
||||
|
||||
static const struct mtk_pin_field_calc mt8183_pin_mode_range[] = {
|
||||
PIN_FIELD(0, 192, 0x300, 0x10, 0, 4),
|
||||
};
|
||||
|
||||
static const struct mtk_pin_field_calc mt8183_pin_dir_range[] = {
|
||||
PIN_FIELD(0, 192, 0x0, 0x10, 0, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_pin_field_calc mt8183_pin_di_range[] = {
|
||||
PIN_FIELD(0, 192, 0x200, 0x10, 0, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_pin_field_calc mt8183_pin_do_range[] = {
|
||||
PIN_FIELD(0, 192, 0x100, 0x10, 0, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_pin_field_calc mt8183_pin_ies_range[] = {
|
||||
PINS_FIELD_BASE(0, 3, 6, 0x000, 0x10, 3, 1),
|
||||
PINS_FIELD_BASE(4, 7, 6, 0x000, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(8, 8, 6, 0x000, 0x10, 0, 1),
|
||||
PINS_FIELD_BASE(9, 10, 6, 0x000, 0x10, 12, 1),
|
||||
PIN_FIELD_BASE(11, 11, 1, 0x000, 0x10, 3, 1),
|
||||
PIN_FIELD_BASE(12, 12, 1, 0x000, 0x10, 7, 1),
|
||||
PINS_FIELD_BASE(13, 16, 2, 0x000, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(17, 20, 2, 0x000, 0x10, 3, 1),
|
||||
PINS_FIELD_BASE(21, 24, 2, 0x000, 0x10, 4, 1),
|
||||
PINS_FIELD_BASE(25, 28, 2, 0x000, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(29, 29, 2, 0x000, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(30, 30, 2, 0x000, 0x10, 7, 1),
|
||||
PINS_FIELD_BASE(31, 31, 2, 0x000, 0x10, 8, 1),
|
||||
PINS_FIELD_BASE(32, 34, 2, 0x000, 0x10, 7, 1),
|
||||
PINS_FIELD_BASE(35, 37, 3, 0x000, 0x10, 0, 1),
|
||||
PINS_FIELD_BASE(38, 40, 3, 0x000, 0x10, 1, 1),
|
||||
PINS_FIELD_BASE(41, 42, 3, 0x000, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(43, 45, 3, 0x000, 0x10, 3, 1),
|
||||
PINS_FIELD_BASE(46, 47, 3, 0x000, 0x10, 4, 1),
|
||||
PINS_FIELD_BASE(48, 49, 3, 0x000, 0x10, 5, 1),
|
||||
PINS_FIELD_BASE(50, 51, 4, 0x000, 0x10, 0, 1),
|
||||
PINS_FIELD_BASE(52, 57, 4, 0x000, 0x10, 1, 1),
|
||||
PINS_FIELD_BASE(58, 60, 4, 0x000, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(61, 64, 5, 0x000, 0x10, 0, 1),
|
||||
PINS_FIELD_BASE(65, 66, 5, 0x000, 0x10, 1, 1),
|
||||
PINS_FIELD_BASE(67, 68, 5, 0x000, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(69, 71, 5, 0x000, 0x10, 3, 1),
|
||||
PINS_FIELD_BASE(72, 76, 5, 0x000, 0x10, 4, 1),
|
||||
PINS_FIELD_BASE(77, 80, 5, 0x000, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(81, 81, 5, 0x000, 0x10, 6, 1),
|
||||
PINS_FIELD_BASE(82, 83, 5, 0x000, 0x10, 7, 1),
|
||||
PIN_FIELD_BASE(84, 84, 5, 0x000, 0x10, 6, 1),
|
||||
PINS_FIELD_BASE(85, 88, 5, 0x000, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(89, 89, 6, 0x000, 0x10, 11, 1),
|
||||
PIN_FIELD_BASE(90, 90, 6, 0x000, 0x10, 1, 1),
|
||||
PINS_FIELD_BASE(91, 94, 6, 0x000, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(95, 96, 6, 0x000, 0x10, 6, 1),
|
||||
PINS_FIELD_BASE(97, 98, 6, 0x000, 0x10, 7, 1),
|
||||
PIN_FIELD_BASE(99, 99, 6, 0x000, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(100, 100, 6, 0x000, 0x10, 9, 1),
|
||||
PINS_FIELD_BASE(101, 102, 6, 0x000, 0x10, 10, 1),
|
||||
PINS_FIELD_BASE(103, 104, 6, 0x000, 0x10, 13, 1),
|
||||
PINS_FIELD_BASE(105, 106, 6, 0x000, 0x10, 14, 1),
|
||||
PIN_FIELD_BASE(107, 107, 7, 0x000, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(108, 108, 7, 0x000, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(109, 109, 7, 0x000, 0x10, 2, 1),
|
||||
PIN_FIELD_BASE(110, 110, 7, 0x000, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(111, 111, 7, 0x000, 0x10, 3, 1),
|
||||
PIN_FIELD_BASE(112, 112, 7, 0x000, 0x10, 2, 1),
|
||||
PIN_FIELD_BASE(113, 113, 7, 0x000, 0x10, 4, 1),
|
||||
PIN_FIELD_BASE(114, 114, 7, 0x000, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(115, 115, 7, 0x000, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(116, 116, 7, 0x000, 0x10, 7, 1),
|
||||
PIN_FIELD_BASE(117, 117, 7, 0x000, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(118, 118, 7, 0x000, 0x10, 9, 1),
|
||||
PIN_FIELD_BASE(119, 119, 7, 0x000, 0x10, 10, 1),
|
||||
PIN_FIELD_BASE(120, 120, 7, 0x000, 0x10, 11, 1),
|
||||
PIN_FIELD_BASE(121, 121, 7, 0x000, 0x10, 12, 1),
|
||||
PIN_FIELD_BASE(122, 122, 8, 0x000, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(123, 123, 8, 0x000, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(124, 124, 8, 0x000, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(125, 130, 8, 0x000, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(131, 131, 8, 0x000, 0x10, 3, 1),
|
||||
PIN_FIELD_BASE(132, 132, 8, 0x000, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(133, 133, 8, 0x000, 0x10, 4, 1),
|
||||
PIN_FIELD_BASE(134, 134, 1, 0x000, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(135, 135, 1, 0x000, 0x10, 1, 1),
|
||||
PINS_FIELD_BASE(136, 143, 1, 0x000, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(144, 147, 1, 0x000, 0x10, 4, 1),
|
||||
PIN_FIELD_BASE(148, 148, 1, 0x000, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(149, 149, 1, 0x000, 0x10, 6, 1),
|
||||
PINS_FIELD_BASE(150, 153, 1, 0x000, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(154, 154, 1, 0x000, 0x10, 9, 1),
|
||||
PINS_FIELD_BASE(155, 157, 1, 0x000, 0x10, 10, 1),
|
||||
PINS_FIELD_BASE(158, 160, 1, 0x000, 0x10, 8, 1),
|
||||
PINS_FIELD_BASE(161, 164, 2, 0x000, 0x10, 0, 1),
|
||||
PINS_FIELD_BASE(165, 166, 2, 0x000, 0x10, 1, 1),
|
||||
PINS_FIELD_BASE(167, 168, 4, 0x000, 0x10, 2, 1),
|
||||
PIN_FIELD_BASE(169, 169, 4, 0x000, 0x10, 3, 1),
|
||||
PINS_FIELD_BASE(170, 174, 4, 0x000, 0x10, 4, 1),
|
||||
PINS_FIELD_BASE(175, 176, 4, 0x000, 0x10, 3, 1),
|
||||
PINS_FIELD_BASE(177, 179, 6, 0x000, 0x10, 4, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_pin_field_calc mt8183_pin_smt_range[] = {
|
||||
PINS_FIELD_BASE(0, 3, 6, 0x010, 0x10, 3, 1),
|
||||
PINS_FIELD_BASE(4, 7, 6, 0x010, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(8, 8, 6, 0x010, 0x10, 0, 1),
|
||||
PINS_FIELD_BASE(9, 10, 6, 0x010, 0x10, 12, 1),
|
||||
PIN_FIELD_BASE(11, 11, 1, 0x010, 0x10, 3, 1),
|
||||
PIN_FIELD_BASE(12, 12, 1, 0x010, 0x10, 7, 1),
|
||||
PINS_FIELD_BASE(13, 16, 2, 0x010, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(17, 20, 2, 0x010, 0x10, 3, 1),
|
||||
PINS_FIELD_BASE(21, 24, 2, 0x010, 0x10, 4, 1),
|
||||
PINS_FIELD_BASE(25, 28, 2, 0x010, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(29, 29, 2, 0x010, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(30, 30, 2, 0x010, 0x10, 7, 1),
|
||||
PINS_FIELD_BASE(31, 31, 2, 0x010, 0x10, 8, 1),
|
||||
PINS_FIELD_BASE(32, 34, 2, 0x010, 0x10, 7, 1),
|
||||
PINS_FIELD_BASE(35, 37, 3, 0x010, 0x10, 0, 1),
|
||||
PINS_FIELD_BASE(38, 40, 3, 0x010, 0x10, 1, 1),
|
||||
PINS_FIELD_BASE(41, 42, 3, 0x010, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(43, 45, 3, 0x010, 0x10, 3, 1),
|
||||
PINS_FIELD_BASE(46, 47, 3, 0x010, 0x10, 4, 1),
|
||||
PINS_FIELD_BASE(48, 49, 3, 0x010, 0x10, 5, 1),
|
||||
PINS_FIELD_BASE(50, 51, 4, 0x010, 0x10, 0, 1),
|
||||
PINS_FIELD_BASE(52, 57, 4, 0x010, 0x10, 1, 1),
|
||||
PINS_FIELD_BASE(58, 60, 4, 0x010, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(61, 64, 5, 0x010, 0x10, 0, 1),
|
||||
PINS_FIELD_BASE(65, 66, 5, 0x010, 0x10, 1, 1),
|
||||
PINS_FIELD_BASE(67, 68, 5, 0x010, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(69, 71, 5, 0x010, 0x10, 3, 1),
|
||||
PINS_FIELD_BASE(72, 76, 5, 0x010, 0x10, 4, 1),
|
||||
PINS_FIELD_BASE(77, 80, 5, 0x010, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(81, 81, 5, 0x010, 0x10, 6, 1),
|
||||
PINS_FIELD_BASE(82, 83, 5, 0x010, 0x10, 7, 1),
|
||||
PIN_FIELD_BASE(84, 84, 5, 0x010, 0x10, 6, 1),
|
||||
PINS_FIELD_BASE(85, 88, 5, 0x010, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(89, 89, 6, 0x010, 0x10, 11, 1),
|
||||
PIN_FIELD_BASE(90, 90, 6, 0x010, 0x10, 1, 1),
|
||||
PINS_FIELD_BASE(91, 94, 6, 0x010, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(95, 96, 6, 0x010, 0x10, 6, 1),
|
||||
PINS_FIELD_BASE(97, 98, 6, 0x010, 0x10, 7, 1),
|
||||
PIN_FIELD_BASE(99, 99, 6, 0x010, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(100, 100, 6, 0x010, 0x10, 9, 1),
|
||||
PINS_FIELD_BASE(101, 102, 6, 0x010, 0x10, 10, 1),
|
||||
PINS_FIELD_BASE(103, 104, 6, 0x010, 0x10, 13, 1),
|
||||
PINS_FIELD_BASE(105, 106, 6, 0x010, 0x10, 14, 1),
|
||||
PIN_FIELD_BASE(107, 107, 7, 0x010, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(108, 108, 7, 0x010, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(109, 109, 7, 0x010, 0x10, 2, 1),
|
||||
PIN_FIELD_BASE(110, 110, 7, 0x010, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(111, 111, 7, 0x010, 0x10, 3, 1),
|
||||
PIN_FIELD_BASE(112, 112, 7, 0x010, 0x10, 2, 1),
|
||||
PIN_FIELD_BASE(113, 113, 7, 0x010, 0x10, 4, 1),
|
||||
PIN_FIELD_BASE(114, 114, 7, 0x010, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(115, 115, 7, 0x010, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(116, 116, 7, 0x010, 0x10, 7, 1),
|
||||
PIN_FIELD_BASE(117, 117, 7, 0x010, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(118, 118, 7, 0x010, 0x10, 9, 1),
|
||||
PIN_FIELD_BASE(119, 119, 7, 0x010, 0x10, 10, 1),
|
||||
PIN_FIELD_BASE(120, 120, 7, 0x010, 0x10, 11, 1),
|
||||
PIN_FIELD_BASE(121, 121, 7, 0x010, 0x10, 12, 1),
|
||||
PIN_FIELD_BASE(122, 122, 8, 0x010, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(123, 123, 8, 0x010, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(124, 124, 8, 0x010, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(125, 130, 8, 0x010, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(131, 131, 8, 0x010, 0x10, 3, 1),
|
||||
PIN_FIELD_BASE(132, 132, 8, 0x010, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(133, 133, 8, 0x010, 0x10, 4, 1),
|
||||
PIN_FIELD_BASE(134, 134, 1, 0x010, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(135, 135, 1, 0x010, 0x10, 1, 1),
|
||||
PINS_FIELD_BASE(136, 143, 1, 0x010, 0x10, 2, 1),
|
||||
PINS_FIELD_BASE(144, 147, 1, 0x010, 0x10, 4, 1),
|
||||
PIN_FIELD_BASE(148, 148, 1, 0x010, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(149, 149, 1, 0x010, 0x10, 6, 1),
|
||||
PINS_FIELD_BASE(150, 153, 1, 0x010, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(154, 154, 1, 0x010, 0x10, 9, 1),
|
||||
PINS_FIELD_BASE(155, 157, 1, 0x010, 0x10, 10, 1),
|
||||
PINS_FIELD_BASE(158, 160, 1, 0x010, 0x10, 8, 1),
|
||||
PINS_FIELD_BASE(161, 164, 2, 0x010, 0x10, 0, 1),
|
||||
PINS_FIELD_BASE(165, 166, 2, 0x010, 0x10, 1, 1),
|
||||
PINS_FIELD_BASE(167, 168, 4, 0x010, 0x10, 2, 1),
|
||||
PIN_FIELD_BASE(169, 169, 4, 0x010, 0x10, 3, 1),
|
||||
PINS_FIELD_BASE(170, 174, 4, 0x010, 0x10, 4, 1),
|
||||
PINS_FIELD_BASE(175, 176, 4, 0x010, 0x10, 3, 1),
|
||||
PINS_FIELD_BASE(177, 179, 6, 0x010, 0x10, 4, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_pin_field_calc mt8183_pin_pullen_range[] = {
|
||||
PIN_FIELD_BASE(0, 3, 6, 0x060, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(4, 7, 6, 0x060, 0x10, 11, 1),
|
||||
PIN_FIELD_BASE(8, 8, 6, 0x060, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(9, 10, 6, 0x060, 0x10, 26, 1),
|
||||
PIN_FIELD_BASE(11, 11, 1, 0x060, 0x10, 10, 1),
|
||||
PIN_FIELD_BASE(12, 12, 1, 0x060, 0x10, 17, 1),
|
||||
PIN_FIELD_BASE(13, 28, 2, 0x060, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(43, 49, 3, 0x060, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(50, 60, 4, 0x060, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(61, 88, 5, 0x060, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(89, 89, 6, 0x060, 0x10, 24, 1),
|
||||
PIN_FIELD_BASE(90, 90, 6, 0x060, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(95, 95, 6, 0x060, 0x10, 15, 1),
|
||||
PIN_FIELD_BASE(96, 102, 6, 0x060, 0x10, 17, 1),
|
||||
PIN_FIELD_BASE(103, 106, 6, 0x060, 0x10, 28, 1),
|
||||
PIN_FIELD_BASE(107, 121, 7, 0x060, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(134, 143, 1, 0x060, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(144, 149, 1, 0x060, 0x10, 11, 1),
|
||||
PIN_FIELD_BASE(150, 160, 1, 0x060, 0x10, 18, 1),
|
||||
PIN_FIELD_BASE(161, 166, 2, 0x060, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(167, 176, 4, 0x060, 0x10, 11, 1),
|
||||
PIN_FIELD_BASE(177, 177, 6, 0x060, 0x10, 10, 1),
|
||||
PIN_FIELD_BASE(178, 178, 6, 0x060, 0x10, 16, 1),
|
||||
PIN_FIELD_BASE(179, 179, 6, 0x060, 0x10, 25, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_pin_field_calc mt8183_pin_pullsel_range[] = {
|
||||
PIN_FIELD_BASE(0, 3, 6, 0x080, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(4, 7, 6, 0x080, 0x10, 11, 1),
|
||||
PIN_FIELD_BASE(8, 8, 6, 0x080, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(9, 10, 6, 0x080, 0x10, 26, 1),
|
||||
PIN_FIELD_BASE(11, 11, 1, 0x080, 0x10, 10, 1),
|
||||
PIN_FIELD_BASE(12, 12, 1, 0x080, 0x10, 17, 1),
|
||||
PIN_FIELD_BASE(13, 28, 2, 0x080, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(43, 49, 3, 0x080, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(50, 60, 4, 0x080, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(61, 88, 5, 0x080, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(89, 89, 6, 0x080, 0x10, 24, 1),
|
||||
PIN_FIELD_BASE(90, 90, 6, 0x080, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(95, 95, 6, 0x080, 0x10, 15, 1),
|
||||
PIN_FIELD_BASE(96, 102, 6, 0x080, 0x10, 17, 1),
|
||||
PIN_FIELD_BASE(103, 106, 6, 0x080, 0x10, 28, 1),
|
||||
PIN_FIELD_BASE(107, 121, 7, 0x080, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(134, 143, 1, 0x080, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(144, 149, 1, 0x080, 0x10, 11, 1),
|
||||
PIN_FIELD_BASE(150, 160, 1, 0x080, 0x10, 18, 1),
|
||||
PIN_FIELD_BASE(161, 166, 2, 0x080, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(167, 176, 4, 0x080, 0x10, 11, 1),
|
||||
PIN_FIELD_BASE(177, 177, 6, 0x080, 0x10, 10, 1),
|
||||
PIN_FIELD_BASE(178, 178, 6, 0x080, 0x10, 16, 1),
|
||||
PIN_FIELD_BASE(179, 179, 6, 0x080, 0x10, 25, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_pin_field_calc mt8183_pin_drv_range[] = {
|
||||
PINS_FIELD_BASE(0, 3, 6, 0x0A0, 0x10, 12, 3),
|
||||
PINS_FIELD_BASE(4, 7, 6, 0x0A0, 0x10, 20, 3),
|
||||
PIN_FIELD_BASE(8, 8, 6, 0x0A0, 0x10, 0, 3),
|
||||
PINS_FIELD_BASE(9, 10, 6, 0x0B0, 0x10, 16, 3),
|
||||
PIN_FIELD_BASE(11, 11, 1, 0x0A0, 0x10, 12, 3),
|
||||
PIN_FIELD_BASE(12, 12, 1, 0x0A0, 0x10, 28, 3),
|
||||
PINS_FIELD_BASE(13, 16, 2, 0x0A0, 0x10, 8, 3),
|
||||
PINS_FIELD_BASE(17, 20, 2, 0x0A0, 0x10, 12, 3),
|
||||
PINS_FIELD_BASE(21, 24, 2, 0x0A0, 0x10, 16, 3),
|
||||
PINS_FIELD_BASE(25, 28, 2, 0x0A0, 0x10, 20, 3),
|
||||
PIN_FIELD_BASE(29, 29, 2, 0x0A0, 0x10, 24, 3),
|
||||
PIN_FIELD_BASE(30, 30, 2, 0x0A0, 0x10, 28, 3),
|
||||
PINS_FIELD_BASE(31, 31, 2, 0x0B0, 0x10, 0, 3),
|
||||
PINS_FIELD_BASE(32, 34, 2, 0x0A0, 0x10, 28, 3),
|
||||
PINS_FIELD_BASE(35, 37, 3, 0x0A0, 0x10, 0, 3),
|
||||
PINS_FIELD_BASE(38, 40, 3, 0x0A0, 0x10, 4, 3),
|
||||
PINS_FIELD_BASE(41, 42, 3, 0x0A0, 0x10, 8, 3),
|
||||
PINS_FIELD_BASE(43, 45, 3, 0x0A0, 0x10, 12, 3),
|
||||
PINS_FIELD_BASE(46, 47, 3, 0x0A0, 0x10, 16, 3),
|
||||
PINS_FIELD_BASE(48, 49, 3, 0x0A0, 0x10, 20, 3),
|
||||
PINS_FIELD_BASE(50, 51, 4, 0x0A0, 0x10, 0, 3),
|
||||
PINS_FIELD_BASE(52, 57, 4, 0x0A0, 0x10, 4, 3),
|
||||
PINS_FIELD_BASE(58, 60, 4, 0x0A0, 0x10, 8, 3),
|
||||
PINS_FIELD_BASE(61, 64, 5, 0x0A0, 0x10, 0, 3),
|
||||
PINS_FIELD_BASE(65, 66, 5, 0x0A0, 0x10, 4, 3),
|
||||
PINS_FIELD_BASE(67, 68, 5, 0x0A0, 0x10, 8, 3),
|
||||
PINS_FIELD_BASE(69, 71, 5, 0x0A0, 0x10, 12, 3),
|
||||
PINS_FIELD_BASE(72, 76, 5, 0x0A0, 0x10, 16, 3),
|
||||
PINS_FIELD_BASE(77, 80, 5, 0x0A0, 0x10, 20, 3),
|
||||
PIN_FIELD_BASE(81, 81, 5, 0x0A0, 0x10, 24, 3),
|
||||
PINS_FIELD_BASE(82, 83, 5, 0x0A0, 0x10, 28, 3),
|
||||
PIN_FIELD_BASE(84, 84, 5, 0x0A0, 0x10, 24, 3),
|
||||
PINS_FIELD_BASE(85, 88, 5, 0x0B0, 0x10, 0, 3),
|
||||
PIN_FIELD_BASE(89, 89, 6, 0x0B0, 0x10, 12, 3),
|
||||
PIN_FIELD_BASE(90, 90, 6, 0x0A0, 0x10, 4, 3),
|
||||
PINS_FIELD_BASE(91, 94, 6, 0x0A0, 0x10, 8, 3),
|
||||
PINS_FIELD_BASE(95, 96, 6, 0x0A0, 0x10, 24, 3),
|
||||
PINS_FIELD_BASE(97, 98, 6, 0x0A0, 0x10, 28, 3),
|
||||
PIN_FIELD_BASE(99, 99, 6, 0x0B0, 0x10, 0, 3),
|
||||
PIN_FIELD_BASE(100, 100, 6, 0x0B0, 0x10, 4, 3),
|
||||
PINS_FIELD_BASE(101, 102, 6, 0x0B0, 0x10, 8, 3),
|
||||
PINS_FIELD_BASE(103, 104, 6, 0x0B0, 0x10, 20, 3),
|
||||
PINS_FIELD_BASE(105, 106, 6, 0x0B0, 0x10, 24, 3),
|
||||
PIN_FIELD_BASE(107, 107, 7, 0x0A0, 0x10, 0, 3),
|
||||
PIN_FIELD_BASE(108, 108, 7, 0x0A0, 0x10, 4, 3),
|
||||
PIN_FIELD_BASE(109, 109, 7, 0x0A0, 0x10, 8, 3),
|
||||
PIN_FIELD_BASE(110, 110, 7, 0x0A0, 0x10, 0, 3),
|
||||
PIN_FIELD_BASE(111, 111, 7, 0x0A0, 0x10, 4, 3),
|
||||
PIN_FIELD_BASE(112, 112, 7, 0x0A0, 0x10, 8, 3),
|
||||
PIN_FIELD_BASE(113, 113, 7, 0x0A0, 0x10, 16, 3),
|
||||
PIN_FIELD_BASE(114, 114, 7, 0x0A0, 0x10, 20, 3),
|
||||
PIN_FIELD_BASE(115, 115, 7, 0x0A0, 0x10, 24, 3),
|
||||
PIN_FIELD_BASE(116, 116, 7, 0x0A0, 0x10, 28, 3),
|
||||
PIN_FIELD_BASE(117, 117, 7, 0x0B0, 0x10, 0, 3),
|
||||
PIN_FIELD_BASE(118, 118, 7, 0x0B0, 0x10, 4, 3),
|
||||
PIN_FIELD_BASE(119, 119, 7, 0x0B0, 0x10, 8, 3),
|
||||
PIN_FIELD_BASE(120, 120, 7, 0x0B0, 0x10, 12, 3),
|
||||
PIN_FIELD_BASE(121, 121, 7, 0x0B0, 0x10, 16, 3),
|
||||
PIN_FIELD_BASE(122, 122, 8, 0x0A0, 0x10, 0, 3),
|
||||
PIN_FIELD_BASE(123, 123, 8, 0x0A0, 0x10, 4, 3),
|
||||
PIN_FIELD_BASE(124, 124, 8, 0x0A0, 0x10, 8, 3),
|
||||
PINS_FIELD_BASE(125, 130, 8, 0x0A0, 0x10, 4, 3),
|
||||
PIN_FIELD_BASE(131, 131, 8, 0x0A0, 0x10, 12, 3),
|
||||
PIN_FIELD_BASE(132, 132, 8, 0x0A0, 0x10, 4, 3),
|
||||
PIN_FIELD_BASE(133, 133, 8, 0x0A0, 0x10, 16, 3),
|
||||
PIN_FIELD_BASE(134, 134, 1, 0x0A0, 0x10, 0, 3),
|
||||
PIN_FIELD_BASE(135, 135, 1, 0x0A0, 0x10, 4, 3),
|
||||
PINS_FIELD_BASE(136, 143, 1, 0x0A0, 0x10, 8, 3),
|
||||
PINS_FIELD_BASE(144, 147, 1, 0x0A0, 0x10, 16, 3),
|
||||
PIN_FIELD_BASE(148, 148, 1, 0x0A0, 0x10, 20, 3),
|
||||
PIN_FIELD_BASE(149, 149, 1, 0x0A0, 0x10, 24, 3),
|
||||
PINS_FIELD_BASE(150, 153, 1, 0x0B0, 0x10, 0, 3),
|
||||
PIN_FIELD_BASE(154, 154, 1, 0x0B0, 0x10, 4, 3),
|
||||
PINS_FIELD_BASE(155, 157, 1, 0x0B0, 0x10, 8, 3),
|
||||
PINS_FIELD_BASE(158, 160, 1, 0x0B0, 0x10, 0, 3),
|
||||
PINS_FIELD_BASE(161, 164, 2, 0x0A0, 0x10, 0, 3),
|
||||
PINS_FIELD_BASE(165, 166, 2, 0x0A0, 0x10, 4, 3),
|
||||
PINS_FIELD_BASE(167, 168, 4, 0x0A0, 0x10, 8, 3),
|
||||
PIN_FIELD_BASE(169, 169, 4, 0x0A0, 0x10, 12, 3),
|
||||
PINS_FIELD_BASE(170, 174, 4, 0x0A0, 0x10, 16, 3),
|
||||
PINS_FIELD_BASE(175, 176, 4, 0x0A0, 0x10, 12, 3),
|
||||
PINS_FIELD_BASE(177, 179, 6, 0x0A0, 0x10, 16, 3),
|
||||
};
|
||||
|
||||
static const struct mtk_pin_field_calc mt8183_pin_pupd_range[] = {
|
||||
PIN_FIELD_BASE(29, 29, 2, 0x0C0, 0x10, 2, 1),
|
||||
PIN_FIELD_BASE(30, 30, 2, 0x0C0, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(31, 31, 2, 0x0C0, 0x10, 10, 1),
|
||||
PIN_FIELD_BASE(32, 32, 2, 0x0C0, 0x10, 14, 1),
|
||||
PIN_FIELD_BASE(33, 33, 2, 0x0C0, 0x10, 18, 1),
|
||||
PIN_FIELD_BASE(34, 34, 2, 0x0C0, 0x10, 22, 1),
|
||||
PIN_FIELD_BASE(35, 35, 3, 0x0C0, 0x10, 2, 1),
|
||||
PIN_FIELD_BASE(36, 36, 3, 0x0C0, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(37, 37, 3, 0x0C0, 0x10, 10, 1),
|
||||
PIN_FIELD_BASE(38, 38, 3, 0x0C0, 0x10, 14, 1),
|
||||
PIN_FIELD_BASE(39, 39, 3, 0x0C0, 0x10, 18, 1),
|
||||
PIN_FIELD_BASE(40, 40, 3, 0x0C0, 0x10, 22, 1),
|
||||
PIN_FIELD_BASE(41, 41, 3, 0x0C0, 0x10, 26, 1),
|
||||
PIN_FIELD_BASE(42, 42, 3, 0x0C0, 0x10, 30, 1),
|
||||
PIN_FIELD_BASE(91, 91, 6, 0x0C0, 0x10, 2, 1),
|
||||
PIN_FIELD_BASE(92, 92, 6, 0x0C0, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(93, 93, 6, 0x0C0, 0x10, 10, 1),
|
||||
PIN_FIELD_BASE(94, 94, 6, 0x0C0, 0x10, 14, 1),
|
||||
PIN_FIELD_BASE(122, 122, 8, 0x0C0, 0x10, 2, 1),
|
||||
PIN_FIELD_BASE(123, 123, 8, 0x0C0, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(124, 124, 8, 0x0C0, 0x10, 10, 1),
|
||||
PIN_FIELD_BASE(125, 125, 8, 0x0C0, 0x10, 14, 1),
|
||||
PIN_FIELD_BASE(126, 126, 8, 0x0C0, 0x10, 18, 1),
|
||||
PIN_FIELD_BASE(127, 127, 8, 0x0C0, 0x10, 22, 1),
|
||||
PIN_FIELD_BASE(128, 128, 8, 0x0C0, 0x10, 26, 1),
|
||||
PIN_FIELD_BASE(129, 129, 8, 0x0C0, 0x10, 30, 1),
|
||||
PIN_FIELD_BASE(130, 130, 8, 0x0D0, 0x10, 2, 1),
|
||||
PIN_FIELD_BASE(131, 131, 8, 0x0D0, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(132, 132, 8, 0x0D0, 0x10, 10, 1),
|
||||
PIN_FIELD_BASE(133, 133, 8, 0x0D0, 0x10, 14, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_pin_field_calc mt8183_pin_r0_range[] = {
|
||||
PIN_FIELD_BASE(29, 29, 2, 0x0C0, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(30, 30, 2, 0x0C0, 0x10, 4, 1),
|
||||
PIN_FIELD_BASE(31, 31, 2, 0x0C0, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(32, 32, 2, 0x0C0, 0x10, 12, 1),
|
||||
PIN_FIELD_BASE(33, 33, 2, 0x0C0, 0x10, 16, 1),
|
||||
PIN_FIELD_BASE(34, 34, 2, 0x0C0, 0x10, 20, 1),
|
||||
PIN_FIELD_BASE(35, 35, 3, 0x0C0, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(36, 36, 3, 0x0C0, 0x10, 4, 1),
|
||||
PIN_FIELD_BASE(37, 37, 3, 0x0C0, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(38, 38, 3, 0x0C0, 0x10, 12, 1),
|
||||
PIN_FIELD_BASE(39, 39, 3, 0x0C0, 0x10, 16, 1),
|
||||
PIN_FIELD_BASE(40, 40, 3, 0x0C0, 0x10, 20, 1),
|
||||
PIN_FIELD_BASE(41, 41, 3, 0x0C0, 0x10, 24, 1),
|
||||
PIN_FIELD_BASE(42, 42, 3, 0x0C0, 0x10, 28, 1),
|
||||
PIN_FIELD_BASE(48, 48, 3, 0x0F0, 0x10, 18, 1),
|
||||
PIN_FIELD_BASE(49, 49, 3, 0x0F0, 0x10, 13, 1),
|
||||
PIN_FIELD_BASE(50, 50, 4, 0x0F0, 0x10, 10, 1),
|
||||
PIN_FIELD_BASE(51, 51, 4, 0x0F0, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(81, 81, 5, 0x0F0, 0x10, 7, 1),
|
||||
PIN_FIELD_BASE(82, 82, 5, 0x0F0, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(83, 83, 5, 0x0F0, 0x10, 15, 1),
|
||||
PIN_FIELD_BASE(84, 84, 5, 0x0F0, 0x10, 17, 1),
|
||||
PIN_FIELD_BASE(91, 91, 6, 0x0C0, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(92, 92, 6, 0x0C0, 0x10, 4, 1),
|
||||
PIN_FIELD_BASE(93, 93, 6, 0x0C0, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(94, 94, 6, 0x0C0, 0x10, 12, 1),
|
||||
PIN_FIELD_BASE(103, 103, 6, 0x0F0, 0x10, 20, 1),
|
||||
PIN_FIELD_BASE(104, 104, 6, 0x0F0, 0x10, 10, 1),
|
||||
PIN_FIELD_BASE(105, 105, 6, 0x0F0, 0x10, 22, 1),
|
||||
PIN_FIELD_BASE(106, 106, 6, 0x0F0, 0x10, 12, 1),
|
||||
PIN_FIELD_BASE(122, 122, 8, 0x0C0, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(123, 123, 8, 0x0C0, 0x10, 4, 1),
|
||||
PIN_FIELD_BASE(124, 124, 8, 0x0C0, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(125, 125, 8, 0x0C0, 0x10, 12, 1),
|
||||
PIN_FIELD_BASE(126, 126, 8, 0x0C0, 0x10, 16, 1),
|
||||
PIN_FIELD_BASE(127, 127, 8, 0x0C0, 0x10, 20, 1),
|
||||
PIN_FIELD_BASE(128, 128, 8, 0x0C0, 0x10, 24, 1),
|
||||
PIN_FIELD_BASE(129, 129, 8, 0x0C0, 0x10, 28, 1),
|
||||
PIN_FIELD_BASE(130, 130, 8, 0x0D0, 0x10, 0, 1),
|
||||
PIN_FIELD_BASE(131, 131, 8, 0x0D0, 0x10, 4, 1),
|
||||
PIN_FIELD_BASE(132, 132, 8, 0x0D0, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(133, 133, 8, 0x0D0, 0x10, 12, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_pin_field_calc mt8183_pin_r1_range[] = {
|
||||
PIN_FIELD_BASE(29, 29, 2, 0x0C0, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(30, 30, 2, 0x0C0, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(31, 31, 2, 0x0C0, 0x10, 9, 1),
|
||||
PIN_FIELD_BASE(32, 32, 2, 0x0C0, 0x10, 13, 1),
|
||||
PIN_FIELD_BASE(33, 33, 2, 0x0C0, 0x10, 17, 1),
|
||||
PIN_FIELD_BASE(34, 34, 2, 0x0C0, 0x10, 21, 1),
|
||||
PIN_FIELD_BASE(35, 35, 3, 0x0C0, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(36, 36, 3, 0x0C0, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(37, 37, 3, 0x0C0, 0x10, 9, 1),
|
||||
PIN_FIELD_BASE(38, 38, 3, 0x0C0, 0x10, 13, 1),
|
||||
PIN_FIELD_BASE(39, 39, 3, 0x0C0, 0x10, 17, 1),
|
||||
PIN_FIELD_BASE(40, 40, 3, 0x0C0, 0x10, 21, 1),
|
||||
PIN_FIELD_BASE(41, 41, 3, 0x0C0, 0x10, 25, 1),
|
||||
PIN_FIELD_BASE(42, 42, 3, 0x0C0, 0x10, 29, 1),
|
||||
PIN_FIELD_BASE(48, 48, 3, 0x0F0, 0x10, 19, 1),
|
||||
PIN_FIELD_BASE(49, 49, 3, 0x0F0, 0x10, 14, 1),
|
||||
PIN_FIELD_BASE(50, 50, 4, 0x0F0, 0x10, 11, 1),
|
||||
PIN_FIELD_BASE(51, 51, 4, 0x0F0, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(81, 81, 5, 0x0F0, 0x10, 8, 1),
|
||||
PIN_FIELD_BASE(82, 82, 5, 0x0F0, 0x10, 6, 1),
|
||||
PIN_FIELD_BASE(83, 83, 5, 0x0F0, 0x10, 16, 1),
|
||||
PIN_FIELD_BASE(84, 84, 5, 0x0F0, 0x10, 18, 1),
|
||||
PIN_FIELD_BASE(91, 91, 6, 0x0C0, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(92, 92, 6, 0x0C0, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(93, 93, 6, 0x0C0, 0x10, 9, 1),
|
||||
PIN_FIELD_BASE(94, 94, 6, 0x0C0, 0x10, 13, 1),
|
||||
PIN_FIELD_BASE(103, 103, 6, 0x0F0, 0x10, 21, 1),
|
||||
PIN_FIELD_BASE(104, 104, 6, 0x0F0, 0x10, 11, 1),
|
||||
PIN_FIELD_BASE(105, 105, 6, 0x0F0, 0x10, 23, 1),
|
||||
PIN_FIELD_BASE(106, 106, 6, 0x0F0, 0x10, 13, 1),
|
||||
PIN_FIELD_BASE(122, 122, 8, 0x0C0, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(123, 123, 8, 0x0C0, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(124, 124, 8, 0x0C0, 0x10, 9, 1),
|
||||
PIN_FIELD_BASE(125, 125, 8, 0x0C0, 0x10, 13, 1),
|
||||
PIN_FIELD_BASE(126, 126, 8, 0x0C0, 0x10, 17, 1),
|
||||
PIN_FIELD_BASE(127, 127, 8, 0x0C0, 0x10, 21, 1),
|
||||
PIN_FIELD_BASE(128, 128, 8, 0x0C0, 0x10, 25, 1),
|
||||
PIN_FIELD_BASE(129, 129, 8, 0x0C0, 0x10, 29, 1),
|
||||
PIN_FIELD_BASE(130, 130, 8, 0x0D0, 0x10, 1, 1),
|
||||
PIN_FIELD_BASE(131, 131, 8, 0x0D0, 0x10, 5, 1),
|
||||
PIN_FIELD_BASE(132, 132, 8, 0x0D0, 0x10, 9, 1),
|
||||
PIN_FIELD_BASE(133, 133, 8, 0x0D0, 0x10, 13, 1),
|
||||
};
|
||||
|
||||
static const struct mtk_pin_reg_calc mt8183_reg_cals[PINCTRL_PIN_REG_MAX] = {
|
||||
[PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt8183_pin_mode_range),
|
||||
[PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt8183_pin_dir_range),
|
||||
[PINCTRL_PIN_REG_DI] = MTK_RANGE(mt8183_pin_di_range),
|
||||
[PINCTRL_PIN_REG_DO] = MTK_RANGE(mt8183_pin_do_range),
|
||||
[PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt8183_pin_smt_range),
|
||||
[PINCTRL_PIN_REG_IES] = MTK_RANGE(mt8183_pin_ies_range),
|
||||
[PINCTRL_PIN_REG_PULLEN] = MTK_RANGE(mt8183_pin_pullen_range),
|
||||
[PINCTRL_PIN_REG_PULLSEL] = MTK_RANGE(mt8183_pin_pullsel_range),
|
||||
[PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt8183_pin_drv_range),
|
||||
[PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt8183_pin_pupd_range),
|
||||
[PINCTRL_PIN_REG_R0] = MTK_RANGE(mt8183_pin_r0_range),
|
||||
[PINCTRL_PIN_REG_R1] = MTK_RANGE(mt8183_pin_r1_range),
|
||||
};
|
||||
|
||||
static const char * const mt8183_pinctrl_register_base_names[] = {
|
||||
"iocfg0", "iocfg1", "iocfg2", "iocfg3", "iocfg4", "iocfg5",
|
||||
"iocfg6", "iocfg7", "iocfg8",
|
||||
};
|
||||
|
||||
static const struct mtk_eint_hw mt8183_eint_hw = {
|
||||
.port_mask = 7,
|
||||
.ports = 6,
|
||||
.ap_num = 212,
|
||||
.db_cnt = 13,
|
||||
};
|
||||
|
||||
static const struct mtk_pin_soc mt8183_data = {
|
||||
.reg_cal = mt8183_reg_cals,
|
||||
.pins = mtk_pins_mt8183,
|
||||
.npins = ARRAY_SIZE(mtk_pins_mt8183),
|
||||
.ngrps = ARRAY_SIZE(mtk_pins_mt8183),
|
||||
.eint_hw = &mt8183_eint_hw,
|
||||
.gpio_m = 0,
|
||||
.ies_present = true,
|
||||
.base_names = mt8183_pinctrl_register_base_names,
|
||||
.nbase_names = ARRAY_SIZE(mt8183_pinctrl_register_base_names),
|
||||
.bias_disable_set = mtk_pinconf_bias_disable_set_rev1,
|
||||
.bias_disable_get = mtk_pinconf_bias_disable_get_rev1,
|
||||
.bias_set = mtk_pinconf_bias_set_rev1,
|
||||
.bias_get = mtk_pinconf_bias_get_rev1,
|
||||
.drive_set = mtk_pinconf_drive_set_rev1,
|
||||
.drive_get = mtk_pinconf_drive_get_rev1,
|
||||
.adv_pull_get = mtk_pinconf_adv_pull_get,
|
||||
.adv_pull_set = mtk_pinconf_adv_pull_set,
|
||||
};
|
||||
|
||||
static const struct of_device_id mt8183_pinctrl_of_match[] = {
|
||||
{ .compatible = "mediatek,mt8183-pinctrl", },
|
||||
{ }
|
||||
};
|
||||
|
||||
static int mt8183_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
return mtk_paris_pinctrl_probe(pdev, &mt8183_data);
|
||||
}
|
||||
|
||||
static struct platform_driver mt8183_pinctrl_driver = {
|
||||
.driver = {
|
||||
.name = "mt8183-pinctrl",
|
||||
.of_match_table = mt8183_pinctrl_of_match,
|
||||
},
|
||||
.probe = mt8183_pinctrl_probe,
|
||||
};
|
||||
|
||||
static int __init mt8183_pinctrl_init(void)
|
||||
{
|
||||
return platform_driver_register(&mt8183_pinctrl_driver);
|
||||
}
|
||||
arch_initcall(mt8183_pinctrl_init);
|
670
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
Normal file
670
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
Normal file
@ -0,0 +1,670 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2018 MediaTek Inc.
|
||||
*
|
||||
* Author: Sean Wang <sean.wang@mediatek.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
||||
#include "mtk-eint.h"
|
||||
#include "pinctrl-mtk-common-v2.h"
|
||||
|
||||
/**
|
||||
* struct mtk_drive_desc - the structure that holds the information
|
||||
* of the driving current
|
||||
* @min: the minimum current of this group
|
||||
* @max: the maximum current of this group
|
||||
* @step: the step current of this group
|
||||
* @scal: the weight factor
|
||||
*
|
||||
* formula: output = ((input) / step - 1) * scal
|
||||
*/
|
||||
struct mtk_drive_desc {
|
||||
u8 min;
|
||||
u8 max;
|
||||
u8 step;
|
||||
u8 scal;
|
||||
};
|
||||
|
||||
/* The groups of drive strength */
|
||||
static const struct mtk_drive_desc mtk_drive[] = {
|
||||
[DRV_GRP0] = { 4, 16, 4, 1 },
|
||||
[DRV_GRP1] = { 4, 16, 4, 2 },
|
||||
[DRV_GRP2] = { 2, 8, 2, 1 },
|
||||
[DRV_GRP3] = { 2, 8, 2, 2 },
|
||||
[DRV_GRP4] = { 2, 16, 2, 1 },
|
||||
};
|
||||
|
||||
static void mtk_w32(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 val)
|
||||
{
|
||||
writel_relaxed(val, pctl->base[i] + reg);
|
||||
}
|
||||
|
||||
static u32 mtk_r32(struct mtk_pinctrl *pctl, u8 i, u32 reg)
|
||||
{
|
||||
return readl_relaxed(pctl->base[i] + reg);
|
||||
}
|
||||
|
||||
void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = mtk_r32(pctl, i, reg);
|
||||
val &= ~mask;
|
||||
val |= set;
|
||||
mtk_w32(pctl, i, reg, val);
|
||||
}
|
||||
|
||||
static int mtk_hw_pin_field_lookup(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc,
|
||||
int field, struct mtk_pin_field *pfd)
|
||||
{
|
||||
const struct mtk_pin_field_calc *c, *e;
|
||||
const struct mtk_pin_reg_calc *rc;
|
||||
u32 bits;
|
||||
|
||||
if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) {
|
||||
rc = &hw->soc->reg_cal[field];
|
||||
} else {
|
||||
dev_dbg(hw->dev,
|
||||
"Not support field %d for pin %d (%s)\n",
|
||||
field, desc->number, desc->name);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
c = rc->range;
|
||||
e = c + rc->nranges;
|
||||
|
||||
while (c < e) {
|
||||
if (desc->number >= c->s_pin && desc->number <= c->e_pin)
|
||||
break;
|
||||
c++;
|
||||
}
|
||||
|
||||
if (c >= e) {
|
||||
dev_dbg(hw->dev, "Not support field %d for pin = %d (%s)\n",
|
||||
field, desc->number, desc->name);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
if (c->i_base > hw->nbase - 1) {
|
||||
dev_err(hw->dev,
|
||||
"Invalid base for field %d for pin = %d (%s)\n",
|
||||
field, desc->number, desc->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Calculated bits as the overall offset the pin is located at,
|
||||
* if c->fixed is held, that determines the all the pins in the
|
||||
* range use the same field with the s_pin.
|
||||
*/
|
||||
bits = c->fixed ? c->s_bit : c->s_bit +
|
||||
(desc->number - c->s_pin) * (c->x_bits);
|
||||
|
||||
/* Fill pfd from bits. For example 32-bit register applied is assumed
|
||||
* when c->sz_reg is equal to 32.
|
||||
*/
|
||||
pfd->index = c->i_base;
|
||||
pfd->offset = c->s_addr + c->x_addrs * (bits / c->sz_reg);
|
||||
pfd->bitpos = bits % c->sz_reg;
|
||||
pfd->mask = (1 << c->x_bits) - 1;
|
||||
|
||||
/* pfd->next is used for indicating that bit wrapping-around happens
|
||||
* which requires the manipulation for bit 0 starting in the next
|
||||
* register to form the complete field read/write.
|
||||
*/
|
||||
pfd->next = pfd->bitpos + c->x_bits > c->sz_reg ? c->x_addrs : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_hw_pin_field_get(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc,
|
||||
int field, struct mtk_pin_field *pfd)
|
||||
{
|
||||
if (field < 0 || field >= PINCTRL_PIN_REG_MAX) {
|
||||
dev_err(hw->dev, "Invalid Field %d\n", field);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return mtk_hw_pin_field_lookup(hw, desc, field, pfd);
|
||||
}
|
||||
|
||||
static void mtk_hw_bits_part(struct mtk_pin_field *pf, int *h, int *l)
|
||||
{
|
||||
*l = 32 - pf->bitpos;
|
||||
*h = get_count_order(pf->mask) - *l;
|
||||
}
|
||||
|
||||
static void mtk_hw_write_cross_field(struct mtk_pinctrl *hw,
|
||||
struct mtk_pin_field *pf, int value)
|
||||
{
|
||||
int nbits_l, nbits_h;
|
||||
|
||||
mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
|
||||
|
||||
mtk_rmw(hw, pf->index, pf->offset, pf->mask << pf->bitpos,
|
||||
(value & pf->mask) << pf->bitpos);
|
||||
|
||||
mtk_rmw(hw, pf->index, pf->offset + pf->next, BIT(nbits_h) - 1,
|
||||
(value & pf->mask) >> nbits_l);
|
||||
}
|
||||
|
||||
static void mtk_hw_read_cross_field(struct mtk_pinctrl *hw,
|
||||
struct mtk_pin_field *pf, int *value)
|
||||
{
|
||||
int nbits_l, nbits_h, h, l;
|
||||
|
||||
mtk_hw_bits_part(pf, &nbits_h, &nbits_l);
|
||||
|
||||
l = (mtk_r32(hw, pf->index, pf->offset)
|
||||
>> pf->bitpos) & (BIT(nbits_l) - 1);
|
||||
h = (mtk_r32(hw, pf->index, pf->offset + pf->next))
|
||||
& (BIT(nbits_h) - 1);
|
||||
|
||||
*value = (h << nbits_l) | l;
|
||||
}
|
||||
|
||||
int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
|
||||
int field, int value)
|
||||
{
|
||||
struct mtk_pin_field pf;
|
||||
int err;
|
||||
|
||||
err = mtk_hw_pin_field_get(hw, desc, field, &pf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!pf.next)
|
||||
mtk_rmw(hw, pf.index, pf.offset, pf.mask << pf.bitpos,
|
||||
(value & pf.mask) << pf.bitpos);
|
||||
else
|
||||
mtk_hw_write_cross_field(hw, &pf, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
|
||||
int field, int *value)
|
||||
{
|
||||
struct mtk_pin_field pf;
|
||||
int err;
|
||||
|
||||
err = mtk_hw_pin_field_get(hw, desc, field, &pf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!pf.next)
|
||||
*value = (mtk_r32(hw, pf.index, pf.offset)
|
||||
>> pf.bitpos) & pf.mask;
|
||||
else
|
||||
mtk_hw_read_cross_field(hw, &pf, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_xt_find_eint_num(struct mtk_pinctrl *hw, unsigned long eint_n)
|
||||
{
|
||||
const struct mtk_pin_desc *desc;
|
||||
int i = 0;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)hw->soc->pins;
|
||||
|
||||
while (i < hw->soc->npins) {
|
||||
if (desc[i].eint.eint_n == eint_n)
|
||||
return desc[i].number;
|
||||
i++;
|
||||
}
|
||||
|
||||
return EINT_NA;
|
||||
}
|
||||
|
||||
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;
|
||||
const struct mtk_pin_desc *desc;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)hw->soc->pins;
|
||||
*gpio_chip = &hw->chip;
|
||||
|
||||
/* Be greedy to guess first gpio_n is equal to eint_n */
|
||||
if (desc[eint_n].eint.eint_n == eint_n)
|
||||
*gpio_n = eint_n;
|
||||
else
|
||||
*gpio_n = mtk_xt_find_eint_num(hw, eint_n);
|
||||
|
||||
return *gpio_n == EINT_NA ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static int mtk_xt_get_gpio_state(void *data, unsigned long eint_n)
|
||||
{
|
||||
struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
|
||||
const struct mtk_pin_desc *desc;
|
||||
struct gpio_chip *gpio_chip;
|
||||
unsigned int gpio_n;
|
||||
int value, err;
|
||||
|
||||
err = mtk_xt_get_gpio_n(hw, eint_n, &gpio_n, &gpio_chip);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n];
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return !!value;
|
||||
}
|
||||
|
||||
static int mtk_xt_set_gpio_as_eint(void *data, unsigned long eint_n)
|
||||
{
|
||||
struct mtk_pinctrl *hw = (struct mtk_pinctrl *)data;
|
||||
const struct mtk_pin_desc *desc;
|
||||
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;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio_n];
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
|
||||
desc->eint.eint_m);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, MTK_INPUT);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, 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,
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
if (!hw->soc->eint_hw)
|
||||
return -ENODEV;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* Revision 0 */
|
||||
int mtk_pinconf_bias_disable_set(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU,
|
||||
MTK_DISABLE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD,
|
||||
MTK_DISABLE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_pinconf_bias_disable_get(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, int *res)
|
||||
{
|
||||
int v, v2;
|
||||
int err;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &v);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &v2);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (v == MTK_ENABLE || v2 == MTK_ENABLE)
|
||||
return -EINVAL;
|
||||
|
||||
*res = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_pinconf_bias_set(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup)
|
||||
{
|
||||
int err, arg;
|
||||
|
||||
arg = pullup ? 1 : 2;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU, arg & 1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD,
|
||||
!!(arg & 2));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_pinconf_bias_get(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup, int *res)
|
||||
{
|
||||
int reg, err, v;
|
||||
|
||||
reg = pullup ? PINCTRL_PIN_REG_PU : PINCTRL_PIN_REG_PD;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, reg, &v);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!v)
|
||||
return -EINVAL;
|
||||
|
||||
*res = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Revision 1 */
|
||||
int mtk_pinconf_bias_disable_set_rev1(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN,
|
||||
MTK_DISABLE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_pinconf_bias_disable_get_rev1(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, int *res)
|
||||
{
|
||||
int v, err;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, &v);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (v == MTK_ENABLE)
|
||||
return -EINVAL;
|
||||
|
||||
*res = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_pinconf_bias_set_rev1(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup)
|
||||
{
|
||||
int err, arg;
|
||||
|
||||
arg = pullup ? MTK_PULLUP : MTK_PULLDOWN;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN,
|
||||
MTK_ENABLE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, arg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup,
|
||||
int *res)
|
||||
{
|
||||
int err, v;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, &v);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (v == MTK_DISABLE)
|
||||
return -EINVAL;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, &v);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (pullup ^ (v == MTK_PULLUP))
|
||||
return -EINVAL;
|
||||
|
||||
*res = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Revision 0 */
|
||||
int mtk_pinconf_drive_set(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, u32 arg)
|
||||
{
|
||||
const struct mtk_drive_desc *tb;
|
||||
int err = -ENOTSUPP;
|
||||
|
||||
tb = &mtk_drive[desc->drv_n];
|
||||
/* 4mA when (e8, e4) = (0, 0)
|
||||
* 8mA when (e8, e4) = (0, 1)
|
||||
* 12mA when (e8, e4) = (1, 0)
|
||||
* 16mA when (e8, e4) = (1, 1)
|
||||
*/
|
||||
if ((arg >= tb->min && arg <= tb->max) && !(arg % tb->step)) {
|
||||
arg = (arg / tb->step - 1) * tb->scal;
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_E4,
|
||||
arg & 0x1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_E8,
|
||||
(arg & 0x2) >> 1);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int mtk_pinconf_drive_get(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, int *val)
|
||||
{
|
||||
const struct mtk_drive_desc *tb;
|
||||
int err, val1, val2;
|
||||
|
||||
tb = &mtk_drive[desc->drv_n];
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_E4, &val1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_E8, &val2);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* 4mA when (e8, e4) = (0, 0); 8mA when (e8, e4) = (0, 1)
|
||||
* 12mA when (e8, e4) = (1, 0); 16mA when (e8, e4) = (1, 1)
|
||||
*/
|
||||
*val = (((val2 << 1) + val1) / tb->scal + 1) * tb->step;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Revision 1 */
|
||||
int mtk_pinconf_drive_set_rev1(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, u32 arg)
|
||||
{
|
||||
const struct mtk_drive_desc *tb;
|
||||
int err = -ENOTSUPP;
|
||||
|
||||
tb = &mtk_drive[desc->drv_n];
|
||||
|
||||
if ((arg >= tb->min && arg <= tb->max) && !(arg % tb->step)) {
|
||||
arg = (arg / tb->step - 1) * tb->scal;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV,
|
||||
arg);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, int *val)
|
||||
{
|
||||
const struct mtk_drive_desc *tb;
|
||||
int err, val1;
|
||||
|
||||
tb = &mtk_drive[desc->drv_n];
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV, &val1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*val = ((val1 & 0x7) / tb->scal + 1) * tb->step;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup,
|
||||
u32 arg)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* 10K off & 50K (75K) off, when (R0, R1) = (0, 0);
|
||||
* 10K off & 50K (75K) on, when (R0, R1) = (0, 1);
|
||||
* 10K on & 50K (75K) off, when (R0, R1) = (1, 0);
|
||||
* 10K on & 50K (75K) on, when (R0, R1) = (1, 1)
|
||||
*/
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R0, arg & 1);
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R1,
|
||||
!!(arg & 2));
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
arg = pullup ? 0 : 1;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PUPD, arg);
|
||||
|
||||
/* If PUPD register is not supported for that pin, let's fallback to
|
||||
* general bias control.
|
||||
*/
|
||||
if (err == -ENOTSUPP) {
|
||||
if (hw->soc->bias_set) {
|
||||
err = hw->soc->bias_set(hw, desc, pullup);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int mtk_pinconf_adv_pull_get(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup,
|
||||
u32 *val)
|
||||
{
|
||||
u32 t, t2;
|
||||
int err;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PUPD, &t);
|
||||
|
||||
/* If PUPD register is not supported for that pin, let's fallback to
|
||||
* general bias control.
|
||||
*/
|
||||
if (err == -ENOTSUPP) {
|
||||
if (hw->soc->bias_get) {
|
||||
err = hw->soc->bias_get(hw, desc, pullup, val);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
} else {
|
||||
/* t == 0 supposes PULLUP for the customized PULL setup */
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (pullup ^ !t)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R0, &t);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R1, &t2);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*val = (t | t2 << 1) & 0x7;
|
||||
|
||||
return 0;
|
||||
}
|
291
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
Normal file
291
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
Normal file
@ -0,0 +1,291 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2018 MediaTek Inc.
|
||||
*
|
||||
* Author: Sean Wang <sean.wang@mediatek.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PINCTRL_MTK_COMMON_V2_H
|
||||
#define __PINCTRL_MTK_COMMON_V2_H
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
#define MTK_INPUT 0
|
||||
#define MTK_OUTPUT 1
|
||||
#define MTK_DISABLE 0
|
||||
#define MTK_ENABLE 1
|
||||
#define MTK_PULLDOWN 0
|
||||
#define MTK_PULLUP 1
|
||||
|
||||
#define EINT_NA U16_MAX
|
||||
#define NO_EINT_SUPPORT EINT_NA
|
||||
|
||||
#define PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, \
|
||||
_s_bit, _x_bits, _sz_reg, _fixed) { \
|
||||
.s_pin = _s_pin, \
|
||||
.e_pin = _e_pin, \
|
||||
.i_base = _i_base, \
|
||||
.s_addr = _s_addr, \
|
||||
.x_addrs = _x_addrs, \
|
||||
.s_bit = _s_bit, \
|
||||
.x_bits = _x_bits, \
|
||||
.sz_reg = _sz_reg, \
|
||||
.fixed = _fixed, \
|
||||
}
|
||||
|
||||
#define PIN_FIELD(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \
|
||||
PIN_FIELD_CALC(_s_pin, _e_pin, 0, _s_addr, _x_addrs, _s_bit, \
|
||||
_x_bits, 32, 0)
|
||||
|
||||
#define PINS_FIELD(_s_pin, _e_pin, _s_addr, _x_addrs, _s_bit, _x_bits) \
|
||||
PIN_FIELD_CALC(_s_pin, _e_pin, 0, _s_addr, _x_addrs, _s_bit, \
|
||||
_x_bits, 32, 1)
|
||||
|
||||
/* List these attributes which could be modified for the pin */
|
||||
enum {
|
||||
PINCTRL_PIN_REG_MODE,
|
||||
PINCTRL_PIN_REG_DIR,
|
||||
PINCTRL_PIN_REG_DI,
|
||||
PINCTRL_PIN_REG_DO,
|
||||
PINCTRL_PIN_REG_SR,
|
||||
PINCTRL_PIN_REG_SMT,
|
||||
PINCTRL_PIN_REG_PD,
|
||||
PINCTRL_PIN_REG_PU,
|
||||
PINCTRL_PIN_REG_E4,
|
||||
PINCTRL_PIN_REG_E8,
|
||||
PINCTRL_PIN_REG_TDSEL,
|
||||
PINCTRL_PIN_REG_RDSEL,
|
||||
PINCTRL_PIN_REG_DRV,
|
||||
PINCTRL_PIN_REG_PUPD,
|
||||
PINCTRL_PIN_REG_R0,
|
||||
PINCTRL_PIN_REG_R1,
|
||||
PINCTRL_PIN_REG_IES,
|
||||
PINCTRL_PIN_REG_PULLEN,
|
||||
PINCTRL_PIN_REG_PULLSEL,
|
||||
PINCTRL_PIN_REG_MAX,
|
||||
};
|
||||
|
||||
/* Group the pins by the driving current */
|
||||
enum {
|
||||
DRV_FIXED,
|
||||
DRV_GRP0,
|
||||
DRV_GRP1,
|
||||
DRV_GRP2,
|
||||
DRV_GRP3,
|
||||
DRV_GRP4,
|
||||
DRV_GRP_MAX,
|
||||
};
|
||||
|
||||
static const char * const mtk_default_register_base_names[] = {
|
||||
"base",
|
||||
};
|
||||
|
||||
/* struct mtk_pin_field - the structure that holds the information of the field
|
||||
* used to describe the attribute for the pin
|
||||
* @base: the index pointing to the entry in base address list
|
||||
* @offset: the register offset relative to the base address
|
||||
* @mask: the mask used to filter out the field from the register
|
||||
* @bitpos: the start bit relative to the register
|
||||
* @next: the indication that the field would be extended to the
|
||||
next register
|
||||
*/
|
||||
struct mtk_pin_field {
|
||||
u8 index;
|
||||
u32 offset;
|
||||
u32 mask;
|
||||
u8 bitpos;
|
||||
u8 next;
|
||||
};
|
||||
|
||||
/* struct mtk_pin_field_calc - the structure that holds the range providing
|
||||
* the guide used to look up the relevant field
|
||||
* @s_pin: the start pin within the range
|
||||
* @e_pin: the end pin within the range
|
||||
* @i_base: the index pointing to the entry in base address list
|
||||
* @s_addr: the start address for the range
|
||||
* @x_addrs: the address distance between two consecutive registers
|
||||
* within the range
|
||||
* @s_bit: the start bit for the first register within the range
|
||||
* @x_bits: the bit distance between two consecutive pins within
|
||||
* the range
|
||||
* @sz_reg: the size of bits in a register
|
||||
* @fixed: the consecutive pins share the same bits with the 1st
|
||||
* pin
|
||||
*/
|
||||
struct mtk_pin_field_calc {
|
||||
u16 s_pin;
|
||||
u16 e_pin;
|
||||
u8 i_base;
|
||||
u32 s_addr;
|
||||
u8 x_addrs;
|
||||
u8 s_bit;
|
||||
u8 x_bits;
|
||||
u8 sz_reg;
|
||||
u8 fixed;
|
||||
};
|
||||
|
||||
/* struct mtk_pin_reg_calc - the structure that holds all ranges used to
|
||||
* determine which register the pin would make use of
|
||||
* for certain pin attribute.
|
||||
* @range: the start address for the range
|
||||
* @nranges: the number of items in the range
|
||||
*/
|
||||
struct mtk_pin_reg_calc {
|
||||
const struct mtk_pin_field_calc *range;
|
||||
unsigned int nranges;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mtk_func_desc - the structure that providing information
|
||||
* all the funcs for this pin
|
||||
* @name: the name of function
|
||||
* @muxval: the mux to the function
|
||||
*/
|
||||
struct mtk_func_desc {
|
||||
const char *name;
|
||||
u8 muxval;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mtk_eint_desc - the structure that providing information
|
||||
* for eint data per pin
|
||||
* @eint_m: the eint mux for this pin
|
||||
* @eitn_n: the eint number for this pin
|
||||
*/
|
||||
struct mtk_eint_desc {
|
||||
u16 eint_m;
|
||||
u16 eint_n;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mtk_pin_desc - the structure that providing information
|
||||
* for each pin of chips
|
||||
* @number: unique pin number from the global pin number space
|
||||
* @name: name for this pin
|
||||
* @eint: the eint data for this pin
|
||||
* @drv_n: the index with the driving group
|
||||
* @funcs: all available functions for this pins (only used in
|
||||
* those drivers compatible to pinctrl-mtk-common.c-like
|
||||
* ones)
|
||||
*/
|
||||
struct mtk_pin_desc {
|
||||
unsigned int number;
|
||||
const char *name;
|
||||
struct mtk_eint_desc eint;
|
||||
u8 drv_n;
|
||||
struct mtk_func_desc *funcs;
|
||||
};
|
||||
|
||||
struct mtk_pinctrl_group {
|
||||
const char *name;
|
||||
unsigned long config;
|
||||
unsigned pin;
|
||||
};
|
||||
|
||||
struct mtk_pinctrl;
|
||||
|
||||
/* struct mtk_pin_soc - the structure that holds SoC-specific data */
|
||||
struct mtk_pin_soc {
|
||||
const struct mtk_pin_reg_calc *reg_cal;
|
||||
const struct mtk_pin_desc *pins;
|
||||
unsigned int npins;
|
||||
const struct group_desc *grps;
|
||||
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;
|
||||
|
||||
/* Specific parameters per SoC */
|
||||
u8 gpio_m;
|
||||
bool ies_present;
|
||||
const char * const *base_names;
|
||||
unsigned int nbase_names;
|
||||
|
||||
/* Specific pinconfig operations */
|
||||
int (*bias_disable_set)(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc);
|
||||
int (*bias_disable_get)(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, int *res);
|
||||
int (*bias_set)(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup);
|
||||
int (*bias_get)(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup, int *res);
|
||||
|
||||
int (*drive_set)(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, u32 arg);
|
||||
int (*drive_get)(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, int *val);
|
||||
|
||||
int (*adv_pull_set)(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup,
|
||||
u32 arg);
|
||||
int (*adv_pull_get)(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup,
|
||||
u32 *val);
|
||||
|
||||
/* Specific driver data */
|
||||
void *driver_data;
|
||||
};
|
||||
|
||||
struct mtk_pinctrl {
|
||||
struct pinctrl_dev *pctrl;
|
||||
void __iomem **base;
|
||||
u8 nbase;
|
||||
struct device *dev;
|
||||
struct gpio_chip chip;
|
||||
const struct mtk_pin_soc *soc;
|
||||
struct mtk_eint *eint;
|
||||
struct mtk_pinctrl_group *groups;
|
||||
const char **grp_names;
|
||||
};
|
||||
|
||||
void mtk_rmw(struct mtk_pinctrl *pctl, u8 i, u32 reg, u32 mask, u32 set);
|
||||
|
||||
int mtk_hw_set_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
|
||||
int field, int value);
|
||||
int mtk_hw_get_value(struct mtk_pinctrl *hw, const struct mtk_pin_desc *desc,
|
||||
int field, int *value);
|
||||
|
||||
int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev);
|
||||
|
||||
int mtk_pinconf_bias_disable_set(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc);
|
||||
int mtk_pinconf_bias_disable_get(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, int *res);
|
||||
int mtk_pinconf_bias_set(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup);
|
||||
int mtk_pinconf_bias_get(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup,
|
||||
int *res);
|
||||
|
||||
int mtk_pinconf_bias_disable_set_rev1(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc);
|
||||
int mtk_pinconf_bias_disable_get_rev1(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc,
|
||||
int *res);
|
||||
int mtk_pinconf_bias_set_rev1(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup);
|
||||
int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup,
|
||||
int *res);
|
||||
|
||||
int mtk_pinconf_drive_set(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, u32 arg);
|
||||
int mtk_pinconf_drive_get(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, int *val);
|
||||
|
||||
int mtk_pinconf_drive_set_rev1(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, u32 arg);
|
||||
int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, int *val);
|
||||
|
||||
int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup,
|
||||
u32 arg);
|
||||
int mtk_pinconf_adv_pull_get(struct mtk_pinctrl *hw,
|
||||
const struct mtk_pin_desc *desc, bool pullup,
|
||||
u32 *val);
|
||||
|
||||
#endif /* __PINCTRL_MTK_COMMON_V2_H */
|
@ -514,8 +514,8 @@ static int mtk_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
|
||||
pins = of_find_property(node, "pinmux", NULL);
|
||||
if (!pins) {
|
||||
dev_err(pctl->dev, "missing pins property in node %s .\n",
|
||||
node->name);
|
||||
dev_err(pctl->dev, "missing pins property in node %pOFn .\n",
|
||||
node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
1754
drivers/pinctrl/mediatek/pinctrl-mtk-mt6765.h
Normal file
1754
drivers/pinctrl/mediatek/pinctrl-mtk-mt6765.h
Normal file
File diff suppressed because it is too large
Load Diff
1916
drivers/pinctrl/mediatek/pinctrl-mtk-mt8183.h
Normal file
1916
drivers/pinctrl/mediatek/pinctrl-mtk-mt8183.h
Normal file
File diff suppressed because it is too large
Load Diff
907
drivers/pinctrl/mediatek/pinctrl-paris.c
Normal file
907
drivers/pinctrl/mediatek/pinctrl-paris.c
Normal file
@ -0,0 +1,907 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* MediaTek Pinctrl Paris Driver, which implement the vendor per-pin
|
||||
* bindings for MediaTek SoC.
|
||||
*
|
||||
* Copyright (C) 2018 MediaTek Inc.
|
||||
* Author: Sean Wang <sean.wang@mediatek.com>
|
||||
* Zhiyong Tao <zhiyong.tao@mediatek.com>
|
||||
* Hongzhou.Yang <hongzhou.yang@mediatek.com>
|
||||
*/
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <dt-bindings/pinctrl/mt65xx.h>
|
||||
#include "pinctrl-paris.h"
|
||||
|
||||
#define PINCTRL_PINCTRL_DEV KBUILD_MODNAME
|
||||
|
||||
/* Custom pinconf parameters */
|
||||
#define MTK_PIN_CONFIG_TDSEL (PIN_CONFIG_END + 1)
|
||||
#define MTK_PIN_CONFIG_RDSEL (PIN_CONFIG_END + 2)
|
||||
#define MTK_PIN_CONFIG_PU_ADV (PIN_CONFIG_END + 3)
|
||||
#define MTK_PIN_CONFIG_PD_ADV (PIN_CONFIG_END + 4)
|
||||
|
||||
static const struct pinconf_generic_params mtk_custom_bindings[] = {
|
||||
{"mediatek,tdsel", MTK_PIN_CONFIG_TDSEL, 0},
|
||||
{"mediatek,rdsel", MTK_PIN_CONFIG_RDSEL, 0},
|
||||
{"mediatek,pull-up-adv", MTK_PIN_CONFIG_PU_ADV, 1},
|
||||
{"mediatek,pull-down-adv", MTK_PIN_CONFIG_PD_ADV, 1},
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static const struct pin_config_item mtk_conf_items[] = {
|
||||
PCONFDUMP(MTK_PIN_CONFIG_TDSEL, "tdsel", NULL, true),
|
||||
PCONFDUMP(MTK_PIN_CONFIG_RDSEL, "rdsel", NULL, true),
|
||||
PCONFDUMP(MTK_PIN_CONFIG_PU_ADV, "pu-adv", NULL, true),
|
||||
PCONFDUMP(MTK_PIN_CONFIG_PD_ADV, "pd-adv", NULL, true),
|
||||
};
|
||||
#endif
|
||||
|
||||
static const char * const mtk_gpio_functions[] = {
|
||||
"func0", "func1", "func2", "func3",
|
||||
"func4", "func5", "func6", "func7",
|
||||
"func8", "func9", "func10", "func11",
|
||||
"func12", "func13", "func14", "func15",
|
||||
};
|
||||
|
||||
static int mtk_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned int pin)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct mtk_pin_desc *desc;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
|
||||
|
||||
return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE,
|
||||
hw->soc->gpio_m);
|
||||
}
|
||||
|
||||
static int mtk_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned int pin, bool input)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct mtk_pin_desc *desc;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
|
||||
|
||||
/* hardware would take 0 as input direction */
|
||||
return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !input);
|
||||
}
|
||||
|
||||
static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
|
||||
unsigned int pin, unsigned long *config)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
u32 param = pinconf_to_config_param(*config);
|
||||
int val, val2, err, reg, ret = 1;
|
||||
const struct mtk_pin_desc *desc;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
if (hw->soc->bias_disable_get) {
|
||||
err = hw->soc->bias_disable_get(hw, desc, &ret);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
if (hw->soc->bias_get) {
|
||||
err = hw->soc->bias_get(hw, desc, 1, &ret);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
if (hw->soc->bias_get) {
|
||||
err = hw->soc->bias_get(hw, desc, 0, &ret);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
case PIN_CONFIG_OUTPUT_ENABLE:
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* HW takes input mode as zero; output mode as non-zero */
|
||||
if ((val && param == PIN_CONFIG_INPUT_ENABLE) ||
|
||||
(!val && param == PIN_CONFIG_OUTPUT_ENABLE))
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &val2);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (val || !val2)
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
if (hw->soc->drive_get) {
|
||||
err = hw->soc->drive_get(hw, desc, &ret);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
err = -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case MTK_PIN_CONFIG_TDSEL:
|
||||
case MTK_PIN_CONFIG_RDSEL:
|
||||
reg = (param == MTK_PIN_CONFIG_TDSEL) ?
|
||||
PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, reg, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ret = val;
|
||||
|
||||
break;
|
||||
case MTK_PIN_CONFIG_PU_ADV:
|
||||
case MTK_PIN_CONFIG_PD_ADV:
|
||||
if (hw->soc->adv_pull_get) {
|
||||
bool pullup;
|
||||
|
||||
pullup = param == MTK_PIN_CONFIG_PU_ADV;
|
||||
err = hw->soc->adv_pull_get(hw, desc, pullup, &ret);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
*config = pinconf_to_config_packed(param, ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
enum pin_config_param param,
|
||||
enum pin_config_param arg)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct mtk_pin_desc *desc;
|
||||
int err = 0;
|
||||
u32 reg;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
|
||||
|
||||
switch ((u32)param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
if (hw->soc->bias_disable_set) {
|
||||
err = hw->soc->bias_disable_set(hw, desc);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
if (hw->soc->bias_set) {
|
||||
err = hw->soc->bias_set(hw, desc, 1);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
if (hw->soc->bias_set) {
|
||||
err = hw->soc->bias_set(hw, desc, 0);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT_ENABLE:
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
|
||||
MTK_DISABLE);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
|
||||
MTK_OUTPUT);
|
||||
if (err)
|
||||
goto err;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
if (hw->soc->ies_present) {
|
||||
mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES,
|
||||
MTK_ENABLE);
|
||||
}
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
|
||||
MTK_INPUT);
|
||||
if (err)
|
||||
goto err;
|
||||
break;
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR,
|
||||
arg);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
|
||||
MTK_OUTPUT);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO,
|
||||
arg);
|
||||
if (err)
|
||||
goto err;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
/* arg = 1: Input mode & SMT enable ;
|
||||
* arg = 0: Output mode & SMT disable
|
||||
*/
|
||||
arg = arg ? 2 : 1;
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
|
||||
arg & 1);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
|
||||
!!(arg & 2));
|
||||
if (err)
|
||||
goto err;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
if (hw->soc->drive_set) {
|
||||
err = hw->soc->drive_set(hw, desc, arg);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
case MTK_PIN_CONFIG_TDSEL:
|
||||
case MTK_PIN_CONFIG_RDSEL:
|
||||
reg = (param == MTK_PIN_CONFIG_TDSEL) ?
|
||||
PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
|
||||
|
||||
err = mtk_hw_set_value(hw, desc, reg, arg);
|
||||
if (err)
|
||||
goto err;
|
||||
break;
|
||||
case MTK_PIN_CONFIG_PU_ADV:
|
||||
case MTK_PIN_CONFIG_PD_ADV:
|
||||
if (hw->soc->adv_pull_set) {
|
||||
bool pullup;
|
||||
|
||||
pullup = param == MTK_PIN_CONFIG_PU_ADV;
|
||||
err = hw->soc->adv_pull_set(hw, desc, pullup,
|
||||
arg);
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
err = -ENOTSUPP;
|
||||
}
|
||||
|
||||
err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct mtk_pinctrl_group *
|
||||
mtk_pctrl_find_group_by_pin(struct mtk_pinctrl *hw, u32 pin)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hw->soc->ngrps; i++) {
|
||||
struct mtk_pinctrl_group *grp = hw->groups + i;
|
||||
|
||||
if (grp->pin == pin)
|
||||
return grp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct mtk_func_desc *
|
||||
mtk_pctrl_find_function_by_pin(struct mtk_pinctrl *hw, u32 pin_num, u32 fnum)
|
||||
{
|
||||
const struct mtk_pin_desc *pin = hw->soc->pins + pin_num;
|
||||
const struct mtk_func_desc *func = pin->funcs;
|
||||
|
||||
while (func && func->name) {
|
||||
if (func->muxval == fnum)
|
||||
return func;
|
||||
func++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool mtk_pctrl_is_function_valid(struct mtk_pinctrl *hw, u32 pin_num,
|
||||
u32 fnum)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < hw->soc->npins; i++) {
|
||||
const struct mtk_pin_desc *pin = hw->soc->pins + i;
|
||||
|
||||
if (pin->number == pin_num) {
|
||||
const struct mtk_func_desc *func = pin->funcs;
|
||||
|
||||
while (func && func->name) {
|
||||
if (func->muxval == fnum)
|
||||
return true;
|
||||
func++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int mtk_pctrl_dt_node_to_map_func(struct mtk_pinctrl *pctl,
|
||||
u32 pin, u32 fnum,
|
||||
struct mtk_pinctrl_group *grp,
|
||||
struct pinctrl_map **map,
|
||||
unsigned *reserved_maps,
|
||||
unsigned *num_maps)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (*num_maps == *reserved_maps)
|
||||
return -ENOSPC;
|
||||
|
||||
(*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
(*map)[*num_maps].data.mux.group = grp->name;
|
||||
|
||||
ret = mtk_pctrl_is_function_valid(pctl, pin, fnum);
|
||||
if (!ret) {
|
||||
dev_err(pctl->dev, "invalid function %d on pin %d .\n",
|
||||
fnum, pin);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
(*map)[*num_maps].data.mux.function = mtk_gpio_functions[fnum];
|
||||
(*num_maps)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *node,
|
||||
struct pinctrl_map **map,
|
||||
unsigned *reserved_maps,
|
||||
unsigned *num_maps)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
int num_pins, num_funcs, maps_per_pin, i, err;
|
||||
struct mtk_pinctrl_group *grp;
|
||||
unsigned int num_configs;
|
||||
bool has_config = false;
|
||||
unsigned long *configs;
|
||||
u32 pinfunc, pin, func;
|
||||
struct property *pins;
|
||||
unsigned reserve = 0;
|
||||
|
||||
pins = of_find_property(node, "pinmux", NULL);
|
||||
if (!pins) {
|
||||
dev_err(hw->dev, "missing pins property in node %s .\n",
|
||||
node->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = pinconf_generic_parse_dt_config(node, pctldev, &configs,
|
||||
&num_configs);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (num_configs)
|
||||
has_config = true;
|
||||
|
||||
num_pins = pins->length / sizeof(u32);
|
||||
num_funcs = num_pins;
|
||||
maps_per_pin = 0;
|
||||
if (num_funcs)
|
||||
maps_per_pin++;
|
||||
if (has_config && num_pins >= 1)
|
||||
maps_per_pin++;
|
||||
|
||||
if (!num_pins || !maps_per_pin) {
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
reserve = num_pins * maps_per_pin;
|
||||
|
||||
err = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps,
|
||||
reserve);
|
||||
if (err < 0)
|
||||
goto exit;
|
||||
|
||||
for (i = 0; i < num_pins; i++) {
|
||||
err = of_property_read_u32_index(node, "pinmux", i, &pinfunc);
|
||||
if (err)
|
||||
goto exit;
|
||||
|
||||
pin = MTK_GET_PIN_NO(pinfunc);
|
||||
func = MTK_GET_PIN_FUNC(pinfunc);
|
||||
|
||||
if (pin >= hw->soc->npins ||
|
||||
func >= ARRAY_SIZE(mtk_gpio_functions)) {
|
||||
dev_err(hw->dev, "invalid pins value.\n");
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
grp = mtk_pctrl_find_group_by_pin(hw, pin);
|
||||
if (!grp) {
|
||||
dev_err(hw->dev, "unable to match pin %d to group\n",
|
||||
pin);
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
err = mtk_pctrl_dt_node_to_map_func(hw, pin, func, grp, map,
|
||||
reserved_maps, num_maps);
|
||||
if (err < 0)
|
||||
goto exit;
|
||||
|
||||
if (has_config) {
|
||||
err = pinctrl_utils_add_map_configs(pctldev, map,
|
||||
reserved_maps,
|
||||
num_maps,
|
||||
grp->name,
|
||||
configs,
|
||||
num_configs,
|
||||
PIN_MAP_TYPE_CONFIGS_GROUP);
|
||||
if (err < 0)
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
||||
exit:
|
||||
kfree(configs);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mtk_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np_config,
|
||||
struct pinctrl_map **map,
|
||||
unsigned *num_maps)
|
||||
{
|
||||
struct device_node *np;
|
||||
unsigned reserved_maps;
|
||||
int ret;
|
||||
|
||||
*map = NULL;
|
||||
*num_maps = 0;
|
||||
reserved_maps = 0;
|
||||
|
||||
for_each_child_of_node(np_config, np) {
|
||||
ret = mtk_pctrl_dt_subnode_to_map(pctldev, np, map,
|
||||
&reserved_maps,
|
||||
num_maps);
|
||||
if (ret < 0) {
|
||||
pinctrl_utils_free_map(pctldev, *map, *num_maps);
|
||||
of_node_put(np);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return hw->soc->ngrps;
|
||||
}
|
||||
|
||||
static const char *mtk_pctrl_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned group)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return hw->groups[group].name;
|
||||
}
|
||||
|
||||
static int mtk_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
unsigned group, const unsigned **pins,
|
||||
unsigned *num_pins)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
*pins = (unsigned *)&hw->groups[group].pin;
|
||||
*num_pins = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops mtk_pctlops = {
|
||||
.dt_node_to_map = mtk_pctrl_dt_node_to_map,
|
||||
.dt_free_map = pinctrl_utils_free_map,
|
||||
.get_groups_count = mtk_pctrl_get_groups_count,
|
||||
.get_group_name = mtk_pctrl_get_group_name,
|
||||
.get_group_pins = mtk_pctrl_get_group_pins,
|
||||
};
|
||||
|
||||
static int mtk_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
return ARRAY_SIZE(mtk_gpio_functions);
|
||||
}
|
||||
|
||||
static const char *mtk_pmx_get_func_name(struct pinctrl_dev *pctldev,
|
||||
unsigned selector)
|
||||
{
|
||||
return mtk_gpio_functions[selector];
|
||||
}
|
||||
|
||||
static int mtk_pmx_get_func_groups(struct pinctrl_dev *pctldev,
|
||||
unsigned function,
|
||||
const char * const **groups,
|
||||
unsigned * const num_groups)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
*groups = hw->grp_names;
|
||||
*num_groups = hw->soc->ngrps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_pmx_set_mux(struct pinctrl_dev *pctldev,
|
||||
unsigned function,
|
||||
unsigned group)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct mtk_pinctrl_group *grp = hw->groups + group;
|
||||
const struct mtk_func_desc *desc_func;
|
||||
const struct mtk_pin_desc *desc;
|
||||
bool ret;
|
||||
|
||||
ret = mtk_pctrl_is_function_valid(hw, grp->pin, function);
|
||||
if (!ret) {
|
||||
dev_err(hw->dev, "invalid function %d on group %d .\n",
|
||||
function, group);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
desc_func = mtk_pctrl_find_function_by_pin(hw, grp->pin, function);
|
||||
if (!desc_func)
|
||||
return -EINVAL;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[grp->pin];
|
||||
mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_MODE, desc_func->muxval);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinmux_ops mtk_pmxops = {
|
||||
.get_functions_count = mtk_pmx_get_funcs_cnt,
|
||||
.get_function_name = mtk_pmx_get_func_name,
|
||||
.get_function_groups = mtk_pmx_get_func_groups,
|
||||
.set_mux = mtk_pmx_set_mux,
|
||||
.gpio_set_direction = mtk_pinmux_gpio_set_direction,
|
||||
.gpio_request_enable = mtk_pinmux_gpio_request_enable,
|
||||
};
|
||||
|
||||
static int mtk_pconf_group_get(struct pinctrl_dev *pctldev, unsigned group,
|
||||
unsigned long *config)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
*config = hw->groups[group].config;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
|
||||
unsigned long *configs, unsigned num_configs)
|
||||
{
|
||||
struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct mtk_pinctrl_group *grp = &hw->groups[group];
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
ret = mtk_pinconf_set(pctldev, grp->pin,
|
||||
pinconf_to_config_param(configs[i]),
|
||||
pinconf_to_config_argument(configs[i]));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
grp->config = configs[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinconf_ops mtk_confops = {
|
||||
.pin_config_get = mtk_pinconf_get,
|
||||
.pin_config_group_get = mtk_pconf_group_get,
|
||||
.pin_config_group_set = mtk_pconf_group_set,
|
||||
};
|
||||
|
||||
static struct pinctrl_desc mtk_desc = {
|
||||
.name = PINCTRL_PINCTRL_DEV,
|
||||
.pctlops = &mtk_pctlops,
|
||||
.pmxops = &mtk_pmxops,
|
||||
.confops = &mtk_confops,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int mtk_gpio_get_direction(struct gpio_chip *chip, unsigned int gpio)
|
||||
{
|
||||
struct mtk_pinctrl *hw = gpiochip_get_data(chip);
|
||||
const struct mtk_pin_desc *desc;
|
||||
int value, err;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return !value;
|
||||
}
|
||||
|
||||
static int mtk_gpio_get(struct gpio_chip *chip, unsigned int gpio)
|
||||
{
|
||||
struct mtk_pinctrl *hw = gpiochip_get_data(chip);
|
||||
const struct mtk_pin_desc *desc;
|
||||
int value, err;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
|
||||
|
||||
err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return !!value;
|
||||
}
|
||||
|
||||
static void mtk_gpio_set(struct gpio_chip *chip, unsigned int gpio, int value)
|
||||
{
|
||||
struct mtk_pinctrl *hw = gpiochip_get_data(chip);
|
||||
const struct mtk_pin_desc *desc;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
|
||||
|
||||
mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value);
|
||||
}
|
||||
|
||||
static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
|
||||
{
|
||||
return pinctrl_gpio_direction_input(chip->base + gpio);
|
||||
}
|
||||
|
||||
static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
|
||||
int value)
|
||||
{
|
||||
mtk_gpio_set(chip, gpio, value);
|
||||
|
||||
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);
|
||||
const struct mtk_pin_desc *desc;
|
||||
|
||||
if (!hw->eint)
|
||||
return -ENOTSUPP;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset];
|
||||
|
||||
if (desc->eint.eint_n == EINT_NA)
|
||||
return -ENOTSUPP;
|
||||
|
||||
return mtk_eint_find_irq(hw->eint, desc->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);
|
||||
const struct mtk_pin_desc *desc;
|
||||
u32 debounce;
|
||||
|
||||
desc = (const struct mtk_pin_desc *)&hw->soc->pins[offset];
|
||||
|
||||
if (!hw->eint ||
|
||||
pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE ||
|
||||
desc->eint.eint_n == EINT_NA)
|
||||
return -ENOTSUPP;
|
||||
|
||||
debounce = pinconf_to_config_argument(config);
|
||||
|
||||
return mtk_eint_set_debounce(hw->eint, desc->eint.eint_n, debounce);
|
||||
}
|
||||
|
||||
static int mtk_build_gpiochip(struct mtk_pinctrl *hw, struct device_node *np)
|
||||
{
|
||||
struct gpio_chip *chip = &hw->chip;
|
||||
int ret;
|
||||
|
||||
chip->label = PINCTRL_PINCTRL_DEV;
|
||||
chip->parent = hw->dev;
|
||||
chip->request = gpiochip_generic_request;
|
||||
chip->free = gpiochip_generic_free;
|
||||
chip->get_direction = mtk_gpio_get_direction;
|
||||
chip->direction_input = mtk_gpio_direction_input;
|
||||
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;
|
||||
chip->of_gpio_n_cells = 2;
|
||||
|
||||
ret = gpiochip_add_data(chip, hw);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtk_pctrl_build_state(struct platform_device *pdev)
|
||||
{
|
||||
struct mtk_pinctrl *hw = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
/* Allocate groups */
|
||||
hw->groups = devm_kmalloc_array(&pdev->dev, hw->soc->ngrps,
|
||||
sizeof(*hw->groups), GFP_KERNEL);
|
||||
if (!hw->groups)
|
||||
return -ENOMEM;
|
||||
|
||||
/* We assume that one pin is one group, use pin name as group name. */
|
||||
hw->grp_names = devm_kmalloc_array(&pdev->dev, hw->soc->ngrps,
|
||||
sizeof(*hw->grp_names), GFP_KERNEL);
|
||||
if (!hw->grp_names)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < hw->soc->npins; i++) {
|
||||
const struct mtk_pin_desc *pin = hw->soc->pins + i;
|
||||
struct mtk_pinctrl_group *group = hw->groups + i;
|
||||
|
||||
group->name = pin->name;
|
||||
group->pin = pin->number;
|
||||
|
||||
hw->grp_names[i] = pin->name;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mtk_paris_pinctrl_probe(struct platform_device *pdev,
|
||||
const struct mtk_pin_soc *soc)
|
||||
{
|
||||
struct pinctrl_pin_desc *pins;
|
||||
struct mtk_pinctrl *hw;
|
||||
struct resource *res;
|
||||
int err, i;
|
||||
|
||||
hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
|
||||
if (!hw)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, hw);
|
||||
hw->soc = soc;
|
||||
hw->dev = &pdev->dev;
|
||||
|
||||
if (!hw->soc->nbase_names) {
|
||||
dev_err(&pdev->dev,
|
||||
"SoC should be assigned at least one register base\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hw->base = devm_kmalloc_array(&pdev->dev, hw->soc->nbase_names,
|
||||
sizeof(*hw->base), GFP_KERNEL);
|
||||
if (!hw->base)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < hw->soc->nbase_names; i++) {
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
hw->soc->base_names[i]);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "missing IO resource\n");
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
hw->base[i] = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(hw->base[i]))
|
||||
return PTR_ERR(hw->base[i]);
|
||||
}
|
||||
|
||||
hw->nbase = hw->soc->nbase_names;
|
||||
|
||||
err = mtk_pctrl_build_state(pdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "build state failed: %d\n", err);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Copy from internal struct mtk_pin_desc to register to the core */
|
||||
pins = devm_kmalloc_array(&pdev->dev, hw->soc->npins, sizeof(*pins),
|
||||
GFP_KERNEL);
|
||||
if (!pins)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < hw->soc->npins; i++) {
|
||||
pins[i].number = hw->soc->pins[i].number;
|
||||
pins[i].name = hw->soc->pins[i].name;
|
||||
}
|
||||
|
||||
/* Setup pins descriptions per SoC types */
|
||||
mtk_desc.pins = (const struct pinctrl_pin_desc *)pins;
|
||||
mtk_desc.npins = hw->soc->npins;
|
||||
mtk_desc.num_custom_params = ARRAY_SIZE(mtk_custom_bindings);
|
||||
mtk_desc.custom_params = mtk_custom_bindings;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
mtk_desc.custom_conf_items = mtk_conf_items;
|
||||
#endif
|
||||
|
||||
err = devm_pinctrl_register_and_init(&pdev->dev, &mtk_desc, hw,
|
||||
&hw->pctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = pinctrl_enable(hw->pctrl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mtk_build_eint(hw, pdev);
|
||||
if (err)
|
||||
dev_warn(&pdev->dev,
|
||||
"Failed to add EINT, but pinctrl still can work\n");
|
||||
|
||||
/* Build gpiochip should be after pinctrl_enable is done */
|
||||
err = mtk_build_gpiochip(hw, pdev->dev.of_node);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to add gpio_chip\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, hw);
|
||||
|
||||
return 0;
|
||||
}
|
63
drivers/pinctrl/mediatek/pinctrl-paris.h
Normal file
63
drivers/pinctrl/mediatek/pinctrl-paris.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2018 MediaTek Inc.
|
||||
*
|
||||
* Author: Sean Wang <sean.wang@mediatek.com>
|
||||
* Zhiyong Tao <zhiyong.tao@mediatek.com>
|
||||
* Hongzhou.Yang <hongzhou.yang@mediatek.com>
|
||||
*/
|
||||
#ifndef __PINCTRL_PARIS_H
|
||||
#define __PINCTRL_PARIS_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
|
||||
#include "../core.h"
|
||||
#include "../pinconf.h"
|
||||
#include "../pinctrl-utils.h"
|
||||
#include "../pinmux.h"
|
||||
#include "mtk-eint.h"
|
||||
#include "pinctrl-mtk-common-v2.h"
|
||||
|
||||
#define MTK_RANGE(_a) { .range = (_a), .nranges = ARRAY_SIZE(_a), }
|
||||
|
||||
#define MTK_EINT_FUNCTION(_eintmux, _eintnum) \
|
||||
{ \
|
||||
.eint_m = _eintmux, \
|
||||
.eint_n = _eintnum, \
|
||||
}
|
||||
|
||||
#define MTK_FUNCTION(_val, _name) \
|
||||
{ \
|
||||
.muxval = _val, \
|
||||
.name = _name, \
|
||||
}
|
||||
|
||||
#define MTK_PIN(_number, _name, _eint, _drv_n, ...) { \
|
||||
.number = _number, \
|
||||
.name = _name, \
|
||||
.eint = _eint, \
|
||||
.drv_n = _drv_n, \
|
||||
.funcs = (struct mtk_func_desc[]){ \
|
||||
__VA_ARGS__, { } }, \
|
||||
}
|
||||
|
||||
#define PINCTRL_PIN_GROUP(name, id) \
|
||||
{ \
|
||||
name, \
|
||||
id##_pins, \
|
||||
ARRAY_SIZE(id##_pins), \
|
||||
id##_funcs, \
|
||||
}
|
||||
|
||||
int mtk_paris_pinctrl_probe(struct platform_device *pdev,
|
||||
const struct mtk_pin_soc *soc);
|
||||
|
||||
#endif /* __PINCTRL_PARIS_H */
|
@ -47,4 +47,10 @@ config PINCTRL_MESON_AXG
|
||||
config PINCTRL_MESON_AXG_PMX
|
||||
bool
|
||||
|
||||
config PINCTRL_MESON_G12A
|
||||
bool "Meson g12a Soc pinctrl driver"
|
||||
depends on ARM64
|
||||
select PINCTRL_MESON_AXG_PMX
|
||||
default y
|
||||
|
||||
endif
|
||||
|
@ -6,3 +6,4 @@ obj-$(CONFIG_PINCTRL_MESON_GXBB) += pinctrl-meson-gxbb.o
|
||||
obj-$(CONFIG_PINCTRL_MESON_GXL) += pinctrl-meson-gxl.o
|
||||
obj-$(CONFIG_PINCTRL_MESON_AXG_PMX) += pinctrl-meson-axg-pmx.o
|
||||
obj-$(CONFIG_PINCTRL_MESON_AXG) += pinctrl-meson-axg.o
|
||||
obj-$(CONFIG_PINCTRL_MESON_G12A) += pinctrl-meson-g12a.o
|
||||
|
1404
drivers/pinctrl/meson/pinctrl-meson-g12a.c
Normal file
1404
drivers/pinctrl/meson/pinctrl-meson-g12a.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -41,7 +41,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
@ -451,7 +451,7 @@ static struct regmap *meson_map_resource(struct meson_pinctrl *pc,
|
||||
|
||||
meson_regmap_config.max_register = resource_size(&res) - 4;
|
||||
meson_regmap_config.name = devm_kasprintf(pc->dev, GFP_KERNEL,
|
||||
"%s-%s", node->name,
|
||||
"%pOFn-%s", node,
|
||||
name);
|
||||
if (!meson_regmap_config.name)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
@ -11,7 +11,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
@ -413,14 +413,14 @@ static int mvebu_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
ret = of_property_read_string(np, "marvell,function", &function);
|
||||
if (ret) {
|
||||
dev_err(pctl->dev,
|
||||
"missing marvell,function in node %s\n", np->name);
|
||||
"missing marvell,function in node %pOFn\n", np);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nmaps = of_property_count_strings(np, "marvell,pins");
|
||||
if (nmaps < 0) {
|
||||
dev_err(pctl->dev,
|
||||
"missing marvell,pins in node %s\n", np->name);
|
||||
"missing marvell,pins in node %pOFn\n", np);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/mfd/abx500/ab8500.h>
|
||||
#include "pinctrl-abx500.h"
|
||||
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/mfd/abx500/ab8500.h>
|
||||
#include "pinctrl-abx500.h"
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/slab.h>
|
||||
@ -203,7 +203,7 @@ typedef unsigned long pin_cfg_t;
|
||||
|
||||
#define GPIO_BLOCK_SHIFT 5
|
||||
#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT)
|
||||
#define NMK_MAX_BANKS DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)
|
||||
#define NMK_MAX_BANKS DIV_ROUND_UP(512, NMK_GPIO_PER_CHIP)
|
||||
|
||||
/* Register in the logic block */
|
||||
#define NMK_GPIO_DAT 0x00
|
||||
@ -971,7 +971,7 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
|
||||
data_out ? "hi" : "lo",
|
||||
(mode < 0) ? "unknown" : modes[mode]);
|
||||
} else {
|
||||
int irq = gpio_to_irq(gpio);
|
||||
int irq = chip->to_irq(chip, offset);
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
int pullidx = 0;
|
||||
int val;
|
||||
@ -1051,7 +1051,7 @@ static struct nmk_gpio_chip *nmk_gpio_populate_chip(struct device_node *np,
|
||||
|
||||
gpio_pdev = of_find_device_by_node(np);
|
||||
if (!gpio_pdev) {
|
||||
pr_err("populate \"%s\": device not found\n", np->name);
|
||||
pr_err("populate \"%pOFn\": device not found\n", np);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
if (of_property_read_u32(np, "gpio-bank", &id)) {
|
||||
@ -1904,8 +1904,8 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
|
||||
gpio_np = of_parse_phandle(np, "nomadik-gpio-chips", i);
|
||||
if (gpio_np) {
|
||||
dev_info(&pdev->dev,
|
||||
"populate NMK GPIO %d \"%s\"\n",
|
||||
i, gpio_np->name);
|
||||
"populate NMK GPIO %d \"%pOFn\"\n",
|
||||
i, gpio_np);
|
||||
nmk_chip = nmk_gpio_populate_chip(gpio_np, pdev);
|
||||
if (IS_ERR(nmk_chip))
|
||||
dev_err(&pdev->dev,
|
||||
|
12
drivers/pinctrl/nuvoton/Kconfig
Normal file
12
drivers/pinctrl/nuvoton/Kconfig
Normal file
@ -0,0 +1,12 @@
|
||||
config PINCTRL_NPCM7XX
|
||||
bool "Pinctrl and GPIO driver for Nuvoton NPCM7XX"
|
||||
depends on (ARCH_NPCM7XX || COMPILE_TEST) && OF
|
||||
select PINMUX
|
||||
select PINCONF
|
||||
select GENERIC_PINCONF
|
||||
select GPIOLIB
|
||||
select GPIO_GENERIC
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say Y here to enable pin controller and GPIO support
|
||||
for Nuvoton NPCM750/730/715/705 SoCs.
|
4
drivers/pinctrl/nuvoton/Makefile
Normal file
4
drivers/pinctrl/nuvoton/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Nuvoton pinctrl support
|
||||
|
||||
obj-$(CONFIG_PINCTRL_NPCM7XX) += pinctrl-npcm7xx.o
|
2072
drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
Normal file
2072
drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -24,7 +24,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mutex.h>
|
||||
|
@ -21,7 +21,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mfd/as3722.h>
|
||||
|
@ -17,8 +17,6 @@
|
||||
#include <dt-bindings/pinctrl/at91.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
/* FIXME: needed for gpio_to_irq(), get rid of this */
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/init.h>
|
||||
@ -264,6 +262,13 @@ static struct irq_chip atmel_gpio_irq_chip = {
|
||||
.irq_set_wake = atmel_gpio_irq_set_wake,
|
||||
};
|
||||
|
||||
static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
|
||||
|
||||
return irq_find_mapping(atmel_pioctrl->irq_domain, offset);
|
||||
}
|
||||
|
||||
static void atmel_gpio_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
unsigned int irq = irq_desc_get_irq(desc);
|
||||
@ -297,8 +302,9 @@ static void atmel_gpio_irq_handler(struct irq_desc *desc)
|
||||
break;
|
||||
|
||||
for_each_set_bit(n, &isr, BITS_PER_LONG)
|
||||
generic_handle_irq(gpio_to_irq(bank *
|
||||
ATMEL_PIO_NPINS_PER_BANK + n));
|
||||
generic_handle_irq(atmel_gpio_to_irq(
|
||||
atmel_pioctrl->gpio_chip,
|
||||
bank * ATMEL_PIO_NPINS_PER_BANK + n));
|
||||
}
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
@ -360,13 +366,6 @@ static void atmel_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
|
||||
BIT(pin->line));
|
||||
}
|
||||
|
||||
static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip);
|
||||
|
||||
return irq_find_mapping(atmel_pioctrl->irq_domain, offset);
|
||||
}
|
||||
|
||||
static struct gpio_chip atmel_gpio_chip = {
|
||||
.direction_input = atmel_gpio_direction_input,
|
||||
.get = atmel_gpio_get,
|
||||
@ -493,7 +492,6 @@ static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
unsigned num_pins, num_configs, reserve;
|
||||
unsigned long *configs;
|
||||
struct property *pins;
|
||||
bool has_config;
|
||||
u32 pinfunc;
|
||||
int ret, i;
|
||||
|
||||
@ -509,9 +507,6 @@ static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (num_configs)
|
||||
has_config = true;
|
||||
|
||||
num_pins = pins->length / sizeof(u32);
|
||||
if (!num_pins) {
|
||||
dev_err(pctldev->dev, "no pins found in node %pOF\n", np);
|
||||
@ -524,7 +519,7 @@ static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
* map for each pin.
|
||||
*/
|
||||
reserve = 1;
|
||||
if (has_config && num_pins >= 1)
|
||||
if (num_configs)
|
||||
reserve++;
|
||||
reserve *= num_pins;
|
||||
ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps,
|
||||
@ -547,7 +542,7 @@ static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
pinctrl_utils_add_map_mux(pctldev, map, reserved_maps, num_maps,
|
||||
group, func);
|
||||
|
||||
if (has_config) {
|
||||
if (num_configs) {
|
||||
ret = pinctrl_utils_add_map_configs(pctldev, map,
|
||||
reserved_maps, num_maps, group,
|
||||
configs, num_configs,
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
@ -263,8 +263,8 @@ static int at91_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
*/
|
||||
grp = at91_pinctrl_find_group_by_name(info, np->name);
|
||||
if (!grp) {
|
||||
dev_err(info->dev, "unable to find group for node %s\n",
|
||||
np->name);
|
||||
dev_err(info->dev, "unable to find group for node %pOFn\n",
|
||||
np);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1071,7 +1071,7 @@ static int at91_pinctrl_parse_groups(struct device_node *np,
|
||||
const __be32 *list;
|
||||
int i, j;
|
||||
|
||||
dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
|
||||
dev_dbg(info->dev, "group(%d): %pOFn\n", index, np);
|
||||
|
||||
/* Initialise group */
|
||||
grp->name = np->name;
|
||||
@ -1122,7 +1122,7 @@ static int at91_pinctrl_parse_functions(struct device_node *np,
|
||||
static u32 grp_index;
|
||||
u32 i = 0;
|
||||
|
||||
dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
|
||||
dev_dbg(info->dev, "parse function(%d): %pOFn\n", index, np);
|
||||
|
||||
func = &info->functions[index];
|
||||
|
||||
@ -1487,7 +1487,7 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
|
||||
return 0;
|
||||
case IRQ_TYPE_NONE:
|
||||
default:
|
||||
pr_warn("AT91: No type for irq %d\n", gpio_to_irq(d->irq));
|
||||
pr_warn("AT91: No type for GPIO irq offset %d\n", d->irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1574,16 +1574,6 @@ void at91_pinctrl_gpio_resume(void)
|
||||
#define gpio_irq_set_wake NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static struct irq_chip gpio_irqchip = {
|
||||
.name = "GPIO",
|
||||
.irq_ack = gpio_irq_ack,
|
||||
.irq_disable = gpio_irq_mask,
|
||||
.irq_mask = gpio_irq_mask,
|
||||
.irq_unmask = gpio_irq_unmask,
|
||||
/* .irq_set_type is set dynamically */
|
||||
.irq_set_wake = gpio_irq_set_wake,
|
||||
};
|
||||
|
||||
static void gpio_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
@ -1624,12 +1614,22 @@ static int at91_gpio_of_irq_setup(struct platform_device *pdev,
|
||||
struct gpio_chip *gpiochip_prev = NULL;
|
||||
struct at91_gpio_chip *prev = NULL;
|
||||
struct irq_data *d = irq_get_irq_data(at91_gpio->pioc_virq);
|
||||
struct irq_chip *gpio_irqchip;
|
||||
int ret, i;
|
||||
|
||||
gpio_irqchip = devm_kzalloc(&pdev->dev, sizeof(*gpio_irqchip), GFP_KERNEL);
|
||||
if (!gpio_irqchip)
|
||||
return -ENOMEM;
|
||||
|
||||
at91_gpio->pioc_hwirq = irqd_to_hwirq(d);
|
||||
|
||||
/* Setup proper .irq_set_type function */
|
||||
gpio_irqchip.irq_set_type = at91_gpio->ops->irq_type;
|
||||
gpio_irqchip->name = "GPIO";
|
||||
gpio_irqchip->irq_ack = gpio_irq_ack;
|
||||
gpio_irqchip->irq_disable = gpio_irq_mask;
|
||||
gpio_irqchip->irq_mask = gpio_irq_mask;
|
||||
gpio_irqchip->irq_unmask = gpio_irq_unmask;
|
||||
gpio_irqchip->irq_set_wake = gpio_irq_set_wake,
|
||||
gpio_irqchip->irq_set_type = at91_gpio->ops->irq_type;
|
||||
|
||||
/* Disable irqs of this PIO controller */
|
||||
writel_relaxed(~0, at91_gpio->regbase + PIO_IDR);
|
||||
@ -1640,7 +1640,7 @@ static int at91_gpio_of_irq_setup(struct platform_device *pdev,
|
||||
* interrupt.
|
||||
*/
|
||||
ret = gpiochip_irqchip_add(&at91_gpio->chip,
|
||||
&gpio_irqchip,
|
||||
gpio_irqchip,
|
||||
0,
|
||||
handle_edge_irq,
|
||||
IRQ_TYPE_NONE);
|
||||
@ -1658,7 +1658,7 @@ static int at91_gpio_of_irq_setup(struct platform_device *pdev,
|
||||
if (!gpiochip_prev) {
|
||||
/* Then register the chain on the parent IRQ */
|
||||
gpiochip_set_chained_irqchip(&at91_gpio->chip,
|
||||
&gpio_irqchip,
|
||||
gpio_irqchip,
|
||||
at91_gpio->pioc_virq,
|
||||
gpio_irq_handler);
|
||||
return 0;
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Copyright (C) 2012 John Crispin <john@phrozen.org>
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
|
@ -591,13 +591,16 @@ static const unsigned int tvc_3512_pins[] = {
|
||||
319, /* TVC_DATA[1] */
|
||||
301, /* TVC_DATA[2] */
|
||||
283, /* TVC_DATA[3] */
|
||||
265, /* TVC_CLK */
|
||||
320, /* TVC_DATA[4] */
|
||||
302, /* TVC_DATA[5] */
|
||||
284, /* TVC_DATA[6] */
|
||||
266, /* TVC_DATA[7] */
|
||||
};
|
||||
|
||||
static const unsigned int tvc_clk_3512_pins[] = {
|
||||
265, /* TVC_CLK */
|
||||
};
|
||||
|
||||
/* NAND flash pins */
|
||||
static const unsigned int nflash_3512_pins[] = {
|
||||
199, 200, 201, 202, 216, 217, 218, 219, 220, 234, 235, 236, 237, 252,
|
||||
@ -629,7 +632,7 @@ static const unsigned int pflash_3512_pins_extended[] = {
|
||||
/* Serial flash pins CE0, CE1, DI, DO, CK */
|
||||
static const unsigned int sflash_3512_pins[] = { 230, 231, 232, 233, 211 };
|
||||
|
||||
/* The GPIO0A (0) pin overlap with TVC and extended parallel flash */
|
||||
/* The GPIO0A (0) pin overlap with TVC CLK and extended parallel flash */
|
||||
static const unsigned int gpio0a_3512_pins[] = { 265 };
|
||||
|
||||
/* The GPIO0B (1-4) pins overlap with TVC and ICE */
|
||||
@ -823,7 +826,13 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = {
|
||||
.num_pins = ARRAY_SIZE(tvc_3512_pins),
|
||||
/* Conflict with character LCD and ICE */
|
||||
.mask = LCD_PADS_ENABLE,
|
||||
.value = TVC_PADS_ENABLE | TVC_CLK_PAD_ENABLE,
|
||||
.value = TVC_PADS_ENABLE,
|
||||
},
|
||||
{
|
||||
.name = "tvcclkgrp",
|
||||
.pins = tvc_clk_3512_pins,
|
||||
.num_pins = ARRAY_SIZE(tvc_clk_3512_pins),
|
||||
.value = TVC_CLK_PAD_ENABLE,
|
||||
},
|
||||
/*
|
||||
* The construction is done such that it is possible to use a serial
|
||||
@ -860,8 +869,8 @@ static const struct gemini_pin_group gemini_3512_pin_groups[] = {
|
||||
.name = "gpio0agrp",
|
||||
.pins = gpio0a_3512_pins,
|
||||
.num_pins = ARRAY_SIZE(gpio0a_3512_pins),
|
||||
/* Conflict with TVC */
|
||||
.mask = TVC_PADS_ENABLE,
|
||||
/* Conflict with TVC CLK */
|
||||
.mask = TVC_CLK_PAD_ENABLE,
|
||||
},
|
||||
{
|
||||
.name = "gpio0bgrp",
|
||||
@ -1531,13 +1540,16 @@ static const unsigned int tvc_3516_pins[] = {
|
||||
311, /* TVC_DATA[1] */
|
||||
394, /* TVC_DATA[2] */
|
||||
374, /* TVC_DATA[3] */
|
||||
333, /* TVC_CLK */
|
||||
354, /* TVC_DATA[4] */
|
||||
395, /* TVC_DATA[5] */
|
||||
312, /* TVC_DATA[6] */
|
||||
334, /* TVC_DATA[7] */
|
||||
};
|
||||
|
||||
static const unsigned int tvc_clk_3516_pins[] = {
|
||||
333, /* TVC_CLK */
|
||||
};
|
||||
|
||||
/* NAND flash pins */
|
||||
static const unsigned int nflash_3516_pins[] = {
|
||||
243, 260, 261, 224, 280, 262, 281, 264, 300, 263, 282, 301, 320, 283,
|
||||
@ -1570,7 +1582,7 @@ static const unsigned int pflash_3516_pins_extended[] = {
|
||||
static const unsigned int sflash_3516_pins[] = { 296, 338, 295, 359, 339 };
|
||||
|
||||
/* The GPIO0A (0-4) pins overlap with TVC and extended parallel flash */
|
||||
static const unsigned int gpio0a_3516_pins[] = { 333, 354, 395, 312, 334 };
|
||||
static const unsigned int gpio0a_3516_pins[] = { 354, 395, 312, 334 };
|
||||
|
||||
/* The GPIO0B (5-7) pins overlap with ICE */
|
||||
static const unsigned int gpio0b_3516_pins[] = { 375, 396, 376 };
|
||||
@ -1602,6 +1614,9 @@ static const unsigned int gpio0j_3516_pins[] = { 359, 339 };
|
||||
/* The GPIO0K (30,31) pins overlap with NAND flash */
|
||||
static const unsigned int gpio0k_3516_pins[] = { 275, 298 };
|
||||
|
||||
/* The GPIO0L (0) pins overlap with TVC_CLK */
|
||||
static const unsigned int gpio0l_3516_pins[] = { 333 };
|
||||
|
||||
/* The GPIO1A (0-4) pins that overlap with IDE and parallel flash */
|
||||
static const unsigned int gpio1a_3516_pins[] = { 221, 200, 222, 201, 220 };
|
||||
|
||||
@ -1761,7 +1776,13 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = {
|
||||
.num_pins = ARRAY_SIZE(tvc_3516_pins),
|
||||
/* Conflict with character LCD */
|
||||
.mask = LCD_PADS_ENABLE,
|
||||
.value = TVC_PADS_ENABLE | TVC_CLK_PAD_ENABLE,
|
||||
.value = TVC_PADS_ENABLE,
|
||||
},
|
||||
{
|
||||
.name = "tvcclkgrp",
|
||||
.pins = tvc_clk_3516_pins,
|
||||
.num_pins = ARRAY_SIZE(tvc_clk_3516_pins),
|
||||
.value = TVC_CLK_PAD_ENABLE,
|
||||
},
|
||||
/*
|
||||
* The construction is done such that it is possible to use a serial
|
||||
@ -1872,6 +1893,13 @@ static const struct gemini_pin_group gemini_3516_pin_groups[] = {
|
||||
/* Conflict with parallel and NAND flash */
|
||||
.value = PFLASH_PADS_DISABLE | NAND_PADS_DISABLE,
|
||||
},
|
||||
{
|
||||
.name = "gpio0lgrp",
|
||||
.pins = gpio0l_3516_pins,
|
||||
.num_pins = ARRAY_SIZE(gpio0l_3516_pins),
|
||||
/* Conflict with TVE CLK */
|
||||
.mask = TVC_CLK_PAD_ENABLE,
|
||||
},
|
||||
{
|
||||
.name = "gpio1agrp",
|
||||
.pins = gpio1a_3516_pins,
|
||||
@ -2179,12 +2207,13 @@ static int gemini_pmx_set_mux(struct pinctrl_dev *pctldev,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev_info(pmx->dev,
|
||||
"ACTIVATE function \"%s\" with group \"%s\"\n",
|
||||
func->name, grp->name);
|
||||
dev_dbg(pmx->dev,
|
||||
"ACTIVATE function \"%s\" with group \"%s\"\n",
|
||||
func->name, grp->name);
|
||||
|
||||
regmap_read(pmx->map, GLOBAL_MISC_CTRL, &before);
|
||||
regmap_update_bits(pmx->map, GLOBAL_MISC_CTRL, grp->mask,
|
||||
regmap_update_bits(pmx->map, GLOBAL_MISC_CTRL,
|
||||
grp->mask | grp->value,
|
||||
grp->value);
|
||||
regmap_read(pmx->map, GLOBAL_MISC_CTRL, &after);
|
||||
|
||||
@ -2211,10 +2240,10 @@ static int gemini_pmx_set_mux(struct pinctrl_dev *pctldev,
|
||||
"GLOBAL MISC CTRL before: %08x, after %08x, expected %08x\n",
|
||||
before, after, expected);
|
||||
} else {
|
||||
dev_info(pmx->dev,
|
||||
"padgroup %s %s\n",
|
||||
gemini_padgroups[i],
|
||||
enabled ? "enabled" : "disabled");
|
||||
dev_dbg(pmx->dev,
|
||||
"padgroup %s %s\n",
|
||||
gemini_padgroups[i],
|
||||
enabled ? "enabled" : "disabled");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2233,10 +2262,10 @@ static int gemini_pmx_set_mux(struct pinctrl_dev *pctldev,
|
||||
"GLOBAL MISC CTRL before: %08x, after %08x, expected %08x\n",
|
||||
before, after, expected);
|
||||
} else {
|
||||
dev_info(pmx->dev,
|
||||
"padgroup %s %s\n",
|
||||
gemini_padgroups[i],
|
||||
enabled ? "enabled" : "disabled");
|
||||
dev_dbg(pmx->dev,
|
||||
"padgroup %s %s\n",
|
||||
gemini_padgroups[i],
|
||||
enabled ? "enabled" : "disabled");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2463,9 +2492,9 @@ static int gemini_pinconf_group_set(struct pinctrl_dev *pctldev,
|
||||
regmap_update_bits(pmx->map, GLOBAL_IODRIVE,
|
||||
grp->driving_mask,
|
||||
val);
|
||||
dev_info(pmx->dev,
|
||||
"set group %s to %d mA drive strength mask %08x val %08x\n",
|
||||
grp->name, arg, grp->driving_mask, val);
|
||||
dev_dbg(pmx->dev,
|
||||
"set group %s to %d mA drive strength mask %08x val %08x\n",
|
||||
grp->name, arg, grp->driving_mask, val);
|
||||
break;
|
||||
default:
|
||||
dev_err(pmx->dev, "invalid config param %04x\n", param);
|
||||
@ -2556,8 +2585,8 @@ static int gemini_pmx_probe(struct platform_device *pdev)
|
||||
/* Print initial state */
|
||||
tmp = val;
|
||||
for_each_set_bit(i, &tmp, PADS_MAXBIT) {
|
||||
dev_info(dev, "pad group %s %s\n", gemini_padgroups[i],
|
||||
(val & BIT(i)) ? "enabled" : "disabled");
|
||||
dev_dbg(dev, "pad group %s %s\n", gemini_padgroups[i],
|
||||
(val & BIT(i)) ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
/* Check if flash pin is set */
|
||||
|
@ -7,10 +7,11 @@
|
||||
*/
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
@ -24,6 +25,9 @@
|
||||
#include "pinconf.h"
|
||||
#include "pinmux.h"
|
||||
|
||||
#define GPIO_PIN 0x00
|
||||
#define GPIO_MSK 0x20
|
||||
|
||||
#define JZ4740_GPIO_DATA 0x10
|
||||
#define JZ4740_GPIO_PULL_DIS 0x30
|
||||
#define JZ4740_GPIO_FUNC 0x40
|
||||
@ -33,7 +37,6 @@
|
||||
#define JZ4740_GPIO_FLAG 0x80
|
||||
|
||||
#define JZ4770_GPIO_INT 0x10
|
||||
#define JZ4770_GPIO_MSK 0x20
|
||||
#define JZ4770_GPIO_PAT1 0x30
|
||||
#define JZ4770_GPIO_PAT0 0x40
|
||||
#define JZ4770_GPIO_FLAG 0x50
|
||||
@ -46,6 +49,7 @@
|
||||
|
||||
enum jz_version {
|
||||
ID_JZ4740,
|
||||
ID_JZ4725B,
|
||||
ID_JZ4770,
|
||||
ID_JZ4780,
|
||||
};
|
||||
@ -72,6 +76,13 @@ struct ingenic_pinctrl {
|
||||
const struct ingenic_chip_info *info;
|
||||
};
|
||||
|
||||
struct ingenic_gpio_chip {
|
||||
struct ingenic_pinctrl *jzpc;
|
||||
struct gpio_chip gc;
|
||||
struct irq_chip irq_chip;
|
||||
unsigned int irq, reg_base;
|
||||
};
|
||||
|
||||
static const u32 jz4740_pull_ups[4] = {
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||
};
|
||||
@ -205,6 +216,99 @@ static const struct ingenic_chip_info jz4740_chip_info = {
|
||||
.pull_downs = jz4740_pull_downs,
|
||||
};
|
||||
|
||||
static int jz4725b_mmc0_1bit_pins[] = { 0x48, 0x49, 0x5c, };
|
||||
static int jz4725b_mmc0_4bit_pins[] = { 0x5d, 0x5b, 0x56, };
|
||||
static int jz4725b_mmc1_1bit_pins[] = { 0x7a, 0x7b, 0x7c, };
|
||||
static int jz4725b_mmc1_4bit_pins[] = { 0x7d, 0x7e, 0x7f, };
|
||||
static int jz4725b_uart_data_pins[] = { 0x4c, 0x4d, };
|
||||
static int jz4725b_nand_cs1_pins[] = { 0x55, };
|
||||
static int jz4725b_nand_cs2_pins[] = { 0x56, };
|
||||
static int jz4725b_nand_cs3_pins[] = { 0x57, };
|
||||
static int jz4725b_nand_cs4_pins[] = { 0x58, };
|
||||
static int jz4725b_nand_cle_ale_pins[] = { 0x48, 0x49 };
|
||||
static int jz4725b_nand_fre_fwe_pins[] = { 0x5c, 0x5d };
|
||||
static int jz4725b_pwm_pwm0_pins[] = { 0x4a, };
|
||||
static int jz4725b_pwm_pwm1_pins[] = { 0x4b, };
|
||||
static int jz4725b_pwm_pwm2_pins[] = { 0x4c, };
|
||||
static int jz4725b_pwm_pwm3_pins[] = { 0x4d, };
|
||||
static int jz4725b_pwm_pwm4_pins[] = { 0x4e, };
|
||||
static int jz4725b_pwm_pwm5_pins[] = { 0x4f, };
|
||||
|
||||
static int jz4725b_mmc0_1bit_funcs[] = { 1, 1, 1, };
|
||||
static int jz4725b_mmc0_4bit_funcs[] = { 1, 0, 1, };
|
||||
static int jz4725b_mmc1_1bit_funcs[] = { 0, 0, 0, };
|
||||
static int jz4725b_mmc1_4bit_funcs[] = { 0, 0, 0, };
|
||||
static int jz4725b_uart_data_funcs[] = { 1, 1, };
|
||||
static int jz4725b_nand_cs1_funcs[] = { 0, };
|
||||
static int jz4725b_nand_cs2_funcs[] = { 0, };
|
||||
static int jz4725b_nand_cs3_funcs[] = { 0, };
|
||||
static int jz4725b_nand_cs4_funcs[] = { 0, };
|
||||
static int jz4725b_nand_cle_ale_funcs[] = { 0, 0, };
|
||||
static int jz4725b_nand_fre_fwe_funcs[] = { 0, 0, };
|
||||
static int jz4725b_pwm_pwm0_funcs[] = { 0, };
|
||||
static int jz4725b_pwm_pwm1_funcs[] = { 0, };
|
||||
static int jz4725b_pwm_pwm2_funcs[] = { 0, };
|
||||
static int jz4725b_pwm_pwm3_funcs[] = { 0, };
|
||||
static int jz4725b_pwm_pwm4_funcs[] = { 0, };
|
||||
static int jz4725b_pwm_pwm5_funcs[] = { 0, };
|
||||
|
||||
static const struct group_desc jz4725b_groups[] = {
|
||||
INGENIC_PIN_GROUP("mmc0-1bit", jz4725b_mmc0_1bit),
|
||||
INGENIC_PIN_GROUP("mmc0-4bit", jz4725b_mmc0_4bit),
|
||||
INGENIC_PIN_GROUP("mmc1-1bit", jz4725b_mmc1_1bit),
|
||||
INGENIC_PIN_GROUP("mmc1-4bit", jz4725b_mmc1_4bit),
|
||||
INGENIC_PIN_GROUP("uart-data", jz4725b_uart_data),
|
||||
INGENIC_PIN_GROUP("nand-cs1", jz4725b_nand_cs1),
|
||||
INGENIC_PIN_GROUP("nand-cs2", jz4725b_nand_cs2),
|
||||
INGENIC_PIN_GROUP("nand-cs3", jz4725b_nand_cs3),
|
||||
INGENIC_PIN_GROUP("nand-cs4", jz4725b_nand_cs4),
|
||||
INGENIC_PIN_GROUP("nand-cle-ale", jz4725b_nand_cle_ale),
|
||||
INGENIC_PIN_GROUP("nand-fre-fwe", jz4725b_nand_fre_fwe),
|
||||
INGENIC_PIN_GROUP("pwm0", jz4725b_pwm_pwm0),
|
||||
INGENIC_PIN_GROUP("pwm1", jz4725b_pwm_pwm1),
|
||||
INGENIC_PIN_GROUP("pwm2", jz4725b_pwm_pwm2),
|
||||
INGENIC_PIN_GROUP("pwm3", jz4725b_pwm_pwm3),
|
||||
INGENIC_PIN_GROUP("pwm4", jz4725b_pwm_pwm4),
|
||||
INGENIC_PIN_GROUP("pwm5", jz4725b_pwm_pwm5),
|
||||
};
|
||||
|
||||
static const char *jz4725b_mmc0_groups[] = { "mmc0-1bit", "mmc0-4bit", };
|
||||
static const char *jz4725b_mmc1_groups[] = { "mmc1-1bit", "mmc1-4bit", };
|
||||
static const char *jz4725b_uart_groups[] = { "uart-data", };
|
||||
static const char *jz4725b_nand_groups[] = {
|
||||
"nand-cs1", "nand-cs2", "nand-cs3", "nand-cs4",
|
||||
"nand-cle-ale", "nand-fre-fwe",
|
||||
};
|
||||
static const char *jz4725b_pwm0_groups[] = { "pwm0", };
|
||||
static const char *jz4725b_pwm1_groups[] = { "pwm1", };
|
||||
static const char *jz4725b_pwm2_groups[] = { "pwm2", };
|
||||
static const char *jz4725b_pwm3_groups[] = { "pwm3", };
|
||||
static const char *jz4725b_pwm4_groups[] = { "pwm4", };
|
||||
static const char *jz4725b_pwm5_groups[] = { "pwm5", };
|
||||
|
||||
static const struct function_desc jz4725b_functions[] = {
|
||||
{ "mmc0", jz4725b_mmc0_groups, ARRAY_SIZE(jz4725b_mmc0_groups), },
|
||||
{ "mmc1", jz4725b_mmc1_groups, ARRAY_SIZE(jz4725b_mmc1_groups), },
|
||||
{ "uart", jz4725b_uart_groups, ARRAY_SIZE(jz4725b_uart_groups), },
|
||||
{ "nand", jz4725b_nand_groups, ARRAY_SIZE(jz4725b_nand_groups), },
|
||||
{ "pwm0", jz4725b_pwm0_groups, ARRAY_SIZE(jz4725b_pwm0_groups), },
|
||||
{ "pwm1", jz4725b_pwm1_groups, ARRAY_SIZE(jz4725b_pwm1_groups), },
|
||||
{ "pwm2", jz4725b_pwm2_groups, ARRAY_SIZE(jz4725b_pwm2_groups), },
|
||||
{ "pwm3", jz4725b_pwm3_groups, ARRAY_SIZE(jz4725b_pwm3_groups), },
|
||||
{ "pwm4", jz4725b_pwm4_groups, ARRAY_SIZE(jz4725b_pwm4_groups), },
|
||||
{ "pwm5", jz4725b_pwm5_groups, ARRAY_SIZE(jz4725b_pwm5_groups), },
|
||||
};
|
||||
|
||||
static const struct ingenic_chip_info jz4725b_chip_info = {
|
||||
.num_chips = 4,
|
||||
.groups = jz4725b_groups,
|
||||
.num_groups = ARRAY_SIZE(jz4725b_groups),
|
||||
.functions = jz4725b_functions,
|
||||
.num_functions = ARRAY_SIZE(jz4725b_functions),
|
||||
.pull_ups = jz4740_pull_ups,
|
||||
.pull_downs = jz4740_pull_downs,
|
||||
};
|
||||
|
||||
static const u32 jz4770_pull_ups[6] = {
|
||||
0x3fffffff, 0xfff0030c, 0xffffffff, 0xffff4fff, 0xfffffb7c, 0xffa7f00f,
|
||||
};
|
||||
@ -438,6 +542,235 @@ static const struct ingenic_chip_info jz4770_chip_info = {
|
||||
.pull_downs = jz4770_pull_downs,
|
||||
};
|
||||
|
||||
static u32 gpio_ingenic_read_reg(struct ingenic_gpio_chip *jzgc, u8 reg)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
regmap_read(jzgc->jzpc->map, jzgc->reg_base + reg, &val);
|
||||
|
||||
return (u32) val;
|
||||
}
|
||||
|
||||
static void gpio_ingenic_set_bit(struct ingenic_gpio_chip *jzgc,
|
||||
u8 reg, u8 offset, bool set)
|
||||
{
|
||||
if (set)
|
||||
reg = REG_SET(reg);
|
||||
else
|
||||
reg = REG_CLEAR(reg);
|
||||
|
||||
regmap_write(jzgc->jzpc->map, jzgc->reg_base + reg, BIT(offset));
|
||||
}
|
||||
|
||||
static inline bool ingenic_gpio_get_value(struct ingenic_gpio_chip *jzgc,
|
||||
u8 offset)
|
||||
{
|
||||
unsigned int val = gpio_ingenic_read_reg(jzgc, GPIO_PIN);
|
||||
|
||||
return !!(val & BIT(offset));
|
||||
}
|
||||
|
||||
static void ingenic_gpio_set_value(struct ingenic_gpio_chip *jzgc,
|
||||
u8 offset, int value)
|
||||
{
|
||||
if (jzgc->jzpc->version >= ID_JZ4770)
|
||||
gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_PAT0, offset, !!value);
|
||||
else
|
||||
gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_DATA, offset, !!value);
|
||||
}
|
||||
|
||||
static void irq_set_type(struct ingenic_gpio_chip *jzgc,
|
||||
u8 offset, unsigned int type)
|
||||
{
|
||||
u8 reg1, reg2;
|
||||
|
||||
if (jzgc->jzpc->version >= ID_JZ4770) {
|
||||
reg1 = JZ4770_GPIO_PAT1;
|
||||
reg2 = JZ4770_GPIO_PAT0;
|
||||
} else {
|
||||
reg1 = JZ4740_GPIO_TRIG;
|
||||
reg2 = JZ4740_GPIO_DIR;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
gpio_ingenic_set_bit(jzgc, reg2, offset, true);
|
||||
gpio_ingenic_set_bit(jzgc, reg1, offset, true);
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
gpio_ingenic_set_bit(jzgc, reg2, offset, false);
|
||||
gpio_ingenic_set_bit(jzgc, reg1, offset, true);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
gpio_ingenic_set_bit(jzgc, reg2, offset, true);
|
||||
gpio_ingenic_set_bit(jzgc, reg1, offset, false);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
default:
|
||||
gpio_ingenic_set_bit(jzgc, reg2, offset, false);
|
||||
gpio_ingenic_set_bit(jzgc, reg1, offset, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ingenic_gpio_irq_mask(struct irq_data *irqd)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
|
||||
gpio_ingenic_set_bit(jzgc, GPIO_MSK, irqd->hwirq, true);
|
||||
}
|
||||
|
||||
static void ingenic_gpio_irq_unmask(struct irq_data *irqd)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
|
||||
gpio_ingenic_set_bit(jzgc, GPIO_MSK, irqd->hwirq, false);
|
||||
}
|
||||
|
||||
static void ingenic_gpio_irq_enable(struct irq_data *irqd)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
int irq = irqd->hwirq;
|
||||
|
||||
if (jzgc->jzpc->version >= ID_JZ4770)
|
||||
gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_INT, irq, true);
|
||||
else
|
||||
gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, true);
|
||||
|
||||
ingenic_gpio_irq_unmask(irqd);
|
||||
}
|
||||
|
||||
static void ingenic_gpio_irq_disable(struct irq_data *irqd)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
int irq = irqd->hwirq;
|
||||
|
||||
ingenic_gpio_irq_mask(irqd);
|
||||
|
||||
if (jzgc->jzpc->version >= ID_JZ4770)
|
||||
gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_INT, irq, false);
|
||||
else
|
||||
gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, false);
|
||||
}
|
||||
|
||||
static void ingenic_gpio_irq_ack(struct irq_data *irqd)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
int irq = irqd->hwirq;
|
||||
bool high;
|
||||
|
||||
if (irqd_get_trigger_type(irqd) == IRQ_TYPE_EDGE_BOTH) {
|
||||
/*
|
||||
* Switch to an interrupt for the opposite edge to the one that
|
||||
* triggered the interrupt being ACKed.
|
||||
*/
|
||||
high = ingenic_gpio_get_value(jzgc, irq);
|
||||
if (high)
|
||||
irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_FALLING);
|
||||
else
|
||||
irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_RISING);
|
||||
}
|
||||
|
||||
if (jzgc->jzpc->version >= ID_JZ4770)
|
||||
gpio_ingenic_set_bit(jzgc, JZ4770_GPIO_FLAG, irq, false);
|
||||
else
|
||||
gpio_ingenic_set_bit(jzgc, JZ4740_GPIO_DATA, irq, true);
|
||||
}
|
||||
|
||||
static int ingenic_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
|
||||
switch (type) {
|
||||
case IRQ_TYPE_EDGE_BOTH:
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
irq_set_handler_locked(irqd, handle_edge_irq);
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
irq_set_handler_locked(irqd, handle_level_irq);
|
||||
break;
|
||||
default:
|
||||
irq_set_handler_locked(irqd, handle_bad_irq);
|
||||
}
|
||||
|
||||
if (type == IRQ_TYPE_EDGE_BOTH) {
|
||||
/*
|
||||
* The hardware does not support interrupts on both edges. The
|
||||
* best we can do is to set up a single-edge interrupt and then
|
||||
* switch to the opposing edge when ACKing the interrupt.
|
||||
*/
|
||||
bool high = ingenic_gpio_get_value(jzgc, irqd->hwirq);
|
||||
|
||||
type = high ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
|
||||
}
|
||||
|
||||
irq_set_type(jzgc, irqd->hwirq, type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ingenic_gpio_irq_set_wake(struct irq_data *irqd, unsigned int on)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
|
||||
return irq_set_irq_wake(jzgc->irq, on);
|
||||
}
|
||||
|
||||
static void ingenic_gpio_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
struct irq_chip *irq_chip = irq_data_get_irq_chip(&desc->irq_data);
|
||||
unsigned long flag, i;
|
||||
|
||||
chained_irq_enter(irq_chip, desc);
|
||||
|
||||
if (jzgc->jzpc->version >= ID_JZ4770)
|
||||
flag = gpio_ingenic_read_reg(jzgc, JZ4770_GPIO_FLAG);
|
||||
else
|
||||
flag = gpio_ingenic_read_reg(jzgc, JZ4740_GPIO_FLAG);
|
||||
|
||||
for_each_set_bit(i, &flag, 32)
|
||||
generic_handle_irq(irq_linear_revmap(gc->irq.domain, i));
|
||||
chained_irq_exit(irq_chip, desc);
|
||||
}
|
||||
|
||||
static void ingenic_gpio_set(struct gpio_chip *gc,
|
||||
unsigned int offset, int value)
|
||||
{
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
|
||||
ingenic_gpio_set_value(jzgc, offset, value);
|
||||
}
|
||||
|
||||
static int ingenic_gpio_get(struct gpio_chip *gc, unsigned int offset)
|
||||
{
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
|
||||
return (int) ingenic_gpio_get_value(jzgc, offset);
|
||||
}
|
||||
|
||||
static int ingenic_gpio_direction_input(struct gpio_chip *gc,
|
||||
unsigned int offset)
|
||||
{
|
||||
return pinctrl_gpio_direction_input(gc->base + offset);
|
||||
}
|
||||
|
||||
static int ingenic_gpio_direction_output(struct gpio_chip *gc,
|
||||
unsigned int offset, int value)
|
||||
{
|
||||
ingenic_gpio_set(gc, offset, value);
|
||||
return pinctrl_gpio_direction_output(gc->base + offset);
|
||||
}
|
||||
|
||||
static inline void ingenic_config_pin(struct ingenic_pinctrl *jzpc,
|
||||
unsigned int pin, u8 reg, bool set)
|
||||
{
|
||||
@ -460,6 +793,21 @@ static inline bool ingenic_get_pin_config(struct ingenic_pinctrl *jzpc,
|
||||
return val & BIT(idx);
|
||||
}
|
||||
|
||||
static int ingenic_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
|
||||
{
|
||||
struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
|
||||
struct ingenic_pinctrl *jzpc = jzgc->jzpc;
|
||||
unsigned int pin = gc->base + offset;
|
||||
|
||||
if (jzpc->version >= ID_JZ4770)
|
||||
return ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PAT1);
|
||||
|
||||
if (ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_SELECT))
|
||||
return true;
|
||||
|
||||
return !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_DIR);
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops ingenic_pctlops = {
|
||||
.get_groups_count = pinctrl_generic_get_group_count,
|
||||
.get_group_name = pinctrl_generic_get_group_name,
|
||||
@ -479,7 +827,7 @@ static int ingenic_pinmux_set_pin_fn(struct ingenic_pinctrl *jzpc,
|
||||
|
||||
if (jzpc->version >= ID_JZ4770) {
|
||||
ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
|
||||
ingenic_config_pin(jzpc, pin, JZ4770_GPIO_MSK, false);
|
||||
ingenic_config_pin(jzpc, pin, GPIO_MSK, false);
|
||||
ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, func & 0x2);
|
||||
ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT0, func & 0x1);
|
||||
} else {
|
||||
@ -532,7 +880,7 @@ static int ingenic_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
|
||||
if (jzpc->version >= ID_JZ4770) {
|
||||
ingenic_config_pin(jzpc, pin, JZ4770_GPIO_INT, false);
|
||||
ingenic_config_pin(jzpc, pin, JZ4770_GPIO_MSK, true);
|
||||
ingenic_config_pin(jzpc, pin, GPIO_MSK, true);
|
||||
ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PAT1, input);
|
||||
} else {
|
||||
ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, false);
|
||||
@ -712,12 +1060,95 @@ static const struct regmap_config ingenic_pinctrl_regmap_config = {
|
||||
|
||||
static const struct of_device_id ingenic_pinctrl_of_match[] = {
|
||||
{ .compatible = "ingenic,jz4740-pinctrl", .data = (void *) ID_JZ4740 },
|
||||
{ .compatible = "ingenic,jz4725b-pinctrl", .data = (void *)ID_JZ4725B },
|
||||
{ .compatible = "ingenic,jz4770-pinctrl", .data = (void *) ID_JZ4770 },
|
||||
{ .compatible = "ingenic,jz4780-pinctrl", .data = (void *) ID_JZ4780 },
|
||||
{},
|
||||
};
|
||||
|
||||
static int ingenic_pinctrl_probe(struct platform_device *pdev)
|
||||
static const struct of_device_id ingenic_gpio_of_match[] __initconst = {
|
||||
{ .compatible = "ingenic,jz4740-gpio", },
|
||||
{ .compatible = "ingenic,jz4770-gpio", },
|
||||
{ .compatible = "ingenic,jz4780-gpio", },
|
||||
{},
|
||||
};
|
||||
|
||||
static int __init ingenic_gpio_probe(struct ingenic_pinctrl *jzpc,
|
||||
struct device_node *node)
|
||||
{
|
||||
struct ingenic_gpio_chip *jzgc;
|
||||
struct device *dev = jzpc->dev;
|
||||
unsigned int bank;
|
||||
int err;
|
||||
|
||||
err = of_property_read_u32(node, "reg", &bank);
|
||||
if (err) {
|
||||
dev_err(dev, "Cannot read \"reg\" property: %i\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
jzgc = devm_kzalloc(dev, sizeof(*jzgc), GFP_KERNEL);
|
||||
if (!jzgc)
|
||||
return -ENOMEM;
|
||||
|
||||
jzgc->jzpc = jzpc;
|
||||
jzgc->reg_base = bank * 0x100;
|
||||
|
||||
jzgc->gc.label = devm_kasprintf(dev, GFP_KERNEL, "GPIO%c", 'A' + bank);
|
||||
if (!jzgc->gc.label)
|
||||
return -ENOMEM;
|
||||
|
||||
/* DO NOT EXPAND THIS: FOR BACKWARD GPIO NUMBERSPACE COMPATIBIBILITY
|
||||
* ONLY: WORK TO TRANSITION CONSUMERS TO USE THE GPIO DESCRIPTOR API IN
|
||||
* <linux/gpio/consumer.h> INSTEAD.
|
||||
*/
|
||||
jzgc->gc.base = bank * 32;
|
||||
|
||||
jzgc->gc.ngpio = 32;
|
||||
jzgc->gc.parent = dev;
|
||||
jzgc->gc.of_node = node;
|
||||
jzgc->gc.owner = THIS_MODULE;
|
||||
|
||||
jzgc->gc.set = ingenic_gpio_set;
|
||||
jzgc->gc.get = ingenic_gpio_get;
|
||||
jzgc->gc.direction_input = ingenic_gpio_direction_input;
|
||||
jzgc->gc.direction_output = ingenic_gpio_direction_output;
|
||||
jzgc->gc.get_direction = ingenic_gpio_get_direction;
|
||||
|
||||
if (of_property_read_bool(node, "gpio-ranges")) {
|
||||
jzgc->gc.request = gpiochip_generic_request;
|
||||
jzgc->gc.free = gpiochip_generic_free;
|
||||
}
|
||||
|
||||
err = devm_gpiochip_add_data(dev, &jzgc->gc, jzgc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
jzgc->irq = irq_of_parse_and_map(node, 0);
|
||||
if (!jzgc->irq)
|
||||
return -EINVAL;
|
||||
|
||||
jzgc->irq_chip.name = jzgc->gc.label;
|
||||
jzgc->irq_chip.irq_enable = ingenic_gpio_irq_enable;
|
||||
jzgc->irq_chip.irq_disable = ingenic_gpio_irq_disable;
|
||||
jzgc->irq_chip.irq_unmask = ingenic_gpio_irq_unmask;
|
||||
jzgc->irq_chip.irq_mask = ingenic_gpio_irq_mask;
|
||||
jzgc->irq_chip.irq_ack = ingenic_gpio_irq_ack;
|
||||
jzgc->irq_chip.irq_set_type = ingenic_gpio_irq_set_type;
|
||||
jzgc->irq_chip.irq_set_wake = ingenic_gpio_irq_set_wake;
|
||||
jzgc->irq_chip.flags = IRQCHIP_MASK_ON_SUSPEND;
|
||||
|
||||
err = gpiochip_irqchip_add(&jzgc->gc, &jzgc->irq_chip, 0,
|
||||
handle_level_irq, IRQ_TYPE_NONE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
gpiochip_set_chained_irqchip(&jzgc->gc, &jzgc->irq_chip,
|
||||
jzgc->irq, ingenic_gpio_irq_handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init ingenic_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct ingenic_pinctrl *jzpc;
|
||||
@ -727,6 +1158,7 @@ static int ingenic_pinctrl_probe(struct platform_device *pdev)
|
||||
const struct of_device_id *of_id = of_match_device(
|
||||
ingenic_pinctrl_of_match, dev);
|
||||
const struct ingenic_chip_info *chip_info;
|
||||
struct device_node *node;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
@ -755,6 +1187,8 @@ static int ingenic_pinctrl_probe(struct platform_device *pdev)
|
||||
|
||||
if (jzpc->version >= ID_JZ4770)
|
||||
chip_info = &jz4770_chip_info;
|
||||
else if (jzpc->version >= ID_JZ4725B)
|
||||
chip_info = &jz4725b_chip_info;
|
||||
else
|
||||
chip_info = &jz4740_chip_info;
|
||||
jzpc->info = chip_info;
|
||||
@ -815,11 +1249,11 @@ static int ingenic_pinctrl_probe(struct platform_device *pdev)
|
||||
|
||||
dev_set_drvdata(dev, jzpc->map);
|
||||
|
||||
if (dev->of_node) {
|
||||
err = of_platform_populate(dev->of_node, NULL, NULL, dev);
|
||||
if (err) {
|
||||
dev_err(dev, "Failed to probe GPIO devices\n");
|
||||
return err;
|
||||
for_each_child_of_node(dev->of_node, node) {
|
||||
if (of_match_node(ingenic_gpio_of_match, node)) {
|
||||
err = ingenic_gpio_probe(jzpc, node);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
@ -828,6 +1262,7 @@ static int ingenic_pinctrl_probe(struct platform_device *pdev)
|
||||
|
||||
static const struct platform_device_id ingenic_pinctrl_ids[] = {
|
||||
{ "jz4740-pinctrl", ID_JZ4740 },
|
||||
{ "jz4725b-pinctrl", ID_JZ4725B },
|
||||
{ "jz4770-pinctrl", ID_JZ4770 },
|
||||
{ "jz4780-pinctrl", ID_JZ4780 },
|
||||
{},
|
||||
@ -837,14 +1272,13 @@ static struct platform_driver ingenic_pinctrl_driver = {
|
||||
.driver = {
|
||||
.name = "pinctrl-ingenic",
|
||||
.of_match_table = of_match_ptr(ingenic_pinctrl_of_match),
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = ingenic_pinctrl_probe,
|
||||
.id_table = ingenic_pinctrl_ids,
|
||||
};
|
||||
|
||||
static int __init ingenic_pinctrl_drv_register(void)
|
||||
{
|
||||
return platform_driver_register(&ingenic_pinctrl_driver);
|
||||
return platform_driver_probe(&ingenic_pinctrl_driver,
|
||||
ingenic_pinctrl_probe);
|
||||
}
|
||||
postcore_initcall(ingenic_pinctrl_drv_register);
|
||||
subsys_initcall(ingenic_pinctrl_drv_register);
|
||||
|
@ -80,14 +80,14 @@ static void ltq_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
int ret, i;
|
||||
|
||||
if (!pins && !groups) {
|
||||
dev_err(pctldev->dev, "%s defines neither pins nor groups\n",
|
||||
np->name);
|
||||
dev_err(pctldev->dev, "%pOFn defines neither pins nor groups\n",
|
||||
np);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pins && groups) {
|
||||
dev_err(pctldev->dev, "%s defines both pins and groups\n",
|
||||
np->name);
|
||||
dev_err(pctldev->dev, "%pOFn defines both pins and groups\n",
|
||||
np);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -844,8 +844,11 @@ static int lpc18xx_pconf_get_pin(struct pinctrl_dev *pctldev, unsigned param,
|
||||
*arg = (reg & LPC18XX_SCU_PIN_EHD_MASK) >> LPC18XX_SCU_PIN_EHD_POS;
|
||||
switch (*arg) {
|
||||
case 3: *arg += 5;
|
||||
/* fall through */
|
||||
case 2: *arg += 5;
|
||||
/* fall through */
|
||||
case 1: *arg += 3;
|
||||
/* fall through */
|
||||
case 0: *arg += 4;
|
||||
}
|
||||
break;
|
||||
@ -1060,8 +1063,11 @@ static int lpc18xx_pconf_set_pin(struct pinctrl_dev *pctldev, unsigned param,
|
||||
|
||||
switch (param_val) {
|
||||
case 20: param_val -= 5;
|
||||
/* fall through */
|
||||
case 14: param_val -= 5;
|
||||
/* fall through */
|
||||
case 8: param_val -= 3;
|
||||
/* fall through */
|
||||
case 4: param_val -= 4;
|
||||
break;
|
||||
default:
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/mcp23s08.h>
|
||||
|
@ -9,7 +9,6 @@
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
@ -501,8 +501,8 @@ static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
*/
|
||||
grp = pinctrl_name_to_group(info, np->name);
|
||||
if (!grp) {
|
||||
dev_err(info->dev, "unable to find group for node %s\n",
|
||||
np->name);
|
||||
dev_err(info->dev, "unable to find group for node %pOFn\n",
|
||||
np);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -2454,7 +2454,7 @@ static int rockchip_pinctrl_parse_groups(struct device_node *np,
|
||||
int i, j;
|
||||
int ret;
|
||||
|
||||
dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
|
||||
dev_dbg(info->dev, "group(%d): %pOFn\n", index, np);
|
||||
|
||||
/* Initialise group */
|
||||
grp->name = np->name;
|
||||
@ -2519,7 +2519,7 @@ static int rockchip_pinctrl_parse_functions(struct device_node *np,
|
||||
static u32 grp_index;
|
||||
u32 i = 0;
|
||||
|
||||
dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
|
||||
dev_dbg(info->dev, "parse function(%d): %pOFn\n", index, np);
|
||||
|
||||
func = &info->functions[index];
|
||||
|
||||
|
@ -1,11 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Combined GPIO and pin controller support for Renesas RZ/A1 (r7s72100) SoC
|
||||
*
|
||||
* Copyright (C) 2017 Jacopo Mondi
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -930,8 +927,8 @@ static int rza1_parse_pinmux_node(struct rza1_pinctrl *rza1_pctl,
|
||||
&npin_configs);
|
||||
if (ret) {
|
||||
dev_err(rza1_pctl->dev,
|
||||
"Unable to parse pin configuration options for %s\n",
|
||||
np->name);
|
||||
"Unable to parse pin configuration options for %pOFn\n",
|
||||
np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1226,8 +1223,8 @@ static int rza1_parse_gpiochip(struct rza1_pinctrl *rza1_pctl,
|
||||
|
||||
*chip = rza1_gpiochip_template;
|
||||
chip->base = -1;
|
||||
chip->label = devm_kasprintf(rza1_pctl->dev, GFP_KERNEL, "%s",
|
||||
np->name);
|
||||
chip->label = devm_kasprintf(rza1_pctl->dev, GFP_KERNEL, "%pOFn",
|
||||
np);
|
||||
chip->ngpio = of_args.args[2];
|
||||
chip->of_node = np;
|
||||
chip->parent = rza1_pctl->dev;
|
||||
@ -1287,7 +1284,7 @@ static int rza1_gpio_register(struct rza1_pinctrl *rza1_pctl)
|
||||
ret = rza1_parse_gpiochip(rza1_pctl, child, &gpio_chips[i],
|
||||
&gpio_ranges[i]);
|
||||
if (ret)
|
||||
goto gpiochip_remove;
|
||||
return ret;
|
||||
|
||||
++i;
|
||||
}
|
||||
@ -1295,12 +1292,6 @@ static int rza1_gpio_register(struct rza1_pinctrl *rza1_pctl)
|
||||
dev_info(rza1_pctl->dev, "Registered %u gpio controllers\n", i);
|
||||
|
||||
return 0;
|
||||
|
||||
gpiochip_remove:
|
||||
for (; i > 0; i--)
|
||||
devm_gpiochip_remove(rza1_pctl->dev, &gpio_chips[i - 1]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
947
drivers/pinctrl/pinctrl-rzn1.c
Normal file
947
drivers/pinctrl/pinctrl-rzn1.c
Normal file
@ -0,0 +1,947 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2014-2018 Renesas Electronics Europe Limited
|
||||
*
|
||||
* Phil Edworthy <phil.edworthy@renesas.com>
|
||||
* Based on a driver originally written by Michel Pollet at Renesas.
|
||||
*/
|
||||
|
||||
#include <dt-bindings/pinctrl/rzn1-pinctrl.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include "core.h"
|
||||
#include "pinconf.h"
|
||||
#include "pinctrl-utils.h"
|
||||
|
||||
/* Field positions and masks in the pinmux registers */
|
||||
#define RZN1_L1_PIN_DRIVE_STRENGTH 10
|
||||
#define RZN1_L1_PIN_DRIVE_STRENGTH_4MA 0
|
||||
#define RZN1_L1_PIN_DRIVE_STRENGTH_6MA 1
|
||||
#define RZN1_L1_PIN_DRIVE_STRENGTH_8MA 2
|
||||
#define RZN1_L1_PIN_DRIVE_STRENGTH_12MA 3
|
||||
#define RZN1_L1_PIN_PULL 8
|
||||
#define RZN1_L1_PIN_PULL_NONE 0
|
||||
#define RZN1_L1_PIN_PULL_UP 1
|
||||
#define RZN1_L1_PIN_PULL_DOWN 3
|
||||
#define RZN1_L1_FUNCTION 0
|
||||
#define RZN1_L1_FUNC_MASK 0xf
|
||||
#define RZN1_L1_FUNCTION_L2 0xf
|
||||
|
||||
/*
|
||||
* The hardware manual describes two levels of multiplexing, but it's more
|
||||
* logical to think of the hardware as three levels, with level 3 consisting of
|
||||
* the multiplexing for Ethernet MDIO signals.
|
||||
*
|
||||
* Level 1 functions go from 0 to 9, with level 1 function '15' (0xf) specifying
|
||||
* that level 2 functions are used instead. Level 2 has a lot more options,
|
||||
* going from 0 to 61. Level 3 allows selection of MDIO functions which can be
|
||||
* floating, or one of seven internal peripherals. Unfortunately, there are two
|
||||
* level 2 functions that can select MDIO, and two MDIO channels so we have four
|
||||
* sets of level 3 functions.
|
||||
*
|
||||
* For this driver, we've compounded the numbers together, so:
|
||||
* 0 to 9 is level 1
|
||||
* 10 to 71 is 10 + level 2 number
|
||||
* 72 to 79 is 72 + MDIO0 source for level 2 MDIO function.
|
||||
* 80 to 87 is 80 + MDIO0 source for level 2 MDIO_E1 function.
|
||||
* 88 to 95 is 88 + MDIO1 source for level 2 MDIO function.
|
||||
* 96 to 103 is 96 + MDIO1 source for level 2 MDIO_E1 function.
|
||||
* Examples:
|
||||
* Function 28 corresponds UART0
|
||||
* Function 73 corresponds to MDIO0 to GMAC0
|
||||
*
|
||||
* There are 170 configurable pins (called PL_GPIO in the datasheet).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Structure detailing the HW registers on the RZ/N1 devices.
|
||||
* Both the Level 1 mux registers and Level 2 mux registers have the same
|
||||
* structure. The only difference is that Level 2 has additional MDIO registers
|
||||
* at the end.
|
||||
*/
|
||||
struct rzn1_pinctrl_regs {
|
||||
u32 conf[170];
|
||||
u32 pad0[86];
|
||||
u32 status_protect; /* 0x400 */
|
||||
/* MDIO mux registers, level2 only */
|
||||
u32 l2_mdio[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rzn1_pmx_func - describes rzn1 pinmux functions
|
||||
* @name: the name of this specific function
|
||||
* @groups: corresponding pin groups
|
||||
* @num_groups: the number of groups
|
||||
*/
|
||||
struct rzn1_pmx_func {
|
||||
const char *name;
|
||||
const char **groups;
|
||||
unsigned int num_groups;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct rzn1_pin_group - describes an rzn1 pin group
|
||||
* @name: the name of this specific pin group
|
||||
* @func: the name of the function selected by this group
|
||||
* @npins: the number of pins in this group array, i.e. the number of
|
||||
* elements in .pins so we can iterate over that array
|
||||
* @pins: array of pins. Needed due to pinctrl_ops.get_group_pins()
|
||||
* @pin_ids: array of pin_ids, i.e. the value used to select the mux
|
||||
*/
|
||||
struct rzn1_pin_group {
|
||||
const char *name;
|
||||
const char *func;
|
||||
unsigned int npins;
|
||||
unsigned int *pins;
|
||||
u8 *pin_ids;
|
||||
};
|
||||
|
||||
struct rzn1_pinctrl {
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
struct pinctrl_dev *pctl;
|
||||
struct rzn1_pinctrl_regs __iomem *lev1;
|
||||
struct rzn1_pinctrl_regs __iomem *lev2;
|
||||
u32 lev1_protect_phys;
|
||||
u32 lev2_protect_phys;
|
||||
u32 mdio_func[2];
|
||||
|
||||
struct rzn1_pin_group *groups;
|
||||
unsigned int ngroups;
|
||||
|
||||
struct rzn1_pmx_func *functions;
|
||||
unsigned int nfunctions;
|
||||
};
|
||||
|
||||
#define RZN1_PINS_PROP "pinmux"
|
||||
|
||||
#define RZN1_PIN(pin) PINCTRL_PIN(pin, "pl_gpio"#pin)
|
||||
|
||||
static const struct pinctrl_pin_desc rzn1_pins[] = {
|
||||
RZN1_PIN(0), RZN1_PIN(1), RZN1_PIN(2), RZN1_PIN(3), RZN1_PIN(4),
|
||||
RZN1_PIN(5), RZN1_PIN(6), RZN1_PIN(7), RZN1_PIN(8), RZN1_PIN(9),
|
||||
RZN1_PIN(10), RZN1_PIN(11), RZN1_PIN(12), RZN1_PIN(13), RZN1_PIN(14),
|
||||
RZN1_PIN(15), RZN1_PIN(16), RZN1_PIN(17), RZN1_PIN(18), RZN1_PIN(19),
|
||||
RZN1_PIN(20), RZN1_PIN(21), RZN1_PIN(22), RZN1_PIN(23), RZN1_PIN(24),
|
||||
RZN1_PIN(25), RZN1_PIN(26), RZN1_PIN(27), RZN1_PIN(28), RZN1_PIN(29),
|
||||
RZN1_PIN(30), RZN1_PIN(31), RZN1_PIN(32), RZN1_PIN(33), RZN1_PIN(34),
|
||||
RZN1_PIN(35), RZN1_PIN(36), RZN1_PIN(37), RZN1_PIN(38), RZN1_PIN(39),
|
||||
RZN1_PIN(40), RZN1_PIN(41), RZN1_PIN(42), RZN1_PIN(43), RZN1_PIN(44),
|
||||
RZN1_PIN(45), RZN1_PIN(46), RZN1_PIN(47), RZN1_PIN(48), RZN1_PIN(49),
|
||||
RZN1_PIN(50), RZN1_PIN(51), RZN1_PIN(52), RZN1_PIN(53), RZN1_PIN(54),
|
||||
RZN1_PIN(55), RZN1_PIN(56), RZN1_PIN(57), RZN1_PIN(58), RZN1_PIN(59),
|
||||
RZN1_PIN(60), RZN1_PIN(61), RZN1_PIN(62), RZN1_PIN(63), RZN1_PIN(64),
|
||||
RZN1_PIN(65), RZN1_PIN(66), RZN1_PIN(67), RZN1_PIN(68), RZN1_PIN(69),
|
||||
RZN1_PIN(70), RZN1_PIN(71), RZN1_PIN(72), RZN1_PIN(73), RZN1_PIN(74),
|
||||
RZN1_PIN(75), RZN1_PIN(76), RZN1_PIN(77), RZN1_PIN(78), RZN1_PIN(79),
|
||||
RZN1_PIN(80), RZN1_PIN(81), RZN1_PIN(82), RZN1_PIN(83), RZN1_PIN(84),
|
||||
RZN1_PIN(85), RZN1_PIN(86), RZN1_PIN(87), RZN1_PIN(88), RZN1_PIN(89),
|
||||
RZN1_PIN(90), RZN1_PIN(91), RZN1_PIN(92), RZN1_PIN(93), RZN1_PIN(94),
|
||||
RZN1_PIN(95), RZN1_PIN(96), RZN1_PIN(97), RZN1_PIN(98), RZN1_PIN(99),
|
||||
RZN1_PIN(100), RZN1_PIN(101), RZN1_PIN(102), RZN1_PIN(103),
|
||||
RZN1_PIN(104), RZN1_PIN(105), RZN1_PIN(106), RZN1_PIN(107),
|
||||
RZN1_PIN(108), RZN1_PIN(109), RZN1_PIN(110), RZN1_PIN(111),
|
||||
RZN1_PIN(112), RZN1_PIN(113), RZN1_PIN(114), RZN1_PIN(115),
|
||||
RZN1_PIN(116), RZN1_PIN(117), RZN1_PIN(118), RZN1_PIN(119),
|
||||
RZN1_PIN(120), RZN1_PIN(121), RZN1_PIN(122), RZN1_PIN(123),
|
||||
RZN1_PIN(124), RZN1_PIN(125), RZN1_PIN(126), RZN1_PIN(127),
|
||||
RZN1_PIN(128), RZN1_PIN(129), RZN1_PIN(130), RZN1_PIN(131),
|
||||
RZN1_PIN(132), RZN1_PIN(133), RZN1_PIN(134), RZN1_PIN(135),
|
||||
RZN1_PIN(136), RZN1_PIN(137), RZN1_PIN(138), RZN1_PIN(139),
|
||||
RZN1_PIN(140), RZN1_PIN(141), RZN1_PIN(142), RZN1_PIN(143),
|
||||
RZN1_PIN(144), RZN1_PIN(145), RZN1_PIN(146), RZN1_PIN(147),
|
||||
RZN1_PIN(148), RZN1_PIN(149), RZN1_PIN(150), RZN1_PIN(151),
|
||||
RZN1_PIN(152), RZN1_PIN(153), RZN1_PIN(154), RZN1_PIN(155),
|
||||
RZN1_PIN(156), RZN1_PIN(157), RZN1_PIN(158), RZN1_PIN(159),
|
||||
RZN1_PIN(160), RZN1_PIN(161), RZN1_PIN(162), RZN1_PIN(163),
|
||||
RZN1_PIN(164), RZN1_PIN(165), RZN1_PIN(166), RZN1_PIN(167),
|
||||
RZN1_PIN(168), RZN1_PIN(169),
|
||||
};
|
||||
|
||||
enum {
|
||||
LOCK_LEVEL1 = 0x1,
|
||||
LOCK_LEVEL2 = 0x2,
|
||||
LOCK_ALL = LOCK_LEVEL1 | LOCK_LEVEL2,
|
||||
};
|
||||
|
||||
static void rzn1_hw_set_lock(struct rzn1_pinctrl *ipctl, u8 lock, u8 value)
|
||||
{
|
||||
/*
|
||||
* The pinmux configuration is locked by writing the physical address of
|
||||
* the status_protect register to itself. It is unlocked by writing the
|
||||
* address | 1.
|
||||
*/
|
||||
if (lock & LOCK_LEVEL1) {
|
||||
u32 val = ipctl->lev1_protect_phys | !(value & LOCK_LEVEL1);
|
||||
|
||||
writel(val, &ipctl->lev1->status_protect);
|
||||
}
|
||||
|
||||
if (lock & LOCK_LEVEL2) {
|
||||
u32 val = ipctl->lev2_protect_phys | !(value & LOCK_LEVEL2);
|
||||
|
||||
writel(val, &ipctl->lev2->status_protect);
|
||||
}
|
||||
}
|
||||
|
||||
static void rzn1_pinctrl_mdio_select(struct rzn1_pinctrl *ipctl, int mdio,
|
||||
u32 func)
|
||||
{
|
||||
if (ipctl->mdio_func[mdio] >= 0 && ipctl->mdio_func[mdio] != func)
|
||||
dev_warn(ipctl->dev, "conflicting setting for mdio%d!\n", mdio);
|
||||
ipctl->mdio_func[mdio] = func;
|
||||
|
||||
dev_dbg(ipctl->dev, "setting mdio%d to %u\n", mdio, func);
|
||||
|
||||
writel(func, &ipctl->lev2->l2_mdio[mdio]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Using a composite pin description, set the hardware pinmux registers
|
||||
* with the corresponding values.
|
||||
* Make sure to unlock write protection and reset it afterward.
|
||||
*
|
||||
* NOTE: There is no protection for potential concurrency, it is assumed these
|
||||
* calls are serialized already.
|
||||
*/
|
||||
static int rzn1_set_hw_pin_func(struct rzn1_pinctrl *ipctl, unsigned int pin,
|
||||
u32 pin_config, u8 use_locks)
|
||||
{
|
||||
u32 l1_cache;
|
||||
u32 l2_cache;
|
||||
u32 l1;
|
||||
u32 l2;
|
||||
|
||||
/* Level 3 MDIO multiplexing */
|
||||
if (pin_config >= RZN1_FUNC_MDIO0_HIGHZ &&
|
||||
pin_config <= RZN1_FUNC_MDIO1_E1_SWITCH) {
|
||||
int mdio_channel;
|
||||
u32 mdio_func;
|
||||
|
||||
if (pin_config <= RZN1_FUNC_MDIO1_HIGHZ)
|
||||
mdio_channel = 0;
|
||||
else
|
||||
mdio_channel = 1;
|
||||
|
||||
/* Get MDIO func, and convert the func to the level 2 number */
|
||||
if (pin_config <= RZN1_FUNC_MDIO0_SWITCH) {
|
||||
mdio_func = pin_config - RZN1_FUNC_MDIO0_HIGHZ;
|
||||
pin_config = RZN1_FUNC_ETH_MDIO;
|
||||
} else if (pin_config <= RZN1_FUNC_MDIO0_E1_SWITCH) {
|
||||
mdio_func = pin_config - RZN1_FUNC_MDIO0_E1_HIGHZ;
|
||||
pin_config = RZN1_FUNC_ETH_MDIO_E1;
|
||||
} else if (pin_config <= RZN1_FUNC_MDIO1_SWITCH) {
|
||||
mdio_func = pin_config - RZN1_FUNC_MDIO1_HIGHZ;
|
||||
pin_config = RZN1_FUNC_ETH_MDIO;
|
||||
} else {
|
||||
mdio_func = pin_config - RZN1_FUNC_MDIO1_E1_HIGHZ;
|
||||
pin_config = RZN1_FUNC_ETH_MDIO_E1;
|
||||
}
|
||||
rzn1_pinctrl_mdio_select(ipctl, mdio_channel, mdio_func);
|
||||
}
|
||||
|
||||
/* Note here, we do not allow anything past the MDIO Mux values */
|
||||
if (pin >= ARRAY_SIZE(ipctl->lev1->conf) ||
|
||||
pin_config >= RZN1_FUNC_MDIO0_HIGHZ)
|
||||
return -EINVAL;
|
||||
|
||||
l1 = readl(&ipctl->lev1->conf[pin]);
|
||||
l1_cache = l1;
|
||||
l2 = readl(&ipctl->lev2->conf[pin]);
|
||||
l2_cache = l2;
|
||||
|
||||
dev_dbg(ipctl->dev, "setting func for pin %u to %u\n", pin, pin_config);
|
||||
|
||||
l1 &= ~(RZN1_L1_FUNC_MASK << RZN1_L1_FUNCTION);
|
||||
|
||||
if (pin_config < RZN1_FUNC_L2_OFFSET) {
|
||||
l1 |= (pin_config << RZN1_L1_FUNCTION);
|
||||
} else {
|
||||
l1 |= (RZN1_L1_FUNCTION_L2 << RZN1_L1_FUNCTION);
|
||||
|
||||
l2 = pin_config - RZN1_FUNC_L2_OFFSET;
|
||||
}
|
||||
|
||||
/* If either configuration changes, we update both anyway */
|
||||
if (l1 != l1_cache || l2 != l2_cache) {
|
||||
writel(l1, &ipctl->lev1->conf[pin]);
|
||||
writel(l2, &ipctl->lev2->conf[pin]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rzn1_pin_group *rzn1_pinctrl_find_group_by_name(
|
||||
const struct rzn1_pinctrl *ipctl, const char *name)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ipctl->ngroups; i++) {
|
||||
if (!strcmp(ipctl->groups[i].name, name))
|
||||
return &ipctl->groups[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int rzn1_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return ipctl->ngroups;
|
||||
}
|
||||
|
||||
static const char *rzn1_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned int selector)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return ipctl->groups[selector].name;
|
||||
}
|
||||
|
||||
static int rzn1_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
unsigned int selector, const unsigned int **pins,
|
||||
unsigned int *npins)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
if (selector >= ipctl->ngroups)
|
||||
return -EINVAL;
|
||||
|
||||
*pins = ipctl->groups[selector].pins;
|
||||
*npins = ipctl->groups[selector].npins;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called for each pinctl 'Function' node.
|
||||
* Sub-nodes can be used to describe multiple 'Groups' for the 'Function'
|
||||
* If there aren't any sub-nodes, the 'Group' is essentially the 'Function'.
|
||||
* Each 'Group' uses pinmux = <...> to detail the pins and data used to select
|
||||
* the functionality. Each 'Group' has optional pin configurations that apply
|
||||
* to all pins in the 'Group'.
|
||||
*/
|
||||
static int rzn1_dt_node_to_map_one(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map,
|
||||
unsigned int *num_maps)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct rzn1_pin_group *grp;
|
||||
unsigned long *configs = NULL;
|
||||
unsigned int reserved_maps = *num_maps;
|
||||
unsigned int num_configs = 0;
|
||||
unsigned int reserve = 1;
|
||||
int ret;
|
||||
|
||||
dev_dbg(ipctl->dev, "processing node %pOF\n", np);
|
||||
|
||||
grp = rzn1_pinctrl_find_group_by_name(ipctl, np->name);
|
||||
if (!grp) {
|
||||
dev_err(ipctl->dev, "unable to find group for node %pOF\n", np);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Get the group's pin configuration */
|
||||
ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
|
||||
&num_configs);
|
||||
if (ret < 0) {
|
||||
dev_err(ipctl->dev, "%pOF: could not parse property\n", np);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (num_configs)
|
||||
reserve++;
|
||||
|
||||
/* Increase the number of maps to cover this group */
|
||||
ret = pinctrl_utils_reserve_map(pctldev, map, &reserved_maps, num_maps,
|
||||
reserve);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* Associate the group with the function */
|
||||
ret = pinctrl_utils_add_map_mux(pctldev, map, &reserved_maps, num_maps,
|
||||
grp->name, grp->func);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (num_configs) {
|
||||
/* Associate the group's pin configuration with the group */
|
||||
ret = pinctrl_utils_add_map_configs(pctldev, map,
|
||||
&reserved_maps, num_maps, grp->name,
|
||||
configs, num_configs,
|
||||
PIN_MAP_TYPE_CONFIGS_GROUP);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_dbg(pctldev->dev, "maps: function %s group %s (%d pins)\n",
|
||||
grp->func, grp->name, grp->npins);
|
||||
|
||||
out:
|
||||
kfree(configs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rzn1_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map,
|
||||
unsigned int *num_maps)
|
||||
{
|
||||
struct device_node *child;
|
||||
int ret;
|
||||
|
||||
*map = NULL;
|
||||
*num_maps = 0;
|
||||
|
||||
ret = rzn1_dt_node_to_map_one(pctldev, np, map, num_maps);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
ret = rzn1_dt_node_to_map_one(pctldev, child, map, num_maps);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops rzn1_pctrl_ops = {
|
||||
.get_groups_count = rzn1_get_groups_count,
|
||||
.get_group_name = rzn1_get_group_name,
|
||||
.get_group_pins = rzn1_get_group_pins,
|
||||
.dt_node_to_map = rzn1_dt_node_to_map,
|
||||
.dt_free_map = pinctrl_utils_free_map,
|
||||
};
|
||||
|
||||
static int rzn1_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return ipctl->nfunctions;
|
||||
}
|
||||
|
||||
static const char *rzn1_pmx_get_func_name(struct pinctrl_dev *pctldev,
|
||||
unsigned int selector)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return ipctl->functions[selector].name;
|
||||
}
|
||||
|
||||
static int rzn1_pmx_get_groups(struct pinctrl_dev *pctldev,
|
||||
unsigned int selector,
|
||||
const char * const **groups,
|
||||
unsigned int * const num_groups)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
*groups = ipctl->functions[selector].groups;
|
||||
*num_groups = ipctl->functions[selector].num_groups;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzn1_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
|
||||
unsigned int group)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct rzn1_pin_group *grp = &ipctl->groups[group];
|
||||
unsigned int i, grp_pins = grp->npins;
|
||||
|
||||
dev_dbg(ipctl->dev, "set mux %s(%d) group %s(%d)\n",
|
||||
ipctl->functions[selector].name, selector, grp->name, group);
|
||||
|
||||
rzn1_hw_set_lock(ipctl, LOCK_ALL, LOCK_ALL);
|
||||
for (i = 0; i < grp_pins; i++)
|
||||
rzn1_set_hw_pin_func(ipctl, grp->pins[i], grp->pin_ids[i], 0);
|
||||
rzn1_hw_set_lock(ipctl, LOCK_ALL, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinmux_ops rzn1_pmx_ops = {
|
||||
.get_functions_count = rzn1_pmx_get_funcs_count,
|
||||
.get_function_name = rzn1_pmx_get_func_name,
|
||||
.get_function_groups = rzn1_pmx_get_groups,
|
||||
.set_mux = rzn1_set_mux,
|
||||
};
|
||||
|
||||
static int rzn1_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *config)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
enum pin_config_param param = pinconf_to_config_param(*config);
|
||||
const u32 reg_drive[4] = { 4, 6, 8, 12 };
|
||||
u32 pull, drive, l1mux;
|
||||
u32 l1, l2, arg = 0;
|
||||
|
||||
if (pin >= ARRAY_SIZE(ipctl->lev1->conf))
|
||||
return -EINVAL;
|
||||
|
||||
l1 = readl(&ipctl->lev1->conf[pin]);
|
||||
|
||||
l1mux = l1 & RZN1_L1_FUNC_MASK;
|
||||
pull = (l1 >> RZN1_L1_PIN_PULL) & 0x3;
|
||||
drive = (l1 >> RZN1_L1_PIN_DRIVE_STRENGTH) & 0x3;
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
if (pull != RZN1_L1_PIN_PULL_UP)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
if (pull != RZN1_L1_PIN_PULL_DOWN)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
if (pull != RZN1_L1_PIN_PULL_NONE)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
arg = reg_drive[drive];
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
|
||||
l2 = readl(&ipctl->lev2->conf[pin]);
|
||||
if (l1mux == RZN1_L1_FUNCTION_L2) {
|
||||
if (l2 != 0)
|
||||
return -EINVAL;
|
||||
} else if (l1mux != RZN1_FUNC_HIGHZ) {
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
*config = pinconf_to_config_packed(param, arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzn1_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *configs, unsigned int num_configs)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
enum pin_config_param param;
|
||||
unsigned int i;
|
||||
u32 l1, l1_cache;
|
||||
u32 drv;
|
||||
u32 arg;
|
||||
|
||||
if (pin >= ARRAY_SIZE(ipctl->lev1->conf))
|
||||
return -EINVAL;
|
||||
|
||||
l1 = readl(&ipctl->lev1->conf[pin]);
|
||||
l1_cache = l1;
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
param = pinconf_to_config_param(configs[i]);
|
||||
arg = pinconf_to_config_argument(configs[i]);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
dev_dbg(ipctl->dev, "set pin %d pull up\n", pin);
|
||||
l1 &= ~(0x3 << RZN1_L1_PIN_PULL);
|
||||
l1 |= (RZN1_L1_PIN_PULL_UP << RZN1_L1_PIN_PULL);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
dev_dbg(ipctl->dev, "set pin %d pull down\n", pin);
|
||||
l1 &= ~(0x3 << RZN1_L1_PIN_PULL);
|
||||
l1 |= (RZN1_L1_PIN_PULL_DOWN << RZN1_L1_PIN_PULL);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
dev_dbg(ipctl->dev, "set pin %d bias off\n", pin);
|
||||
l1 &= ~(0x3 << RZN1_L1_PIN_PULL);
|
||||
l1 |= (RZN1_L1_PIN_PULL_NONE << RZN1_L1_PIN_PULL);
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
dev_dbg(ipctl->dev, "set pin %d drv %umA\n", pin, arg);
|
||||
switch (arg) {
|
||||
case 4:
|
||||
drv = RZN1_L1_PIN_DRIVE_STRENGTH_4MA;
|
||||
break;
|
||||
case 6:
|
||||
drv = RZN1_L1_PIN_DRIVE_STRENGTH_6MA;
|
||||
break;
|
||||
case 8:
|
||||
drv = RZN1_L1_PIN_DRIVE_STRENGTH_8MA;
|
||||
break;
|
||||
case 12:
|
||||
drv = RZN1_L1_PIN_DRIVE_STRENGTH_12MA;
|
||||
break;
|
||||
default:
|
||||
dev_err(ipctl->dev,
|
||||
"Drive strength %umA not supported\n",
|
||||
arg);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
l1 &= ~(0x3 << RZN1_L1_PIN_DRIVE_STRENGTH);
|
||||
l1 |= (drv << RZN1_L1_PIN_DRIVE_STRENGTH);
|
||||
break;
|
||||
|
||||
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
|
||||
dev_dbg(ipctl->dev, "set pin %d High-Z\n", pin);
|
||||
l1 &= ~RZN1_L1_FUNC_MASK;
|
||||
l1 |= RZN1_FUNC_HIGHZ;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
if (l1 != l1_cache) {
|
||||
rzn1_hw_set_lock(ipctl, LOCK_LEVEL1, LOCK_LEVEL1);
|
||||
writel(l1, &ipctl->lev1->conf[pin]);
|
||||
rzn1_hw_set_lock(ipctl, LOCK_LEVEL1, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzn1_pinconf_group_get(struct pinctrl_dev *pctldev,
|
||||
unsigned int selector,
|
||||
unsigned long *config)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct rzn1_pin_group *grp = &ipctl->groups[selector];
|
||||
unsigned long old = 0;
|
||||
unsigned int i;
|
||||
|
||||
dev_dbg(ipctl->dev, "group get %s selector:%u\n", grp->name, selector);
|
||||
|
||||
for (i = 0; i < grp->npins; i++) {
|
||||
if (rzn1_pinconf_get(pctldev, grp->pins[i], config))
|
||||
return -ENOTSUPP;
|
||||
|
||||
/* configs do not match between two pins */
|
||||
if (i && (old != *config))
|
||||
return -ENOTSUPP;
|
||||
|
||||
old = *config;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzn1_pinconf_group_set(struct pinctrl_dev *pctldev,
|
||||
unsigned int selector,
|
||||
unsigned long *configs,
|
||||
unsigned int num_configs)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct rzn1_pin_group *grp = &ipctl->groups[selector];
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
dev_dbg(ipctl->dev, "group set %s selector:%u configs:%p/%d\n",
|
||||
grp->name, selector, configs, num_configs);
|
||||
|
||||
for (i = 0; i < grp->npins; i++) {
|
||||
unsigned int pin = grp->pins[i];
|
||||
|
||||
ret = rzn1_pinconf_set(pctldev, pin, configs, num_configs);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinconf_ops rzn1_pinconf_ops = {
|
||||
.is_generic = true,
|
||||
.pin_config_get = rzn1_pinconf_get,
|
||||
.pin_config_set = rzn1_pinconf_set,
|
||||
.pin_config_group_get = rzn1_pinconf_group_get,
|
||||
.pin_config_group_set = rzn1_pinconf_group_set,
|
||||
.pin_config_config_dbg_show = pinconf_generic_dump_config,
|
||||
};
|
||||
|
||||
static struct pinctrl_desc rzn1_pinctrl_desc = {
|
||||
.pctlops = &rzn1_pctrl_ops,
|
||||
.pmxops = &rzn1_pmx_ops,
|
||||
.confops = &rzn1_pinconf_ops,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int rzn1_pinctrl_parse_groups(struct device_node *np,
|
||||
struct rzn1_pin_group *grp,
|
||||
struct rzn1_pinctrl *ipctl)
|
||||
{
|
||||
const __be32 *list;
|
||||
unsigned int i;
|
||||
int size;
|
||||
|
||||
dev_dbg(ipctl->dev, "%s: %s\n", __func__, np->name);
|
||||
|
||||
/* Initialise group */
|
||||
grp->name = np->name;
|
||||
|
||||
/*
|
||||
* The binding format is
|
||||
* pinmux = <PIN_FUNC_ID CONFIG ...>,
|
||||
* do sanity check and calculate pins number
|
||||
*/
|
||||
list = of_get_property(np, RZN1_PINS_PROP, &size);
|
||||
if (!list) {
|
||||
dev_err(ipctl->dev,
|
||||
"no " RZN1_PINS_PROP " property in node %pOF\n", np);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!size) {
|
||||
dev_err(ipctl->dev, "Invalid " RZN1_PINS_PROP " in node %pOF\n",
|
||||
np);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
grp->npins = size / sizeof(list[0]);
|
||||
grp->pin_ids = devm_kmalloc_array(ipctl->dev,
|
||||
grp->npins, sizeof(grp->pin_ids[0]),
|
||||
GFP_KERNEL);
|
||||
grp->pins = devm_kmalloc_array(ipctl->dev,
|
||||
grp->npins, sizeof(grp->pins[0]),
|
||||
GFP_KERNEL);
|
||||
if (!grp->pin_ids || !grp->pins)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < grp->npins; i++) {
|
||||
u32 pin_id = be32_to_cpu(*list++);
|
||||
|
||||
grp->pins[i] = pin_id & 0xff;
|
||||
grp->pin_ids[i] = (pin_id >> 8) & 0x7f;
|
||||
}
|
||||
|
||||
return grp->npins;
|
||||
}
|
||||
|
||||
static int rzn1_pinctrl_count_function_groups(struct device_node *np)
|
||||
{
|
||||
struct device_node *child;
|
||||
int count = 0;
|
||||
|
||||
if (of_property_count_u32_elems(np, RZN1_PINS_PROP) > 0)
|
||||
count++;
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
if (of_property_count_u32_elems(child, RZN1_PINS_PROP) > 0)
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int rzn1_pinctrl_parse_functions(struct device_node *np,
|
||||
struct rzn1_pinctrl *ipctl,
|
||||
unsigned int index)
|
||||
{
|
||||
struct rzn1_pmx_func *func;
|
||||
struct rzn1_pin_group *grp;
|
||||
struct device_node *child;
|
||||
unsigned int i = 0;
|
||||
int ret;
|
||||
|
||||
func = &ipctl->functions[index];
|
||||
|
||||
/* Initialise function */
|
||||
func->name = np->name;
|
||||
func->num_groups = rzn1_pinctrl_count_function_groups(np);
|
||||
if (func->num_groups == 0) {
|
||||
dev_err(ipctl->dev, "no groups defined in %pOF\n", np);
|
||||
return -EINVAL;
|
||||
}
|
||||
dev_dbg(ipctl->dev, "function %s has %d groups\n",
|
||||
np->name, func->num_groups);
|
||||
|
||||
func->groups = devm_kmalloc_array(ipctl->dev,
|
||||
func->num_groups, sizeof(char *),
|
||||
GFP_KERNEL);
|
||||
if (!func->groups)
|
||||
return -ENOMEM;
|
||||
|
||||
if (of_property_count_u32_elems(np, RZN1_PINS_PROP) > 0) {
|
||||
func->groups[i] = np->name;
|
||||
grp = &ipctl->groups[ipctl->ngroups];
|
||||
grp->func = func->name;
|
||||
ret = rzn1_pinctrl_parse_groups(np, grp, ipctl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
i++;
|
||||
ipctl->ngroups++;
|
||||
}
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
func->groups[i] = child->name;
|
||||
grp = &ipctl->groups[ipctl->ngroups];
|
||||
grp->func = func->name;
|
||||
ret = rzn1_pinctrl_parse_groups(child, grp, ipctl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
i++;
|
||||
ipctl->ngroups++;
|
||||
}
|
||||
|
||||
dev_dbg(ipctl->dev, "function %s parsed %u/%u groups\n",
|
||||
np->name, i, func->num_groups);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzn1_pinctrl_probe_dt(struct platform_device *pdev,
|
||||
struct rzn1_pinctrl *ipctl)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct device_node *child;
|
||||
unsigned int maxgroups = 0;
|
||||
unsigned int nfuncs = 0;
|
||||
unsigned int i = 0;
|
||||
int ret;
|
||||
|
||||
nfuncs = of_get_child_count(np);
|
||||
if (nfuncs <= 0)
|
||||
return 0;
|
||||
|
||||
ipctl->nfunctions = nfuncs;
|
||||
ipctl->functions = devm_kmalloc_array(&pdev->dev, nfuncs,
|
||||
sizeof(*ipctl->functions),
|
||||
GFP_KERNEL);
|
||||
if (!ipctl->functions)
|
||||
return -ENOMEM;
|
||||
|
||||
ipctl->ngroups = 0;
|
||||
for_each_child_of_node(np, child)
|
||||
maxgroups += rzn1_pinctrl_count_function_groups(child);
|
||||
|
||||
ipctl->groups = devm_kmalloc_array(&pdev->dev,
|
||||
maxgroups,
|
||||
sizeof(*ipctl->groups),
|
||||
GFP_KERNEL);
|
||||
if (!ipctl->groups)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
ret = rzn1_pinctrl_parse_functions(child, ipctl, i++);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rzn1_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
/* Create state holders etc for this driver */
|
||||
ipctl = devm_kzalloc(&pdev->dev, sizeof(*ipctl), GFP_KERNEL);
|
||||
if (!ipctl)
|
||||
return -ENOMEM;
|
||||
|
||||
ipctl->mdio_func[0] = -1;
|
||||
ipctl->mdio_func[1] = -1;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
ipctl->lev1_protect_phys = (u32)res->start + 0x400;
|
||||
ipctl->lev1 = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(ipctl->lev1))
|
||||
return PTR_ERR(ipctl->lev1);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
ipctl->lev2_protect_phys = (u32)res->start + 0x400;
|
||||
ipctl->lev2 = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(ipctl->lev2))
|
||||
return PTR_ERR(ipctl->lev2);
|
||||
|
||||
ipctl->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(ipctl->clk))
|
||||
return PTR_ERR(ipctl->clk);
|
||||
ret = clk_prepare_enable(ipctl->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ipctl->dev = &pdev->dev;
|
||||
rzn1_pinctrl_desc.name = dev_name(&pdev->dev);
|
||||
rzn1_pinctrl_desc.pins = rzn1_pins;
|
||||
rzn1_pinctrl_desc.npins = ARRAY_SIZE(rzn1_pins);
|
||||
|
||||
ret = rzn1_pinctrl_probe_dt(pdev, ipctl);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "fail to probe dt properties\n");
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, ipctl);
|
||||
|
||||
ret = devm_pinctrl_register_and_init(&pdev->dev, &rzn1_pinctrl_desc,
|
||||
ipctl, &ipctl->pctl);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "could not register rzn1 pinctrl driver\n");
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
ret = pinctrl_enable(ipctl->pctl);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
|
||||
dev_info(&pdev->dev, "probed\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk:
|
||||
clk_disable_unprepare(ipctl->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rzn1_pinctrl_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rzn1_pinctrl *ipctl = platform_get_drvdata(pdev);
|
||||
|
||||
clk_disable_unprepare(ipctl->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id rzn1_pinctrl_match[] = {
|
||||
{ .compatible = "renesas,rzn1-pinctrl", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rzn1_pinctrl_match);
|
||||
|
||||
static struct platform_driver rzn1_pinctrl_driver = {
|
||||
.probe = rzn1_pinctrl_probe,
|
||||
.remove = rzn1_pinctrl_remove,
|
||||
.driver = {
|
||||
.name = "rzn1-pinctrl",
|
||||
.of_match_table = rzn1_pinctrl_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init _pinctrl_drv_register(void)
|
||||
{
|
||||
return platform_driver_register(&rzn1_pinctrl_driver);
|
||||
}
|
||||
subsys_initcall(_pinctrl_drv_register);
|
||||
|
||||
MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
|
||||
MODULE_DESCRIPTION("Renesas RZ/N1 pinctrl driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -1022,14 +1022,14 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
|
||||
vals[found].reg = pcs->base + offset;
|
||||
vals[found].val = pinctrl_spec.args[1];
|
||||
|
||||
dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x\n",
|
||||
pinctrl_spec.np->name, offset, pinctrl_spec.args[1]);
|
||||
dev_dbg(pcs->dev, "%pOFn index: 0x%x value: 0x%x\n",
|
||||
pinctrl_spec.np, offset, pinctrl_spec.args[1]);
|
||||
|
||||
pin = pcs_get_pin_by_offset(pcs, offset);
|
||||
if (pin < 0) {
|
||||
dev_err(pcs->dev,
|
||||
"could not add functions for %s %ux\n",
|
||||
np->name, offset);
|
||||
"could not add functions for %pOFn %ux\n",
|
||||
np, offset);
|
||||
break;
|
||||
}
|
||||
pins[found++] = pin;
|
||||
@ -1135,8 +1135,8 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
|
||||
val = pinctrl_spec.args[1];
|
||||
mask = pinctrl_spec.args[2];
|
||||
|
||||
dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x mask: 0x%x\n",
|
||||
pinctrl_spec.np->name, offset, val, mask);
|
||||
dev_dbg(pcs->dev, "%pOFn index: 0x%x value: 0x%x mask: 0x%x\n",
|
||||
pinctrl_spec.np, offset, val, mask);
|
||||
|
||||
/* Parse pins in each row from LSB */
|
||||
while (mask) {
|
||||
@ -1148,8 +1148,8 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
|
||||
|
||||
if ((mask & mask_pos) == 0) {
|
||||
dev_err(pcs->dev,
|
||||
"Invalid mask for %s at 0x%x\n",
|
||||
np->name, offset);
|
||||
"Invalid mask for %pOFn at 0x%x\n",
|
||||
np, offset);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1157,8 +1157,8 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
|
||||
|
||||
if (submask != mask_pos) {
|
||||
dev_warn(pcs->dev,
|
||||
"Invalid submask 0x%x for %s at 0x%x\n",
|
||||
submask, np->name, offset);
|
||||
"Invalid submask 0x%x for %pOFn at 0x%x\n",
|
||||
submask, np, offset);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1169,8 +1169,8 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
|
||||
pin = pcs_get_pin_by_offset(pcs, offset);
|
||||
if (pin < 0) {
|
||||
dev_err(pcs->dev,
|
||||
"could not add functions for %s %ux\n",
|
||||
np->name, offset);
|
||||
"could not add functions for %pOFn %ux\n",
|
||||
np, offset);
|
||||
break;
|
||||
}
|
||||
pins[found++] = pin + pin_num_from_lsb;
|
||||
@ -1254,16 +1254,16 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
ret = pcs_parse_bits_in_pinctrl_entry(pcs, np_config, map,
|
||||
num_maps, pgnames);
|
||||
if (ret < 0) {
|
||||
dev_err(pcs->dev, "no pins entries for %s\n",
|
||||
np_config->name);
|
||||
dev_err(pcs->dev, "no pins entries for %pOFn\n",
|
||||
np_config);
|
||||
goto free_pgnames;
|
||||
}
|
||||
} else {
|
||||
ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map,
|
||||
num_maps, pgnames);
|
||||
if (ret < 0) {
|
||||
dev_err(pcs->dev, "no pins entries for %s\n",
|
||||
np_config->name);
|
||||
dev_err(pcs->dev, "no pins entries for %pOFn\n",
|
||||
np_config);
|
||||
goto free_pgnames;
|
||||
}
|
||||
}
|
||||
|
@ -817,8 +817,8 @@ static int st_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
|
||||
grp = st_pctl_find_group_by_name(info, np->name);
|
||||
if (!grp) {
|
||||
dev_err(info->dev, "unable to find group for node %s\n",
|
||||
np->name);
|
||||
dev_err(info->dev, "unable to find group for node %pOFn\n",
|
||||
np);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1184,7 +1184,7 @@ static int st_pctl_dt_parse_groups(struct device_node *np,
|
||||
if (pp->length / sizeof(__be32) >= OF_GPIO_ARGS_MIN) {
|
||||
npins++;
|
||||
} else {
|
||||
pr_warn("Invalid st,pins in %s node\n", np->name);
|
||||
pr_warn("Invalid st,pins in %pOFn node\n", np);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +114,14 @@ config PINCTRL_MSM8998
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
Qualcomm TLMM block found in the Qualcomm MSM8998 platform.
|
||||
|
||||
config PINCTRL_QCS404
|
||||
tristate "Qualcomm QCS404 pin controller driver"
|
||||
depends on GPIOLIB && OF
|
||||
select PINCTRL_MSM
|
||||
help
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
TLMM block found in the Qualcomm QCS404 platform.
|
||||
|
||||
config PINCTRL_QDF2XXX
|
||||
tristate "Qualcomm Technologies QDF2xxx pin controller driver"
|
||||
depends on GPIOLIB && ACPI
|
||||
@ -147,6 +155,15 @@ config PINCTRL_QCOM_SSBI_PMIC
|
||||
which are using SSBI for communication with SoC. Example PMIC's
|
||||
devices are pm8058 and pm8921.
|
||||
|
||||
config PINCTRL_SDM660
|
||||
tristate "Qualcomm Technologies Inc SDM660 pin controller driver"
|
||||
depends on GPIOLIB && OF
|
||||
select PINCTRL_MSM
|
||||
help
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
Qualcomm Technologies Inc TLMM block found on the Qualcomm
|
||||
Technologies Inc SDM660 platform.
|
||||
|
||||
config PINCTRL_SDM845
|
||||
tristate "Qualcomm Technologies Inc SDM845 pin controller driver"
|
||||
depends on GPIOLIB && OF
|
||||
|
@ -13,10 +13,12 @@ obj-$(CONFIG_PINCTRL_MSM8916) += pinctrl-msm8916.o
|
||||
obj-$(CONFIG_PINCTRL_MSM8994) += pinctrl-msm8994.o
|
||||
obj-$(CONFIG_PINCTRL_MSM8996) += pinctrl-msm8996.o
|
||||
obj-$(CONFIG_PINCTRL_MSM8998) += pinctrl-msm8998.o
|
||||
obj-$(CONFIG_PINCTRL_QCS404) += pinctrl-qcs404.o
|
||||
obj-$(CONFIG_PINCTRL_QDF2XXX) += pinctrl-qdf2xxx.o
|
||||
obj-$(CONFIG_PINCTRL_MDM9615) += pinctrl-mdm9615.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-gpio.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-mpp.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-gpio.o
|
||||
obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-mpp.o
|
||||
obj-$(CONFIG_PINCTRL_SDM660) += pinctrl-sdm660.o
|
||||
obj-$(CONFIG_PINCTRL_SDM845) += pinctrl-sdm845.o
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/reboot.h>
|
||||
@ -37,6 +37,7 @@
|
||||
#include "../pinctrl-utils.h"
|
||||
|
||||
#define MAX_NR_GPIO 300
|
||||
#define MAX_NR_TILES 4
|
||||
#define PS_HOLD_OFFSET 0x820
|
||||
|
||||
/**
|
||||
@ -52,7 +53,7 @@
|
||||
* @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge
|
||||
* detection.
|
||||
* @soc; Reference to soc_data of platform specific data.
|
||||
* @regs: Base address for the TLMM register map.
|
||||
* @regs: Base addresses for the TLMM tiles.
|
||||
*/
|
||||
struct msm_pinctrl {
|
||||
struct device *dev;
|
||||
@ -70,9 +71,27 @@ struct msm_pinctrl {
|
||||
DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO);
|
||||
|
||||
const struct msm_pinctrl_soc_data *soc;
|
||||
void __iomem *regs;
|
||||
void __iomem *regs[MAX_NR_TILES];
|
||||
};
|
||||
|
||||
#define MSM_ACCESSOR(name) \
|
||||
static u32 msm_readl_##name(struct msm_pinctrl *pctrl, \
|
||||
const struct msm_pingroup *g) \
|
||||
{ \
|
||||
return readl(pctrl->regs[g->tile] + g->name##_reg); \
|
||||
} \
|
||||
static void msm_writel_##name(u32 val, struct msm_pinctrl *pctrl, \
|
||||
const struct msm_pingroup *g) \
|
||||
{ \
|
||||
writel(val, pctrl->regs[g->tile] + g->name##_reg); \
|
||||
}
|
||||
|
||||
MSM_ACCESSOR(ctl)
|
||||
MSM_ACCESSOR(io)
|
||||
MSM_ACCESSOR(intr_cfg)
|
||||
MSM_ACCESSOR(intr_status)
|
||||
MSM_ACCESSOR(intr_target)
|
||||
|
||||
static int msm_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
@ -166,21 +185,37 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
val = readl(pctrl->regs + g->ctl_reg);
|
||||
val = msm_readl_ctl(pctrl, g);
|
||||
val &= ~mask;
|
||||
val |= i << g->mux_bit;
|
||||
writel(val, pctrl->regs + g->ctl_reg);
|
||||
msm_writel_ctl(val, pctrl, g);
|
||||
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_pinmux_request_gpio(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned offset)
|
||||
{
|
||||
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct msm_pingroup *g = &pctrl->soc->groups[offset];
|
||||
|
||||
/* No funcs? Probably ACPI so can't do anything here */
|
||||
if (!g->nfuncs)
|
||||
return 0;
|
||||
|
||||
/* For now assume function 0 is GPIO because it always is */
|
||||
return msm_pinmux_set_mux(pctldev, g->funcs[0], offset);
|
||||
}
|
||||
|
||||
static const struct pinmux_ops msm_pinmux_ops = {
|
||||
.request = msm_pinmux_request,
|
||||
.get_functions_count = msm_get_functions_count,
|
||||
.get_function_name = msm_get_function_name,
|
||||
.get_function_groups = msm_get_function_groups,
|
||||
.gpio_request_enable = msm_pinmux_request_gpio,
|
||||
.set_mux = msm_pinmux_set_mux,
|
||||
};
|
||||
|
||||
@ -244,7 +279,7 @@ static int msm_config_group_get(struct pinctrl_dev *pctldev,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val = readl(pctrl->regs + g->ctl_reg);
|
||||
val = msm_readl_ctl(pctrl, g);
|
||||
arg = (val >> bit) & mask;
|
||||
|
||||
/* Convert register value to pinconf value */
|
||||
@ -283,7 +318,7 @@ static int msm_config_group_get(struct pinctrl_dev *pctldev,
|
||||
if (!arg)
|
||||
return -EINVAL;
|
||||
|
||||
val = readl(pctrl->regs + g->io_reg);
|
||||
val = msm_readl_io(pctrl, g);
|
||||
arg = !!(val & BIT(g->in_bit));
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
@ -357,12 +392,12 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev,
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
/* set output value */
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
val = readl(pctrl->regs + g->io_reg);
|
||||
val = msm_readl_io(pctrl, g);
|
||||
if (arg)
|
||||
val |= BIT(g->out_bit);
|
||||
else
|
||||
val &= ~BIT(g->out_bit);
|
||||
writel(val, pctrl->regs + g->io_reg);
|
||||
msm_writel_io(val, pctrl, g);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
/* enable output */
|
||||
@ -385,10 +420,10 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
val = readl(pctrl->regs + g->ctl_reg);
|
||||
val = msm_readl_ctl(pctrl, g);
|
||||
val &= ~(mask << bit);
|
||||
val |= arg << bit;
|
||||
writel(val, pctrl->regs + g->ctl_reg);
|
||||
msm_writel_ctl(val, pctrl, g);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
}
|
||||
|
||||
@ -412,9 +447,9 @@ static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
val = readl(pctrl->regs + g->ctl_reg);
|
||||
val = msm_readl_ctl(pctrl, g);
|
||||
val &= ~BIT(g->oe_bit);
|
||||
writel(val, pctrl->regs + g->ctl_reg);
|
||||
msm_writel_ctl(val, pctrl, g);
|
||||
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
@ -432,16 +467,16 @@ static int msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, in
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
val = readl(pctrl->regs + g->io_reg);
|
||||
val = msm_readl_io(pctrl, g);
|
||||
if (value)
|
||||
val |= BIT(g->out_bit);
|
||||
else
|
||||
val &= ~BIT(g->out_bit);
|
||||
writel(val, pctrl->regs + g->io_reg);
|
||||
msm_writel_io(val, pctrl, g);
|
||||
|
||||
val = readl(pctrl->regs + g->ctl_reg);
|
||||
val = msm_readl_ctl(pctrl, g);
|
||||
val |= BIT(g->oe_bit);
|
||||
writel(val, pctrl->regs + g->ctl_reg);
|
||||
msm_writel_ctl(val, pctrl, g);
|
||||
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
@ -456,7 +491,7 @@ static int msm_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
|
||||
|
||||
g = &pctrl->soc->groups[offset];
|
||||
|
||||
val = readl(pctrl->regs + g->ctl_reg);
|
||||
val = msm_readl_ctl(pctrl, g);
|
||||
|
||||
/* 0 = output, 1 = input */
|
||||
return val & BIT(g->oe_bit) ? 0 : 1;
|
||||
@ -470,7 +505,7 @@ static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
|
||||
g = &pctrl->soc->groups[offset];
|
||||
|
||||
val = readl(pctrl->regs + g->io_reg);
|
||||
val = msm_readl_io(pctrl, g);
|
||||
return !!(val & BIT(g->in_bit));
|
||||
}
|
||||
|
||||
@ -485,12 +520,12 @@ static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
val = readl(pctrl->regs + g->io_reg);
|
||||
val = msm_readl_io(pctrl, g);
|
||||
if (value)
|
||||
val |= BIT(g->out_bit);
|
||||
else
|
||||
val &= ~BIT(g->out_bit);
|
||||
writel(val, pctrl->regs + g->io_reg);
|
||||
msm_writel_io(val, pctrl, g);
|
||||
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
}
|
||||
@ -530,8 +565,8 @@ static void msm_gpio_dbg_show_one(struct seq_file *s,
|
||||
return;
|
||||
|
||||
g = &pctrl->soc->groups[offset];
|
||||
ctl_reg = readl(pctrl->regs + g->ctl_reg);
|
||||
io_reg = readl(pctrl->regs + g->io_reg);
|
||||
ctl_reg = msm_readl_ctl(pctrl, g);
|
||||
io_reg = msm_readl_io(pctrl, g);
|
||||
|
||||
is_out = !!(ctl_reg & BIT(g->oe_bit));
|
||||
func = (ctl_reg >> g->mux_bit) & 7;
|
||||
@ -606,14 +641,14 @@ static void msm_gpio_update_dual_edge_pos(struct msm_pinctrl *pctrl,
|
||||
unsigned pol;
|
||||
|
||||
do {
|
||||
val = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit);
|
||||
val = msm_readl_io(pctrl, g) & BIT(g->in_bit);
|
||||
|
||||
pol = readl(pctrl->regs + g->intr_cfg_reg);
|
||||
pol = msm_readl_intr_cfg(pctrl, g);
|
||||
pol ^= BIT(g->intr_polarity_bit);
|
||||
writel(pol, pctrl->regs + g->intr_cfg_reg);
|
||||
msm_writel_intr_cfg(val, pctrl, g);
|
||||
|
||||
val2 = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit);
|
||||
intstat = readl(pctrl->regs + g->intr_status_reg);
|
||||
val2 = msm_readl_io(pctrl, g) & BIT(g->in_bit);
|
||||
intstat = msm_readl_intr_status(pctrl, g);
|
||||
if (intstat || (val == val2))
|
||||
return;
|
||||
} while (loop_limit-- > 0);
|
||||
@ -633,7 +668,7 @@ static void msm_gpio_irq_mask(struct irq_data *d)
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
val = readl(pctrl->regs + g->intr_cfg_reg);
|
||||
val = msm_readl_intr_cfg(pctrl, g);
|
||||
/*
|
||||
* There are two bits that control interrupt forwarding to the CPU. The
|
||||
* RAW_STATUS_EN bit causes the level or edge sensed on the line to be
|
||||
@ -658,7 +693,7 @@ static void msm_gpio_irq_mask(struct irq_data *d)
|
||||
val &= ~BIT(g->intr_raw_status_bit);
|
||||
|
||||
val &= ~BIT(g->intr_enable_bit);
|
||||
writel(val, pctrl->regs + g->intr_cfg_reg);
|
||||
msm_writel_intr_cfg(val, pctrl, g);
|
||||
|
||||
clear_bit(d->hwirq, pctrl->enabled_irqs);
|
||||
|
||||
@ -677,10 +712,10 @@ static void msm_gpio_irq_unmask(struct irq_data *d)
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
val = readl(pctrl->regs + g->intr_cfg_reg);
|
||||
val = msm_readl_intr_cfg(pctrl, g);
|
||||
val |= BIT(g->intr_raw_status_bit);
|
||||
val |= BIT(g->intr_enable_bit);
|
||||
writel(val, pctrl->regs + g->intr_cfg_reg);
|
||||
msm_writel_intr_cfg(val, pctrl, g);
|
||||
|
||||
set_bit(d->hwirq, pctrl->enabled_irqs);
|
||||
|
||||
@ -699,12 +734,12 @@ static void msm_gpio_irq_ack(struct irq_data *d)
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
|
||||
val = readl(pctrl->regs + g->intr_status_reg);
|
||||
val = msm_readl_intr_status(pctrl, g);
|
||||
if (g->intr_ack_high)
|
||||
val |= BIT(g->intr_status_bit);
|
||||
else
|
||||
val &= ~BIT(g->intr_status_bit);
|
||||
writel(val, pctrl->regs + g->intr_status_reg);
|
||||
msm_writel_intr_status(val, pctrl, g);
|
||||
|
||||
if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
|
||||
msm_gpio_update_dual_edge_pos(pctrl, g, d);
|
||||
@ -733,17 +768,17 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
clear_bit(d->hwirq, pctrl->dual_edge_irqs);
|
||||
|
||||
/* Route interrupts to application cpu */
|
||||
val = readl(pctrl->regs + g->intr_target_reg);
|
||||
val = msm_readl_intr_target(pctrl, g);
|
||||
val &= ~(7 << g->intr_target_bit);
|
||||
val |= g->intr_target_kpss_val << g->intr_target_bit;
|
||||
writel(val, pctrl->regs + g->intr_target_reg);
|
||||
msm_writel_intr_target(val, pctrl, g);
|
||||
|
||||
/* Update configuration for gpio.
|
||||
* RAW_STATUS_EN is left on for all gpio irqs. Due to the
|
||||
* internal circuitry of TLMM, toggling the RAW_STATUS
|
||||
* could cause the INTR_STATUS to be set for EDGE interrupts.
|
||||
*/
|
||||
val = readl(pctrl->regs + g->intr_cfg_reg);
|
||||
val = msm_readl_intr_cfg(pctrl, g);
|
||||
val |= BIT(g->intr_raw_status_bit);
|
||||
if (g->intr_detection_width == 2) {
|
||||
val &= ~(3 << g->intr_detection_bit);
|
||||
@ -791,7 +826,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
} else {
|
||||
BUG();
|
||||
}
|
||||
writel(val, pctrl->regs + g->intr_cfg_reg);
|
||||
msm_writel_intr_cfg(val, pctrl, g);
|
||||
|
||||
if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
|
||||
msm_gpio_update_dual_edge_pos(pctrl, g, d);
|
||||
@ -821,6 +856,41 @@ static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_gpio_irq_reqres(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct msm_pinctrl *pctrl = gpiochip_get_data(gc);
|
||||
int ret;
|
||||
|
||||
if (!try_module_get(gc->owner))
|
||||
return -ENODEV;
|
||||
|
||||
ret = msm_pinmux_request_gpio(pctrl->pctrl, NULL, d->hwirq);
|
||||
if (ret)
|
||||
goto out;
|
||||
msm_gpio_direction_input(gc, d->hwirq);
|
||||
|
||||
if (gpiochip_lock_as_irq(gc, d->hwirq)) {
|
||||
dev_err(gc->parent,
|
||||
"unable to lock HW IRQ %lu for IRQ\n",
|
||||
d->hwirq);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
return 0;
|
||||
out:
|
||||
module_put(gc->owner);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void msm_gpio_irq_relres(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
|
||||
gpiochip_unlock_as_irq(gc, d->hwirq);
|
||||
module_put(gc->owner);
|
||||
}
|
||||
|
||||
static void msm_gpio_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
|
||||
@ -840,7 +910,7 @@ static void msm_gpio_irq_handler(struct irq_desc *desc)
|
||||
*/
|
||||
for_each_set_bit(i, pctrl->enabled_irqs, pctrl->chip.ngpio) {
|
||||
g = &pctrl->soc->groups[i];
|
||||
val = readl(pctrl->regs + g->intr_status_reg);
|
||||
val = msm_readl_intr_status(pctrl, g);
|
||||
if (val & BIT(g->intr_status_bit)) {
|
||||
irq_pin = irq_find_mapping(gc->irq.domain, i);
|
||||
generic_handle_irq(irq_pin);
|
||||
@ -919,6 +989,8 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
|
||||
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;
|
||||
pctrl->irq_chip.irq_request_resources = msm_gpio_irq_reqres;
|
||||
pctrl->irq_chip.irq_release_resources = msm_gpio_irq_relres;
|
||||
|
||||
ret = gpiochip_add_data(&pctrl->chip, pctrl);
|
||||
if (ret) {
|
||||
@ -975,7 +1047,7 @@ static int msm_ps_hold_restart(struct notifier_block *nb, unsigned long action,
|
||||
{
|
||||
struct msm_pinctrl *pctrl = container_of(nb, struct msm_pinctrl, restart_nb);
|
||||
|
||||
writel(0, pctrl->regs + PS_HOLD_OFFSET);
|
||||
writel(0, pctrl->regs[0] + PS_HOLD_OFFSET);
|
||||
mdelay(1000);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
@ -1011,6 +1083,7 @@ int msm_pinctrl_probe(struct platform_device *pdev,
|
||||
struct msm_pinctrl *pctrl;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
|
||||
if (!pctrl)
|
||||
@ -1022,10 +1095,20 @@ int msm_pinctrl_probe(struct platform_device *pdev,
|
||||
|
||||
raw_spin_lock_init(&pctrl->lock);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
pctrl->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pctrl->regs))
|
||||
return PTR_ERR(pctrl->regs);
|
||||
if (soc_data->tiles) {
|
||||
for (i = 0; i < soc_data->ntiles; i++) {
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
soc_data->tiles[i]);
|
||||
pctrl->regs[i] = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pctrl->regs[i]))
|
||||
return PTR_ERR(pctrl->regs[i]);
|
||||
}
|
||||
} else {
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
pctrl->regs[0] = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pctrl->regs[0]))
|
||||
return PTR_ERR(pctrl->regs[0]);
|
||||
}
|
||||
|
||||
msm_pinctrl_setup_pm_reset(pctrl);
|
||||
|
||||
|
@ -76,6 +76,8 @@ struct msm_pingroup {
|
||||
u32 intr_status_reg;
|
||||
u32 intr_target_reg;
|
||||
|
||||
unsigned int tile:2;
|
||||
|
||||
unsigned mux_bit:5;
|
||||
|
||||
unsigned pull_bit:5;
|
||||
@ -117,6 +119,8 @@ struct msm_pinctrl_soc_data {
|
||||
unsigned ngroups;
|
||||
unsigned ngpios;
|
||||
bool pull_no_keeper;
|
||||
const char *const *tiles;
|
||||
unsigned int ntiles;
|
||||
};
|
||||
|
||||
int msm_pinctrl_probe(struct platform_device *pdev,
|
||||
|
1697
drivers/pinctrl/qcom/pinctrl-qcs404.c
Normal file
1697
drivers/pinctrl/qcom/pinctrl-qcs404.c
Normal file
File diff suppressed because it is too large
Load Diff
1455
drivers/pinctrl/qcom/pinctrl-sdm660.c
Normal file
1455
drivers/pinctrl/qcom/pinctrl-sdm660.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
@ -11,7 +11,7 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
@ -319,6 +319,8 @@ static int pmic_mpp_set_mux(struct pinctrl_dev *pctldev, unsigned function,
|
||||
pad->function = function;
|
||||
|
||||
ret = pmic_mpp_write_mode_ctl(state, pad);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val = pad->is_enabled << PMIC_MPP_REG_MASTER_EN_SHIFT;
|
||||
|
||||
@ -343,13 +345,12 @@ static int pmic_mpp_config_get(struct pinctrl_dev *pctldev,
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
arg = pad->pullup == PMIC_MPP_PULL_UP_OPEN;
|
||||
if (pad->pullup != PMIC_MPP_PULL_UP_OPEN)
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
switch (pad->pullup) {
|
||||
case PMIC_MPP_PULL_UP_OPEN:
|
||||
arg = 0;
|
||||
break;
|
||||
case PMIC_MPP_PULL_UP_0P6KOHM:
|
||||
arg = 600;
|
||||
break;
|
||||
@ -364,13 +365,17 @@ static int pmic_mpp_config_get(struct pinctrl_dev *pctldev,
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
|
||||
arg = !pad->is_enabled;
|
||||
if (pad->is_enabled)
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
case PIN_CONFIG_POWER_SOURCE:
|
||||
arg = pad->power_source;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
arg = pad->input_enabled;
|
||||
if (!pad->input_enabled)
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
arg = pad->out_value;
|
||||
@ -382,7 +387,9 @@ static int pmic_mpp_config_get(struct pinctrl_dev *pctldev,
|
||||
arg = pad->amux_input;
|
||||
break;
|
||||
case PMIC_MPP_CONF_PAIRED:
|
||||
arg = pad->paired;
|
||||
if (!pad->paired)
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
arg = pad->drive_strength;
|
||||
@ -455,7 +462,7 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
pad->dtest = arg;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH:
|
||||
arg = pad->drive_strength;
|
||||
pad->drive_strength = arg;
|
||||
break;
|
||||
case PMIC_MPP_CONF_AMUX_ROUTE:
|
||||
if (arg >= PMIC_MPP_AMUX_ROUTE_ABUS4)
|
||||
@ -502,6 +509,10 @@ static int pmic_mpp_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = pmic_mpp_write(state, pad, PMIC_MPP_REG_SINK_CTL, pad->drive_strength);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val = pad->is_enabled << PMIC_MPP_REG_MASTER_EN_SHIFT;
|
||||
|
||||
return pmic_mpp_write(state, pad, PMIC_MPP_REG_EN_CTL, val);
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
@ -260,22 +260,32 @@ static int pm8xxx_pin_config_get(struct pinctrl_dev *pctldev,
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
arg = pin->bias == PM8XXX_GPIO_BIAS_NP;
|
||||
if (pin->bias != PM8XXX_GPIO_BIAS_NP)
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
arg = pin->bias == PM8XXX_GPIO_BIAS_PD;
|
||||
if (pin->bias != PM8XXX_GPIO_BIAS_PD)
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
arg = pin->bias <= PM8XXX_GPIO_BIAS_PU_1P5_30;
|
||||
if (pin->bias > PM8XXX_GPIO_BIAS_PU_1P5_30)
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
case PM8XXX_QCOM_PULL_UP_STRENGTH:
|
||||
arg = pin->pull_up_strength;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
|
||||
arg = pin->disable;
|
||||
if (!pin->disable)
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
arg = pin->mode == PM8XXX_GPIO_MODE_INPUT;
|
||||
if (pin->mode != PM8XXX_GPIO_MODE_INPUT)
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
case PIN_CONFIG_OUTPUT:
|
||||
if (pin->mode & PM8XXX_GPIO_MODE_OUTPUT)
|
||||
@ -290,10 +300,14 @@ static int pm8xxx_pin_config_get(struct pinctrl_dev *pctldev,
|
||||
arg = pin->output_strength;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_PUSH_PULL:
|
||||
arg = !pin->open_drain;
|
||||
if (pin->open_drain)
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
|
||||
arg = pin->open_drain;
|
||||
if (!pin->open_drain)
|
||||
return -EINVAL;
|
||||
arg = 1;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
|
||||
/**
|
||||
* enum pincfg_type - possible pin configuration types supported.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user