mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/
synced 2026-04-03 23:37:40 -04:00
Merge tag 'pinctrl-v6.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pin control updates from Linus Walleij:
"Core changes:
- None really.
New drivers:
- AMD ISP411 "AMD ISP" driver
- Exynos 2200 and 7870 SoC subdrivers
- Sophgo RISC-V SG2042 and SG2044 subdrivers
- Amlogic A4 subdriver
- Rockchip RK3528 subdriver
- Broadcom BCM21664 subdriver
- Allwinner A523/T527 subdriver
- Ingenic X1600 subdriver
- Microchip SAMA7D65 subdriver, essentially a re-branded Atmel AT91
PIO4 driver, but nowadays a Microschip SoC line
Improvements:
- Bring in the devm_kmemdup_array() helper and use it throughout,
also bring in changes to other subsystems for this to establish
this helper
- Support EGPIO on the Qualcomm SA8775P SoC
- Extend EINT support in the Mediatek driver"
* tag 'pinctrl-v6.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (101 commits)
pinctrl: mediatek: Add EINT support for multiple addresses
pinctrl: amlogic-a4: Drop surplus semicolon
pinctrl: nuvoton: Reduce use of OF-specific APIs
pinctrl: nuvoton: Convert to use struct group_desc
pinctrl: nuvoton: Make use of struct pinfunction and PINCTRL_PINFUNCTION()
pinctrl: nuvoton: Convert to use struct pingroup and PINCTRL_PINGROUP()
pinctrl: npcm8xx: Fix incorrect struct npcm8xx_pincfg assignment
pinctrl: tegra: Fix off by one in tegra_pinctrl_get_group()
pinctrl: PINCTRL_AMDISP should depend on DRM_AMD_ISP
pinctrl: qcom: sa8775p: Enable egpio function
dt-bindings: pinctrl: qcom: Add egpio function for sa8775p
pinctrl: qcom: tlmm-test: Validate irq_enable delivers edge irqs
pinctrl: qcom: Clear latched interrupt status when changing IRQ type
dt-bindings: pinctrl: airoha: Add missing gpio-ranges property
pinctrl: bcm281xx: Add missing assignment in bcm21664_pinctrl_lock_all()
pinctrl: amd: isp411: Fix IS_ERR() vs NULL check in probe()
dt-bindings: pinctrl: at91-pio4: add microchip,sama7d65-pinctrl
pinctrl: tegra: Set SFIO mode to Mux Register
pinctrl-tegra: Restore SFSEL bit when freeing pins
pinctrl: tegra: Add descriptions for SoC data fields
...
This commit is contained in:
@@ -24,6 +24,9 @@ properties:
|
||||
'#gpio-cells':
|
||||
const: 2
|
||||
|
||||
gpio-ranges:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
'#interrupt-cells':
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pinctrl/allwinner,sun55i-a523-pinctrl.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Allwinner A523 Pin Controller
|
||||
|
||||
maintainers:
|
||||
- Andre Przywara <andre.przywara@arm.com>
|
||||
|
||||
properties:
|
||||
"#gpio-cells":
|
||||
const: 3
|
||||
description:
|
||||
GPIO consumers must use three arguments, first the number of the
|
||||
bank, then the pin number inside that bank, and finally the GPIO
|
||||
flags.
|
||||
|
||||
"#interrupt-cells":
|
||||
const: 3
|
||||
description:
|
||||
Interrupts consumers must use three arguments, first the number
|
||||
of the bank, then the pin number inside that bank, and finally
|
||||
the interrupts flags.
|
||||
|
||||
compatible:
|
||||
enum:
|
||||
- allwinner,sun55i-a523-pinctrl
|
||||
- allwinner,sun55i-a523-r-pinctrl
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
minItems: 2
|
||||
maxItems: 10
|
||||
description:
|
||||
One interrupt per external interrupt bank supported on the
|
||||
controller, sorted by bank number ascending order.
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Bus Clock
|
||||
- description: High Frequency Oscillator
|
||||
- description: Low Frequency Oscillator
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: apb
|
||||
- const: hosc
|
||||
- const: losc
|
||||
|
||||
gpio-controller: true
|
||||
interrupt-controller: true
|
||||
gpio-line-names: true
|
||||
|
||||
input-debounce:
|
||||
description:
|
||||
Debouncing periods in microseconds, one period per interrupt
|
||||
bank found in the controller
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 2
|
||||
maxItems: 10
|
||||
|
||||
patternProperties:
|
||||
# It's pretty scary, but the basic idea is that:
|
||||
# - One node name can start with either s- or r- for PRCM nodes,
|
||||
# - Then, the name itself can be any repetition of <string>- (to
|
||||
# accommodate with nodes like uart4-rts-cts-pins), where each
|
||||
# string can be either starting with 'p' but in a string longer
|
||||
# than 3, or something that doesn't start with 'p',
|
||||
# - Then, the bank name is optional and will be between pa and pm.
|
||||
# Some pins groups that have several options will have the pin
|
||||
# numbers then,
|
||||
# - Finally, the name will end with either -pin or pins.
|
||||
|
||||
"^([rs]-)?(([a-z0-9]{3,}|[a-oq-z][a-z0-9]*?)?-)+?(p[a-m][0-9]*?-)??pins?$":
|
||||
type: object
|
||||
|
||||
properties:
|
||||
pins: true
|
||||
function: true
|
||||
bias-disable: true
|
||||
bias-pull-up: true
|
||||
bias-pull-down: true
|
||||
|
||||
drive-strength:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [10, 20, 30, 40]
|
||||
|
||||
allwinner,pinmux:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description:
|
||||
Pinmux selector value, for each pin. Almost every time this value
|
||||
is the same for all pins, so any array shorter than the number of
|
||||
pins will repeat the last value, to allow just specifying a single
|
||||
cell, for all cells.
|
||||
|
||||
required:
|
||||
- pins
|
||||
- allwinner,pinmux
|
||||
- function
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
"^vcc-p[a-m]-supply$":
|
||||
description:
|
||||
Power supplies for pin banks.
|
||||
|
||||
required:
|
||||
- "#gpio-cells"
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- gpio-controller
|
||||
- "#interrupt-cells"
|
||||
- interrupts
|
||||
- interrupt-controller
|
||||
|
||||
allOf:
|
||||
- $ref: pinctrl.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- allwinner,sun55i-a523-pinctrl
|
||||
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 10
|
||||
maxItems: 10
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- allwinner,sun55i-a523-r-pinctrl
|
||||
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 2
|
||||
maxItems: 2
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
r_pio: pinctrl@7022000 {
|
||||
compatible = "allwinner,sun55i-a523-r-pinctrl";
|
||||
reg = <0x7022000 0x800>;
|
||||
interrupts = <0 159 4>, <0 161 4>;
|
||||
clocks = <&r_ccu 1>, <&osc24M>, <&osc32k>;
|
||||
clock-names = "apb", "hosc", "losc";
|
||||
gpio-controller;
|
||||
#gpio-cells = <3>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <3>;
|
||||
|
||||
r_i2c_pins: r-i2c-pins {
|
||||
pins = "PL0", "PL1";
|
||||
allwinner,pinmux = <2>;
|
||||
function = "r_i2c0";
|
||||
bias-pull-up;
|
||||
};
|
||||
|
||||
r_spi_pins: r-spi-pins {
|
||||
pins = "PL11" ,"PL12", "PL13";
|
||||
allwinner,pinmux = <6>;
|
||||
function = "r_spi";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,126 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pinctrl/amlogic,pinctrl-a4.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Amlogic pinmux controller
|
||||
|
||||
maintainers:
|
||||
- Xianwei Zhao <xianwei.zhao@amlogic.com>
|
||||
|
||||
allOf:
|
||||
- $ref: pinctrl.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: amlogic,pinctrl-a4
|
||||
|
||||
"#address-cells":
|
||||
const: 2
|
||||
|
||||
"#size-cells":
|
||||
const: 2
|
||||
|
||||
ranges: true
|
||||
|
||||
patternProperties:
|
||||
"^gpio@[0-9a-f]+$":
|
||||
type: object
|
||||
|
||||
additionalProperties: false
|
||||
properties:
|
||||
reg:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: pin config register
|
||||
- description: pin mux setting register (some special pin fixed function)
|
||||
- description: pin drive strength register (optional)
|
||||
|
||||
reg-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: gpio
|
||||
- const: mux
|
||||
- const: ds
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
|
||||
gpio-ranges:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- reg
|
||||
- reg-names
|
||||
- gpio-controller
|
||||
- "#gpio-cells"
|
||||
- gpio-ranges
|
||||
|
||||
"^func-[0-9a-z-]+$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
patternProperties:
|
||||
"^group-[0-9a-z-]+$":
|
||||
type: object
|
||||
allOf:
|
||||
- $ref: /schemas/pinctrl/pincfg-node.yaml
|
||||
- $ref: /schemas/pinctrl/pinmux-node.yaml
|
||||
|
||||
required:
|
||||
- pinmux
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- ranges
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/pinctrl/amlogic,pinctrl.h>
|
||||
apb {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
periphs_pinctrl: pinctrl {
|
||||
compatible = "amlogic,pinctrl-a4";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
ranges;
|
||||
|
||||
gpio@4240 {
|
||||
reg = <0 0x4240 0 0x40>, <0 0x4000 0 0x8>;
|
||||
reg-names = "gpio", "mux";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio-ranges = <&periphs_pinctrl 0 8 10>;
|
||||
};
|
||||
|
||||
func-uart-b {
|
||||
group-default {
|
||||
pinmux = <AML_PINMUX(AMLOGIC_GPIO_B, 1, 4)>;
|
||||
bias-pull-up;
|
||||
drive-strength-microamp = <4000>;
|
||||
};
|
||||
|
||||
group-pins1 {
|
||||
pinmux = <AML_PINMUX(AMLOGIC_GPIO_B, 5, 2)>;
|
||||
bias-pull-up;
|
||||
drive-strength-microamp = <4000>;
|
||||
};
|
||||
};
|
||||
|
||||
func-uart-c {
|
||||
group-default {
|
||||
pinmux = <AML_PINMUX(AMLOGIC_GPIO_B, 3, 1)>,
|
||||
<AML_PINMUX(AMLOGIC_GPIO_B, 2, 1)>;
|
||||
bias-pull-up;
|
||||
drive-strength-microamp = <4000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -6,6 +6,7 @@ configure it.
|
||||
Required properties:
|
||||
- compatible:
|
||||
"atmel,sama5d2-pinctrl"
|
||||
"microchip,sama7d65-pinctrl", "microchip,sama7g5-pinctrl"
|
||||
"microchip,sama7g5-pinctrl"
|
||||
- reg: base address and length of the PIO controller.
|
||||
- interrupts: interrupt outputs from the controller, one for each bank.
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pinctrl/brcm,bcm21664-pinctrl.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom BCM21664 pin controller
|
||||
|
||||
maintainers:
|
||||
- Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
- Ray Jui <rjui@broadcom.com>
|
||||
- Scott Branden <sbranden@broadcom.com>
|
||||
|
||||
allOf:
|
||||
- $ref: pinctrl.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm21664-pinctrl
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
'-pins$':
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
patternProperties:
|
||||
'-grp[0-9]$':
|
||||
type: object
|
||||
|
||||
properties:
|
||||
pins:
|
||||
description:
|
||||
Specifies the name(s) of one or more pins to be configured by
|
||||
this node.
|
||||
items:
|
||||
enum: [ adcsyn, batrm, bsc1clk, bsc1dat, camcs0, camcs1, clk32k,
|
||||
clk_cx8, dclk1, dclk4, dclkreq1, dclkreq4, dmic0clk,
|
||||
dmic0dq, dsi0te, gpio00, gpio01, gpio02, gpio03, gpio04,
|
||||
gpio05, gpio06, gpio07, gpio08, gpio09, gpio10, gpio11,
|
||||
gpio12, gpio13, gpio14, gpio15, gpio16, gpio17, gpio18,
|
||||
gpio19, gpio20, gpio21, gpio22, gpio23, gpio24, gpio25,
|
||||
gpio26, gpio27, gpio28, gpio32, gpio33, gpio34, gpio93,
|
||||
gpio94, gps_calreq, gps_hostreq, gps_pablank, gps_tmark,
|
||||
icusbdm, icusbdp, lcdcs0, lcdres, lcdscl, lcdsda, lcdte,
|
||||
mdmgpio00, mdmgpio01, mdmgpio02, mdmgpio03, mdmgpio04,
|
||||
mdmgpio05, mdmgpio06, mdmgpio07, mdmgpio08, mmc0ck,
|
||||
mmc0cmd, mmc0dat0, mmc0dat1, mmc0dat2, mmc0dat3, mmc0dat4,
|
||||
mmc0dat5, mmc0dat6, mmc0dat7, mmc0rst, mmc1ck, mmc1cmd,
|
||||
mmc1dat0, mmc1dat1, mmc1dat2, mmc1dat3, mmc1dat4,
|
||||
mmc1dat5, mmc1dat6, mmc1dat7, mmc1rst, pc1, pc2, pmbscclk,
|
||||
pmbscdat, pmuint, resetn, rfst2g_mtsloten3g,
|
||||
rtxdata2g_txdata3g1, rtxen2g_txdata3g2, rxdata3g0,
|
||||
rxdata3g1, rxdata3g2, sdck, sdcmd, sddat0, sddat1, sddat2,
|
||||
sddat3, simclk, simdat, simdet, simrst, spi0clk, spi0fss,
|
||||
spi0rxd, spi0txd, sri_c, sri_d, sri_e, sspck, sspdi,
|
||||
sspdo, sspsyn, stat1, stat2, swclktck, swdiotms, sysclken,
|
||||
tdi, tdo, testmode, traceclk, tracedt00, tracedt01,
|
||||
tracedt02, tracedt03, tracedt04, tracedt05, tracedt06,
|
||||
tracedt07, tracedt08, tracedt09, tracedt10, tracedt11,
|
||||
tracedt12, tracedt13, tracedt14, tracedt15, trstb,
|
||||
txdata3g0, ubctsn, ubrtsn, ubrx, ubtx ]
|
||||
|
||||
function:
|
||||
description:
|
||||
Specifies the pin mux selection.
|
||||
enum: [ alt1, alt2, alt3, alt4, alt5, alt6 ]
|
||||
|
||||
bias-disable: true
|
||||
|
||||
bias-pull-up:
|
||||
type: boolean
|
||||
|
||||
bias-pull-down:
|
||||
type: boolean
|
||||
|
||||
slew-rate:
|
||||
description: |
|
||||
Meaning depends on configured pin mux:
|
||||
bsc*clk/pmbscclk or bsc*dat/pmbscdat or gpio16/gpio17:
|
||||
0: Standard (100 kbps) & Fast (400 kbps) mode
|
||||
1: Highspeed (3.4 Mbps) mode
|
||||
Otherwise:
|
||||
0: fast slew rate
|
||||
1: normal slew rate
|
||||
|
||||
drive-strength:
|
||||
enum: [ 2, 4, 6, 8, 10, 12, 14, 16 ]
|
||||
|
||||
input-enable: true
|
||||
input-disable: true
|
||||
|
||||
input-schmitt-enable: true
|
||||
input-schmitt-disable: true
|
||||
|
||||
required:
|
||||
- pins
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- $ref: pincfg-node.yaml#
|
||||
# Limitations for I2C pins
|
||||
- if:
|
||||
properties:
|
||||
pins:
|
||||
contains:
|
||||
enum: [ bsc1clk, bsc1dat, gpio16, gpio17, pmbscclk,
|
||||
pmbscdat ]
|
||||
then:
|
||||
properties:
|
||||
drive-strength: false
|
||||
bias-pull-down: false
|
||||
input-schmitt-enable: false
|
||||
input-schmitt-disable: false
|
||||
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
pinctrl@35004800 {
|
||||
compatible = "brcm,bcm21664-pinctrl";
|
||||
reg = <0x35004800 0x7f0>;
|
||||
|
||||
dev-a-active-pins {
|
||||
/* group node defining 1 standard pin */
|
||||
std-grp0 {
|
||||
pins = "gpio00";
|
||||
function = "alt1";
|
||||
input-schmitt-enable;
|
||||
bias-disable;
|
||||
slew-rate = <1>;
|
||||
drive-strength = <4>;
|
||||
};
|
||||
|
||||
/* group node defining 2 I2C pins */
|
||||
i2c-grp0 {
|
||||
pins = "bsc1clk", "bsc1dat";
|
||||
function = "alt2";
|
||||
bias-pull-up;
|
||||
input-enable;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -42,6 +42,7 @@ properties:
|
||||
- ingenic,jz4780-pinctrl
|
||||
- ingenic,x1000-pinctrl
|
||||
- ingenic,x1500-pinctrl
|
||||
- ingenic,x1600-pinctrl
|
||||
- ingenic,x1830-pinctrl
|
||||
- ingenic,x2000-pinctrl
|
||||
- ingenic,x2100-pinctrl
|
||||
@@ -81,6 +82,7 @@ patternProperties:
|
||||
- ingenic,jz4780-gpio
|
||||
- ingenic,x1000-gpio
|
||||
- ingenic,x1500-gpio
|
||||
- ingenic,x1600-gpio
|
||||
- ingenic,x1830-gpio
|
||||
- ingenic,x2000-gpio
|
||||
- ingenic,x2100-gpio
|
||||
|
||||
@@ -79,7 +79,7 @@ $defs:
|
||||
cri_trng, cri_trng0, cri_trng1, dbg_out, ddr_bist, ddr_pxi0,
|
||||
ddr_pxi1, ddr_pxi2, ddr_pxi3, ddr_pxi4, ddr_pxi5, edp0_hot,
|
||||
edp0_lcd, edp1_hot, edp1_lcd, edp2_hot, edp2_lcd, edp3_hot,
|
||||
edp3_lcd, emac0_mcg0, emac0_mcg1, emac0_mcg2, emac0_mcg3,
|
||||
edp3_lcd, egpio, emac0_mcg0, emac0_mcg1, emac0_mcg2, emac0_mcg3,
|
||||
emac0_mdc, emac0_mdio, emac0_ptp_aux, emac0_ptp_pps, emac1_mcg0,
|
||||
emac1_mcg1, emac1_mcg2, emac1_mcg3, emac1_mdc, emac1_mdio,
|
||||
emac1_ptp_aux, emac1_ptp_pps, gcc_gp1, gcc_gp2, gcc_gp3,
|
||||
|
||||
@@ -44,6 +44,7 @@ properties:
|
||||
- rockchip,rk3328-pinctrl
|
||||
- rockchip,rk3368-pinctrl
|
||||
- rockchip,rk3399-pinctrl
|
||||
- rockchip,rk3528-pinctrl
|
||||
- rockchip,rk3562-pinctrl
|
||||
- rockchip,rk3568-pinctrl
|
||||
- rockchip,rk3576-pinctrl
|
||||
|
||||
@@ -40,6 +40,7 @@ properties:
|
||||
- items:
|
||||
- enum:
|
||||
- samsung,exynos5433-wakeup-eint
|
||||
- samsung,exynos7870-wakeup-eint
|
||||
- samsung,exynos7885-wakeup-eint
|
||||
- samsung,exynos850-wakeup-eint
|
||||
- samsung,exynos8895-wakeup-eint
|
||||
@@ -47,6 +48,7 @@ properties:
|
||||
- items:
|
||||
- enum:
|
||||
- google,gs101-wakeup-eint
|
||||
- samsung,exynos2200-wakeup-eint
|
||||
- samsung,exynos9810-wakeup-eint
|
||||
- samsung,exynos990-wakeup-eint
|
||||
- samsung,exynosautov9-wakeup-eint
|
||||
@@ -104,6 +106,7 @@ allOf:
|
||||
- contains:
|
||||
enum:
|
||||
- samsung,exynos5433-wakeup-eint
|
||||
- samsung,exynos7870-wakeup-eint
|
||||
- samsung,exynos7885-wakeup-eint
|
||||
- samsung,exynos8895-wakeup-eint
|
||||
then:
|
||||
|
||||
@@ -42,6 +42,7 @@ properties:
|
||||
- samsung,s3c2450-pinctrl
|
||||
- samsung,s3c64xx-pinctrl
|
||||
- samsung,s5pv210-pinctrl
|
||||
- samsung,exynos2200-pinctrl
|
||||
- samsung,exynos3250-pinctrl
|
||||
- samsung,exynos4210-pinctrl
|
||||
- samsung,exynos4x12-pinctrl
|
||||
@@ -51,6 +52,7 @@ properties:
|
||||
- samsung,exynos5420-pinctrl
|
||||
- samsung,exynos5433-pinctrl
|
||||
- samsung,exynos7-pinctrl
|
||||
- samsung,exynos7870-pinctrl
|
||||
- samsung,exynos7885-pinctrl
|
||||
- samsung,exynos850-pinctrl
|
||||
- samsung,exynos8895-pinctrl
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pinctrl/sophgo,sg2042-pinctrl.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sophgo SG2042 Pin Controller
|
||||
|
||||
maintainers:
|
||||
- Inochi Amaoto <inochiama@outlook.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- sophgo,sg2042-pinctrl
|
||||
- sophgo,sg2044-pinctrl
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
'-cfg$':
|
||||
type: object
|
||||
description:
|
||||
A pinctrl node should contain at least one subnode representing the
|
||||
pinctrl groups available on the machine.
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
patternProperties:
|
||||
'-pins$':
|
||||
type: object
|
||||
description: |
|
||||
Each subnode will list the pins it needs, and how they should
|
||||
be configured, with regard to muxer configuration, bias input
|
||||
enable/disable, input schmitt trigger enable, drive strength
|
||||
output enable/disable state. For configuration detail,
|
||||
refer to https://github.com/sophgo/sophgo-doc/.
|
||||
|
||||
allOf:
|
||||
- $ref: pincfg-node.yaml#
|
||||
- $ref: pinmux-node.yaml#
|
||||
|
||||
properties:
|
||||
pinmux:
|
||||
description: |
|
||||
The list of GPIOs and their mux settings that properties in the
|
||||
node apply to. This should be set using the PINMUX macro.
|
||||
|
||||
bias-disable: true
|
||||
|
||||
bias-pull-up:
|
||||
type: boolean
|
||||
|
||||
bias-pull-down:
|
||||
type: boolean
|
||||
|
||||
drive-strength-microamp:
|
||||
description: typical current when output low level.
|
||||
|
||||
input-schmitt-enable: true
|
||||
|
||||
input-schmitt-disable: true
|
||||
|
||||
required:
|
||||
- pinmux
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: sophgo,sg2042-pinctrl
|
||||
then:
|
||||
patternProperties:
|
||||
'-cfg$':
|
||||
patternProperties:
|
||||
'-pins$':
|
||||
properties:
|
||||
drive-strength-microamp:
|
||||
enum: [ 5400, 8100, 10700, 13400,
|
||||
16100, 18800, 21400, 24100,
|
||||
26800, 29400, 32100, 34800,
|
||||
37400, 40100, 42800, 45400 ]
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: sophgo,sg2044-pinctrl
|
||||
then:
|
||||
patternProperties:
|
||||
'-cfg$':
|
||||
patternProperties:
|
||||
'-pins$':
|
||||
properties:
|
||||
drive-strength-microamp:
|
||||
enum: [ 3200, 6400, 9600, 12700,
|
||||
15900, 19100, 22200, 25300,
|
||||
29500, 32700, 35900, 39000,
|
||||
42000, 45200, 48300, 51400]
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/pinctrl/pinctrl-sg2042.h>
|
||||
|
||||
pinctrl@30011000 {
|
||||
compatible = "sophgo,sg2042-pinctrl";
|
||||
reg = <30011000 0x1000>;
|
||||
|
||||
uart0_cfg: uart0-cfg {
|
||||
uart0-pins {
|
||||
pinmux = <PINMUX(PIN_UART0_TX, 0)>,
|
||||
<PINMUX(PIN_UART0_RX, 0)>;
|
||||
bias-pull-up;
|
||||
drive-strength-microamp = <13400>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
15
MAINTAINERS
15
MAINTAINERS
@@ -1253,6 +1253,14 @@ F: Documentation/devicetree/bindings/perf/amlogic,g12-ddr-pmu.yaml
|
||||
F: drivers/perf/amlogic/
|
||||
F: include/soc/amlogic/
|
||||
|
||||
AMLOGIC PINCTRL DRIVER
|
||||
M: Xianwei Zhao <xianwei.zhao@amlogic.com>
|
||||
L: linux-amlogic@lists.infradead.org
|
||||
L: linux-gpio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/pinctrl/amlogic,pinctrl-a4.yaml
|
||||
F: drivers/pinctrl/meson/pinctrl-amlogic-a4.c
|
||||
|
||||
AMLOGIC RTC DRIVER
|
||||
M: Yiting Deng <yiting.deng@amlogic.com>
|
||||
M: Xianwei Zhao <xianwei.zhao@amlogic.com>
|
||||
@@ -12050,12 +12058,19 @@ S: Supported
|
||||
F: arch/x86/include/asm/intel-mid.h
|
||||
F: arch/x86/pci/intel_mid_pci.c
|
||||
F: arch/x86/platform/intel-mid/
|
||||
F: drivers/dma/hsu/
|
||||
F: drivers/extcon/extcon-intel-mrfld.c
|
||||
F: drivers/gpio/gpio-merrifield.c
|
||||
F: drivers/gpio/gpio-tangier.*
|
||||
F: drivers/iio/adc/intel_mrfld_adc.c
|
||||
F: drivers/mfd/intel_soc_pmic_mrfld.c
|
||||
F: drivers/pinctrl/intel/pinctrl-merrifield.c
|
||||
F: drivers/pinctrl/intel/pinctrl-moorefield.c
|
||||
F: drivers/pinctrl/intel/pinctrl-tangier.*
|
||||
F: drivers/platform/x86/intel/mrfld_pwrbtn.c
|
||||
F: drivers/platform/x86/intel_scu_*
|
||||
F: drivers/staging/media/atomisp/
|
||||
F: drivers/tty/serial/8250/8250_mid.c
|
||||
F: drivers/watchdog/intel-mid_wdt.c
|
||||
F: include/linux/mfd/intel_soc_pmic_mrfld.h
|
||||
F: include/linux/platform_data/x86/intel-mid_wdt.h
|
||||
|
||||
@@ -1245,8 +1245,8 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, unsigned int *conf, int irq)
|
||||
channel_templates = xadc_us_channels;
|
||||
max_channels = ARRAY_SIZE(xadc_us_channels);
|
||||
}
|
||||
channels = devm_kmemdup(dev, channel_templates,
|
||||
sizeof(channels[0]) * max_channels, GFP_KERNEL);
|
||||
channels = devm_kmemdup_array(dev, channel_templates, max_channels,
|
||||
sizeof(*channel_templates), GFP_KERNEL);
|
||||
if (!channels)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -102,9 +102,8 @@ static int micro_key_probe(struct platform_device *pdev)
|
||||
|
||||
keys->input->keycodesize = sizeof(micro_keycodes[0]);
|
||||
keys->input->keycodemax = ARRAY_SIZE(micro_keycodes);
|
||||
keys->codes = devm_kmemdup(&pdev->dev, micro_keycodes,
|
||||
keys->input->keycodesize * keys->input->keycodemax,
|
||||
GFP_KERNEL);
|
||||
keys->codes = devm_kmemdup_array(&pdev->dev, micro_keycodes, keys->input->keycodemax,
|
||||
keys->input->keycodesize, GFP_KERNEL);
|
||||
if (!keys->codes)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -176,8 +176,7 @@ int sparse_keymap_setup(struct input_dev *dev,
|
||||
for (e = keymap; e->type != KE_END; e++)
|
||||
map_size++;
|
||||
|
||||
map = devm_kmemdup(&dev->dev, keymap, map_size * sizeof(*map),
|
||||
GFP_KERNEL);
|
||||
map = devm_kmemdup_array(&dev->dev, keymap, map_size, sizeof(*keymap), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -49,6 +49,20 @@ config PINCTRL_AMD
|
||||
Requires ACPI/FDT device enumeration code to set up a platform
|
||||
device.
|
||||
|
||||
config PINCTRL_AMDISP
|
||||
tristate "AMDISP GPIO pin control"
|
||||
depends on DRM_AMD_ISP || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
select GPIOLIB
|
||||
select PINCONF
|
||||
select GENERIC_PINCONF
|
||||
help
|
||||
The driver for memory mapped GPIO functionality on AMD platforms
|
||||
with ISP support. All the pins are output controlled only
|
||||
|
||||
Requires AMDGPU to MFD add device for enumeration to set up as
|
||||
platform device.
|
||||
|
||||
config PINCTRL_APPLE_GPIO
|
||||
tristate "Apple SoC GPIO pin controller driver"
|
||||
depends on ARCH_APPLE
|
||||
|
||||
@@ -10,6 +10,7 @@ obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o
|
||||
obj-$(CONFIG_OF) += devicetree.o
|
||||
|
||||
obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o
|
||||
obj-$(CONFIG_PINCTRL_AMDISP) += pinctrl-amdisp.o
|
||||
obj-$(CONFIG_PINCTRL_APPLE_GPIO) += pinctrl-apple-gpio.o
|
||||
obj-$(CONFIG_PINCTRL_ARTPEC6) += pinctrl-artpec6.o
|
||||
obj-$(CONFIG_PINCTRL_AS3722) += pinctrl-as3722.o
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -346,14 +346,14 @@ static int bcm2835_gpio_get_direction(struct gpio_chip *chip, unsigned int offse
|
||||
struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
|
||||
enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset);
|
||||
|
||||
/* Alternative function doesn't clearly provide a direction */
|
||||
if (fsel > BCM2835_FSEL_GPIO_OUT)
|
||||
return -EINVAL;
|
||||
if (fsel == BCM2835_FSEL_GPIO_OUT)
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
|
||||
if (fsel == BCM2835_FSEL_GPIO_IN)
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
/*
|
||||
* Alternative function doesn't clearly provide a direction. Default
|
||||
* to INPUT.
|
||||
*/
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
|
||||
@@ -143,10 +143,14 @@ static int dt_to_map_one_config(struct pinctrl *p,
|
||||
pctldev = get_pinctrl_dev_from_of_node(np_pctldev);
|
||||
if (pctldev)
|
||||
break;
|
||||
/* Do not defer probing of hogs (circular loop) */
|
||||
/*
|
||||
* Do not defer probing of hogs (circular loop)
|
||||
*
|
||||
* Return 1 to let the caller catch the case.
|
||||
*/
|
||||
if (np_pctldev == p->dev->of_node) {
|
||||
of_node_put(np_pctldev);
|
||||
return -ENODEV;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
of_node_put(np_pctldev);
|
||||
@@ -265,6 +269,8 @@ int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev)
|
||||
ret = dt_to_map_one_config(p, pctldev, statename,
|
||||
np_config);
|
||||
of_node_put(np_config);
|
||||
if (ret == 1)
|
||||
continue;
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ config PINCTRL_INTEL
|
||||
|
||||
config PINCTRL_INTEL_PLATFORM
|
||||
tristate "Intel pinctrl and GPIO platform driver"
|
||||
depends on ACPI
|
||||
select PINCTRL_INTEL
|
||||
help
|
||||
This pinctrl driver provides an interface that allows configuring
|
||||
@@ -141,7 +140,6 @@ config PINCTRL_METEORLAKE
|
||||
|
||||
config PINCTRL_METEORPOINT
|
||||
tristate "Intel Meteor Point pinctrl and GPIO driver"
|
||||
depends on ACPI
|
||||
select PINCTRL_INTEL
|
||||
help
|
||||
Meteor Point is the PCH of Intel Meteor Lake. This pinctrl driver
|
||||
|
||||
@@ -1355,6 +1355,8 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
|
||||
void __iomem *reg;
|
||||
unsigned long pending;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
/* check from GPIO controller which pin triggered the interrupt */
|
||||
for (base = 0; base < vg->chip.ngpio; base += 32) {
|
||||
reg = byt_gpio_reg(vg, base, BYT_INT_STAT_REG);
|
||||
@@ -1369,7 +1371,8 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
|
||||
for_each_set_bit(pin, &pending, 32)
|
||||
generic_handle_domain_irq(vg->chip.irq.domain, base + pin);
|
||||
}
|
||||
chip->irq_eoi(data);
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static bool byt_direct_irq_sanity_check(struct intel_pinctrl *vg, int pin, u32 conf0)
|
||||
@@ -1557,16 +1560,14 @@ static int byt_set_soc_data(struct intel_pinctrl *vg,
|
||||
vg->soc = soc;
|
||||
|
||||
vg->ncommunities = vg->soc->ncommunities;
|
||||
vg->communities = devm_kcalloc(vg->dev, vg->ncommunities,
|
||||
sizeof(*vg->communities), GFP_KERNEL);
|
||||
vg->communities = devm_kmemdup_array(vg->dev, vg->soc->communities, vg->ncommunities,
|
||||
sizeof(*vg->soc->communities), GFP_KERNEL);
|
||||
if (!vg->communities)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < vg->soc->ncommunities; i++) {
|
||||
struct intel_community *comm = vg->communities + i;
|
||||
|
||||
*comm = vg->soc->communities[i];
|
||||
|
||||
comm->pad_regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(comm->pad_regs))
|
||||
return PTR_ERR(comm->pad_regs);
|
||||
|
||||
@@ -1631,9 +1631,8 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
|
||||
pctrl->soc = soc_data;
|
||||
|
||||
pctrl->ncommunities = pctrl->soc->ncommunities;
|
||||
pctrl->communities = devm_kmemdup(dev, pctrl->soc->communities,
|
||||
pctrl->ncommunities * sizeof(*pctrl->communities),
|
||||
GFP_KERNEL);
|
||||
pctrl->communities = devm_kmemdup_array(dev, pctrl->soc->communities, pctrl->ncommunities,
|
||||
sizeof(*pctrl->soc->communities), GFP_KERNEL);
|
||||
if (!pctrl->communities)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -1543,7 +1543,6 @@ static int intel_pinctrl_probe_pwm(struct intel_pinctrl *pctrl,
|
||||
.clk_rate = 19200000,
|
||||
.npwm = 1,
|
||||
.base_unit_bits = 22,
|
||||
.bypass = true,
|
||||
};
|
||||
struct pwm_chip *chip;
|
||||
|
||||
@@ -1577,8 +1576,8 @@ int intel_pinctrl_probe(struct platform_device *pdev,
|
||||
* to the registers.
|
||||
*/
|
||||
pctrl->ncommunities = pctrl->soc->ncommunities;
|
||||
pctrl->communities = devm_kcalloc(dev, pctrl->ncommunities,
|
||||
sizeof(*pctrl->communities), GFP_KERNEL);
|
||||
pctrl->communities = devm_kmemdup_array(dev, pctrl->soc->communities, pctrl->ncommunities,
|
||||
sizeof(*pctrl->soc->communities), GFP_KERNEL);
|
||||
if (!pctrl->communities)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1588,8 +1587,6 @@ int intel_pinctrl_probe(struct platform_device *pdev,
|
||||
u32 offset;
|
||||
u32 value;
|
||||
|
||||
*community = pctrl->soc->communities[i];
|
||||
|
||||
regs = devm_platform_ioremap_resource(pdev, community->barno);
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
@@ -1941,3 +1938,4 @@ MODULE_AUTHOR("Mathias Nyman <mathias.nyman@linux.intel.com>");
|
||||
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
|
||||
MODULE_DESCRIPTION("Intel pinctrl/GPIO core driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_IMPORT_NS("PWM_LPSS");
|
||||
|
||||
@@ -549,6 +549,8 @@ static void lp_gpio_irq_handler(struct irq_desc *desc)
|
||||
unsigned long pending;
|
||||
u32 base, pin;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
|
||||
/* check from GPIO controller which pin triggered the interrupt */
|
||||
for (base = 0; base < lg->chip.ngpio; base += 32) {
|
||||
reg = lp_gpio_reg(&lg->chip, base, LP_INT_STAT);
|
||||
@@ -560,7 +562,8 @@ static void lp_gpio_irq_handler(struct irq_desc *desc)
|
||||
for_each_set_bit(pin, &pending, 32)
|
||||
generic_handle_domain_irq(lg->chip.irq.domain, base + pin);
|
||||
}
|
||||
chip->irq_eoi(data);
|
||||
|
||||
chained_irq_exit(chip, desc);
|
||||
}
|
||||
|
||||
static void lp_irq_ack(struct irq_data *d)
|
||||
|
||||
@@ -524,7 +524,6 @@ static int tng_pinctrl_probe(struct platform_device *pdev,
|
||||
struct device *dev = &pdev->dev;
|
||||
struct tng_family *families;
|
||||
struct tng_pinctrl *tp;
|
||||
size_t families_len;
|
||||
void __iomem *regs;
|
||||
unsigned int i;
|
||||
|
||||
@@ -543,8 +542,8 @@ static int tng_pinctrl_probe(struct platform_device *pdev,
|
||||
* Make a copy of the families which we can use to hold pointers
|
||||
* to the registers.
|
||||
*/
|
||||
families_len = size_mul(sizeof(*families), tp->nfamilies);
|
||||
families = devm_kmemdup(dev, tp->families, families_len, GFP_KERNEL);
|
||||
families = devm_kmemdup_array(dev, tp->families, tp->nfamilies,
|
||||
sizeof(*tp->families), GFP_KERNEL);
|
||||
if (!families)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (c) 2014-2018 MediaTek Inc.
|
||||
// Copyright (c) 2014-2025 MediaTek Inc.
|
||||
|
||||
/*
|
||||
* Library for MediaTek External Interrupt Support
|
||||
*
|
||||
* Author: Maoguang Meng <maoguang.meng@mediatek.com>
|
||||
* Sean Wang <sean.wang@mediatek.com>
|
||||
* Hao Chang <ot_chhao.chang@mediatek.com>
|
||||
* Qingliang Li <qingliang.li@mediatek.com>
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -20,6 +22,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "mtk-eint.h"
|
||||
#include "pinctrl-mtk-common-v2.h"
|
||||
|
||||
#define MTK_EINT_EDGE_SENSITIVE 0
|
||||
#define MTK_EINT_LEVEL_SENSITIVE 1
|
||||
@@ -68,13 +71,11 @@ static void __iomem *mtk_eint_get_offset(struct mtk_eint *eint,
|
||||
unsigned int eint_num,
|
||||
unsigned int offset)
|
||||
{
|
||||
unsigned int eint_base = 0;
|
||||
unsigned int idx = eint->pins[eint_num].index;
|
||||
unsigned int inst = eint->pins[eint_num].instance;
|
||||
void __iomem *reg;
|
||||
|
||||
if (eint_num >= eint->hw->ap_num)
|
||||
eint_base = eint->hw->ap_num;
|
||||
|
||||
reg = eint->base + offset + ((eint_num - eint_base) / 32) * 4;
|
||||
reg = eint->base[inst] + offset + (idx / 32 * 4);
|
||||
|
||||
return reg;
|
||||
}
|
||||
@@ -83,7 +84,7 @@ static unsigned int mtk_eint_can_en_debounce(struct mtk_eint *eint,
|
||||
unsigned int eint_num)
|
||||
{
|
||||
unsigned int sens;
|
||||
unsigned int bit = BIT(eint_num % 32);
|
||||
unsigned int bit = BIT(eint->pins[eint_num].index % 32);
|
||||
void __iomem *reg = mtk_eint_get_offset(eint, eint_num,
|
||||
eint->regs->sens);
|
||||
|
||||
@@ -92,7 +93,7 @@ static unsigned int mtk_eint_can_en_debounce(struct mtk_eint *eint,
|
||||
else
|
||||
sens = MTK_EINT_EDGE_SENSITIVE;
|
||||
|
||||
if (eint_num < eint->hw->db_cnt && sens != MTK_EINT_EDGE_SENSITIVE)
|
||||
if (eint->pins[eint_num].debounce && sens != MTK_EINT_EDGE_SENSITIVE)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
@@ -102,9 +103,9 @@ static int mtk_eint_flip_edge(struct mtk_eint *eint, int hwirq)
|
||||
{
|
||||
int start_level, curr_level;
|
||||
unsigned int reg_offset;
|
||||
u32 mask = BIT(hwirq & 0x1f);
|
||||
u32 port = (hwirq >> 5) & eint->hw->port_mask;
|
||||
void __iomem *reg = eint->base + (port << 2);
|
||||
unsigned int mask = BIT(eint->pins[hwirq].index & 0x1f);
|
||||
unsigned int port = (eint->pins[hwirq].index >> 5) & eint->hw->port_mask;
|
||||
void __iomem *reg = eint->base[eint->pins[hwirq].instance] + (port << 2);
|
||||
|
||||
curr_level = eint->gpio_xlate->get_gpio_state(eint->pctl, hwirq);
|
||||
|
||||
@@ -126,11 +127,13 @@ static int mtk_eint_flip_edge(struct mtk_eint *eint, int hwirq)
|
||||
static void mtk_eint_mask(struct irq_data *d)
|
||||
{
|
||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||
u32 mask = BIT(d->hwirq & 0x1f);
|
||||
unsigned int idx = eint->pins[d->hwirq].index;
|
||||
unsigned int inst = eint->pins[d->hwirq].instance;
|
||||
unsigned int mask = BIT(idx & 0x1f);
|
||||
void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
|
||||
eint->regs->mask_set);
|
||||
|
||||
eint->cur_mask[d->hwirq >> 5] &= ~mask;
|
||||
eint->cur_mask[inst][idx >> 5] &= ~mask;
|
||||
|
||||
writel(mask, reg);
|
||||
}
|
||||
@@ -138,22 +141,24 @@ static void mtk_eint_mask(struct irq_data *d)
|
||||
static void mtk_eint_unmask(struct irq_data *d)
|
||||
{
|
||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||
u32 mask = BIT(d->hwirq & 0x1f);
|
||||
unsigned int idx = eint->pins[d->hwirq].index;
|
||||
unsigned int inst = eint->pins[d->hwirq].instance;
|
||||
unsigned int mask = BIT(idx & 0x1f);
|
||||
void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
|
||||
eint->regs->mask_clr);
|
||||
|
||||
eint->cur_mask[d->hwirq >> 5] |= mask;
|
||||
eint->cur_mask[inst][idx >> 5] |= mask;
|
||||
|
||||
writel(mask, reg);
|
||||
|
||||
if (eint->dual_edge[d->hwirq])
|
||||
if (eint->pins[d->hwirq].dual_edge)
|
||||
mtk_eint_flip_edge(eint, d->hwirq);
|
||||
}
|
||||
|
||||
static unsigned int mtk_eint_get_mask(struct mtk_eint *eint,
|
||||
unsigned int eint_num)
|
||||
{
|
||||
unsigned int bit = BIT(eint_num % 32);
|
||||
unsigned int bit = BIT(eint->pins[eint_num].index % 32);
|
||||
void __iomem *reg = mtk_eint_get_offset(eint, eint_num,
|
||||
eint->regs->mask);
|
||||
|
||||
@@ -163,7 +168,7 @@ static unsigned int mtk_eint_get_mask(struct mtk_eint *eint,
|
||||
static void mtk_eint_ack(struct irq_data *d)
|
||||
{
|
||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||
u32 mask = BIT(d->hwirq & 0x1f);
|
||||
unsigned int mask = BIT(eint->pins[d->hwirq].index & 0x1f);
|
||||
void __iomem *reg = mtk_eint_get_offset(eint, d->hwirq,
|
||||
eint->regs->ack);
|
||||
|
||||
@@ -174,7 +179,7 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||
bool masked;
|
||||
u32 mask = BIT(d->hwirq & 0x1f);
|
||||
unsigned int mask = BIT(eint->pins[d->hwirq].index & 0x1f);
|
||||
void __iomem *reg;
|
||||
|
||||
if (((type & IRQ_TYPE_EDGE_BOTH) && (type & IRQ_TYPE_LEVEL_MASK)) ||
|
||||
@@ -186,9 +191,9 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
|
||||
}
|
||||
|
||||
if ((type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
|
||||
eint->dual_edge[d->hwirq] = 1;
|
||||
eint->pins[d->hwirq].dual_edge = 1;
|
||||
else
|
||||
eint->dual_edge[d->hwirq] = 0;
|
||||
eint->pins[d->hwirq].dual_edge = 0;
|
||||
|
||||
if (!mtk_eint_get_mask(eint, d->hwirq)) {
|
||||
mtk_eint_mask(d);
|
||||
@@ -223,27 +228,32 @@ static int mtk_eint_set_type(struct irq_data *d, unsigned int type)
|
||||
static int mtk_eint_irq_set_wake(struct irq_data *d, unsigned int on)
|
||||
{
|
||||
struct mtk_eint *eint = irq_data_get_irq_chip_data(d);
|
||||
int shift = d->hwirq & 0x1f;
|
||||
int reg = d->hwirq >> 5;
|
||||
unsigned int idx = eint->pins[d->hwirq].index;
|
||||
unsigned int inst = eint->pins[d->hwirq].instance;
|
||||
unsigned int shift = idx & 0x1f;
|
||||
unsigned int port = idx >> 5;
|
||||
|
||||
if (on)
|
||||
eint->wake_mask[reg] |= BIT(shift);
|
||||
eint->wake_mask[inst][port] |= BIT(shift);
|
||||
else
|
||||
eint->wake_mask[reg] &= ~BIT(shift);
|
||||
eint->wake_mask[inst][port] &= ~BIT(shift);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mtk_eint_chip_write_mask(const struct mtk_eint *eint,
|
||||
void __iomem *base, u32 *buf)
|
||||
void __iomem *base, unsigned int **buf)
|
||||
{
|
||||
int port;
|
||||
int inst, port, port_num;
|
||||
void __iomem *reg;
|
||||
|
||||
for (port = 0; port < eint->hw->ports; port++) {
|
||||
reg = base + (port << 2);
|
||||
writel_relaxed(~buf[port], reg + eint->regs->mask_set);
|
||||
writel_relaxed(buf[port], reg + eint->regs->mask_clr);
|
||||
for (inst = 0; inst < eint->nbase; inst++) {
|
||||
port_num = DIV_ROUND_UP(eint->base_pin_num[inst], 32);
|
||||
for (port = 0; port < port_num; port++) {
|
||||
reg = eint->base[inst] + (port << 2);
|
||||
writel_relaxed(~buf[inst][port], reg + eint->regs->mask_set);
|
||||
writel_relaxed(buf[inst][port], reg + eint->regs->mask_clr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,15 +313,18 @@ static struct irq_chip mtk_eint_irq_chip = {
|
||||
|
||||
static unsigned int mtk_eint_hw_init(struct mtk_eint *eint)
|
||||
{
|
||||
void __iomem *dom_en = eint->base + eint->regs->dom_en;
|
||||
void __iomem *mask_set = eint->base + eint->regs->mask_set;
|
||||
unsigned int i;
|
||||
void __iomem *dom_reg, *mask_reg;
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < eint->hw->ap_num; i += 32) {
|
||||
writel(0xffffffff, dom_en);
|
||||
writel(0xffffffff, mask_set);
|
||||
dom_en += 4;
|
||||
mask_set += 4;
|
||||
for (i = 0; i < eint->nbase; i++) {
|
||||
dom_reg = eint->base[i] + eint->regs->dom_en;
|
||||
mask_reg = eint->base[i] + eint->regs->mask_set;
|
||||
for (j = 0; j < eint->base_pin_num[i]; j += 32) {
|
||||
writel(0xffffffff, dom_reg);
|
||||
writel(0xffffffff, mask_reg);
|
||||
dom_reg += 4;
|
||||
mask_reg += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -322,14 +335,16 @@ mtk_eint_debounce_process(struct mtk_eint *eint, int index)
|
||||
{
|
||||
unsigned int rst, ctrl_offset;
|
||||
unsigned int bit, dbnc;
|
||||
unsigned int inst = eint->pins[index].instance;
|
||||
unsigned int idx = eint->pins[index].index;
|
||||
|
||||
ctrl_offset = (index / 4) * 4 + eint->regs->dbnc_ctrl;
|
||||
dbnc = readl(eint->base + ctrl_offset);
|
||||
bit = MTK_EINT_DBNC_SET_EN << ((index % 4) * 8);
|
||||
ctrl_offset = (idx / 4) * 4 + eint->regs->dbnc_ctrl;
|
||||
dbnc = readl(eint->base[inst] + ctrl_offset);
|
||||
bit = MTK_EINT_DBNC_SET_EN << ((idx % 4) * 8);
|
||||
if ((bit & dbnc) > 0) {
|
||||
ctrl_offset = (index / 4) * 4 + eint->regs->dbnc_set;
|
||||
rst = MTK_EINT_DBNC_RST_BIT << ((index % 4) * 8);
|
||||
writel(rst, eint->base + ctrl_offset);
|
||||
ctrl_offset = (idx / 4) * 4 + eint->regs->dbnc_set;
|
||||
rst = MTK_EINT_DBNC_RST_BIT << ((idx % 4) * 8);
|
||||
writel(rst, eint->base[inst] + ctrl_offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,65 +352,68 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_chip *chip = irq_desc_get_chip(desc);
|
||||
struct mtk_eint *eint = irq_desc_get_handler_data(desc);
|
||||
unsigned int status, eint_num;
|
||||
int offset, mask_offset, index;
|
||||
void __iomem *reg = mtk_eint_get_offset(eint, 0, eint->regs->stat);
|
||||
unsigned int i, j, port, status, shift, mask, eint_num;
|
||||
void __iomem *reg;
|
||||
int dual_edge, start_level, curr_level;
|
||||
|
||||
chained_irq_enter(chip, desc);
|
||||
for (eint_num = 0; eint_num < eint->hw->ap_num; eint_num += 32,
|
||||
reg += 4) {
|
||||
status = readl(reg);
|
||||
while (status) {
|
||||
offset = __ffs(status);
|
||||
mask_offset = eint_num >> 5;
|
||||
index = eint_num + offset;
|
||||
status &= ~BIT(offset);
|
||||
|
||||
/*
|
||||
* If we get an interrupt on pin that was only required
|
||||
* for wake (but no real interrupt requested), mask the
|
||||
* interrupt (as would mtk_eint_resume do anyway later
|
||||
* in the resume sequence).
|
||||
*/
|
||||
if (eint->wake_mask[mask_offset] & BIT(offset) &&
|
||||
!(eint->cur_mask[mask_offset] & BIT(offset))) {
|
||||
writel_relaxed(BIT(offset), reg -
|
||||
eint->regs->stat +
|
||||
eint->regs->mask_set);
|
||||
}
|
||||
|
||||
dual_edge = eint->dual_edge[index];
|
||||
if (dual_edge) {
|
||||
/*
|
||||
* Clear soft-irq in case we raised it last
|
||||
* time.
|
||||
*/
|
||||
writel(BIT(offset), reg - eint->regs->stat +
|
||||
eint->regs->soft_clr);
|
||||
|
||||
start_level =
|
||||
eint->gpio_xlate->get_gpio_state(eint->pctl,
|
||||
index);
|
||||
}
|
||||
|
||||
generic_handle_domain_irq(eint->domain, index);
|
||||
|
||||
if (dual_edge) {
|
||||
curr_level = mtk_eint_flip_edge(eint, index);
|
||||
for (i = 0; i < eint->nbase; i++) {
|
||||
for (j = 0; j < eint->base_pin_num[i]; j += 32) {
|
||||
port = j >> 5;
|
||||
status = readl(eint->base[i] + port * 4 + eint->regs->stat);
|
||||
while (status) {
|
||||
shift = __ffs(status);
|
||||
status &= ~BIT(shift);
|
||||
mask = BIT(shift);
|
||||
eint_num = eint->pin_list[i][shift + j];
|
||||
|
||||
/*
|
||||
* If level changed, we might lost one edge
|
||||
* interrupt, raised it through soft-irq.
|
||||
* If we get an interrupt on pin that was only required
|
||||
* for wake (but no real interrupt requested), mask the
|
||||
* interrupt (as would mtk_eint_resume do anyway later
|
||||
* in the resume sequence).
|
||||
*/
|
||||
if (start_level != curr_level)
|
||||
writel(BIT(offset), reg -
|
||||
eint->regs->stat +
|
||||
eint->regs->soft_set);
|
||||
}
|
||||
if (eint->wake_mask[i][port] & mask &&
|
||||
!(eint->cur_mask[i][port] & mask)) {
|
||||
reg = mtk_eint_get_offset(eint, eint_num,
|
||||
eint->regs->mask_set);
|
||||
writel_relaxed(mask, reg);
|
||||
}
|
||||
|
||||
if (index < eint->hw->db_cnt)
|
||||
mtk_eint_debounce_process(eint, index);
|
||||
dual_edge = eint->pins[eint_num].dual_edge;
|
||||
if (dual_edge) {
|
||||
/*
|
||||
* Clear soft-irq in case we raised it last
|
||||
* time.
|
||||
*/
|
||||
reg = mtk_eint_get_offset(eint, eint_num,
|
||||
eint->regs->soft_clr);
|
||||
writel(mask, reg);
|
||||
|
||||
start_level =
|
||||
eint->gpio_xlate->get_gpio_state(eint->pctl,
|
||||
eint_num);
|
||||
}
|
||||
|
||||
generic_handle_domain_irq(eint->domain, eint_num);
|
||||
|
||||
if (dual_edge) {
|
||||
curr_level = mtk_eint_flip_edge(eint, eint_num);
|
||||
|
||||
/*
|
||||
* If level changed, we might lost one edge
|
||||
* interrupt, raised it through soft-irq.
|
||||
*/
|
||||
if (start_level != curr_level) {
|
||||
reg = mtk_eint_get_offset(eint, eint_num,
|
||||
eint->regs->soft_set);
|
||||
writel(mask, reg);
|
||||
}
|
||||
}
|
||||
|
||||
if (eint->pins[eint_num].debounce)
|
||||
mtk_eint_debounce_process(eint, eint_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
chained_irq_exit(chip, desc);
|
||||
@@ -423,6 +441,8 @@ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
|
||||
int virq, eint_offset;
|
||||
unsigned int set_offset, bit, clr_bit, clr_offset, rst, i, unmask,
|
||||
dbnc;
|
||||
unsigned int inst = eint->pins[eint_num].instance;
|
||||
unsigned int idx = eint->pins[eint_num].index;
|
||||
struct irq_data *d;
|
||||
|
||||
if (!eint->hw->db_time)
|
||||
@@ -432,8 +452,8 @@ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
|
||||
eint_offset = (eint_num % 4) * 8;
|
||||
d = irq_get_irq_data(virq);
|
||||
|
||||
set_offset = (eint_num / 4) * 4 + eint->regs->dbnc_set;
|
||||
clr_offset = (eint_num / 4) * 4 + eint->regs->dbnc_clr;
|
||||
set_offset = (idx / 4) * 4 + eint->regs->dbnc_set;
|
||||
clr_offset = (idx / 4) * 4 + eint->regs->dbnc_clr;
|
||||
|
||||
if (!mtk_eint_can_en_debounce(eint, eint_num))
|
||||
return -EINVAL;
|
||||
@@ -454,12 +474,12 @@ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,
|
||||
}
|
||||
|
||||
clr_bit = 0xff << eint_offset;
|
||||
writel(clr_bit, eint->base + clr_offset);
|
||||
writel(clr_bit, eint->base[inst] + clr_offset);
|
||||
|
||||
bit = ((dbnc << MTK_EINT_DBNC_SET_DBNC_BITS) | MTK_EINT_DBNC_SET_EN) <<
|
||||
eint_offset;
|
||||
rst = MTK_EINT_DBNC_RST_BIT << eint_offset;
|
||||
writel(rst | bit, eint->base + set_offset);
|
||||
writel(rst | bit, eint->base[inst] + set_offset);
|
||||
|
||||
/*
|
||||
* Delay a while (more than 2T) to wait for hw debounce counter reset
|
||||
@@ -487,32 +507,69 @@ EXPORT_SYMBOL_GPL(mtk_eint_find_irq);
|
||||
|
||||
int mtk_eint_do_init(struct mtk_eint *eint)
|
||||
{
|
||||
int i;
|
||||
unsigned int size, i, port, inst = 0;
|
||||
struct mtk_pinctrl *hw = (struct mtk_pinctrl *)eint->pctl;
|
||||
|
||||
/* If clients don't assign a specific regs, let's use generic one */
|
||||
if (!eint->regs)
|
||||
eint->regs = &mtk_generic_eint_regs;
|
||||
|
||||
eint->wake_mask = devm_kcalloc(eint->dev, eint->hw->ports,
|
||||
sizeof(*eint->wake_mask), GFP_KERNEL);
|
||||
eint->base_pin_num = devm_kmalloc_array(eint->dev, eint->nbase, sizeof(u16),
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!eint->base_pin_num)
|
||||
return -ENOMEM;
|
||||
|
||||
if (eint->nbase == 1) {
|
||||
size = eint->hw->ap_num * sizeof(struct mtk_eint_pin);
|
||||
eint->pins = devm_kmalloc(eint->dev, size, GFP_KERNEL);
|
||||
if (!eint->pins)
|
||||
goto err_pins;
|
||||
|
||||
eint->base_pin_num[inst] = eint->hw->ap_num;
|
||||
for (i = 0; i < eint->hw->ap_num; i++) {
|
||||
eint->pins[i].instance = inst;
|
||||
eint->pins[i].index = i;
|
||||
eint->pins[i].debounce = (i < eint->hw->db_cnt) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (hw && hw->soc && hw->soc->eint_pin) {
|
||||
eint->pins = hw->soc->eint_pin;
|
||||
for (i = 0; i < eint->hw->ap_num; i++) {
|
||||
inst = eint->pins[i].instance;
|
||||
if (inst >= eint->nbase)
|
||||
continue;
|
||||
eint->base_pin_num[inst]++;
|
||||
}
|
||||
}
|
||||
|
||||
eint->pin_list = devm_kmalloc(eint->dev, eint->nbase * sizeof(u16 *), GFP_KERNEL);
|
||||
if (!eint->pin_list)
|
||||
goto err_pin_list;
|
||||
|
||||
eint->wake_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL);
|
||||
if (!eint->wake_mask)
|
||||
return -ENOMEM;
|
||||
goto err_wake_mask;
|
||||
|
||||
eint->cur_mask = devm_kcalloc(eint->dev, eint->hw->ports,
|
||||
sizeof(*eint->cur_mask), GFP_KERNEL);
|
||||
eint->cur_mask = devm_kmalloc(eint->dev, eint->nbase * sizeof(u32 *), GFP_KERNEL);
|
||||
if (!eint->cur_mask)
|
||||
return -ENOMEM;
|
||||
goto err_cur_mask;
|
||||
|
||||
eint->dual_edge = devm_kcalloc(eint->dev, eint->hw->ap_num,
|
||||
sizeof(int), GFP_KERNEL);
|
||||
if (!eint->dual_edge)
|
||||
return -ENOMEM;
|
||||
for (i = 0; i < eint->nbase; i++) {
|
||||
eint->pin_list[i] = devm_kzalloc(eint->dev, eint->base_pin_num[i] * sizeof(u16),
|
||||
GFP_KERNEL);
|
||||
port = DIV_ROUND_UP(eint->base_pin_num[i], 32);
|
||||
eint->wake_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL);
|
||||
eint->cur_mask[i] = devm_kzalloc(eint->dev, port * sizeof(u32), GFP_KERNEL);
|
||||
if (!eint->pin_list[i] || !eint->wake_mask[i] || !eint->cur_mask[i])
|
||||
goto err_eint;
|
||||
}
|
||||
|
||||
eint->domain = irq_domain_add_linear(eint->dev->of_node,
|
||||
eint->hw->ap_num,
|
||||
&irq_domain_simple_ops, NULL);
|
||||
if (!eint->domain)
|
||||
return -ENOMEM;
|
||||
goto err_eint;
|
||||
|
||||
if (eint->hw->db_time) {
|
||||
for (i = 0; i < MTK_EINT_DBNC_MAX; i++)
|
||||
@@ -523,8 +580,11 @@ int mtk_eint_do_init(struct mtk_eint *eint)
|
||||
|
||||
mtk_eint_hw_init(eint);
|
||||
for (i = 0; i < eint->hw->ap_num; i++) {
|
||||
inst = eint->pins[i].instance;
|
||||
if (inst >= eint->nbase)
|
||||
continue;
|
||||
eint->pin_list[inst][eint->pins[i].index] = i;
|
||||
int virq = irq_create_mapping(eint->domain, i);
|
||||
|
||||
irq_set_chip_and_handler(virq, &mtk_eint_irq_chip,
|
||||
handle_level_irq);
|
||||
irq_set_chip_data(virq, eint);
|
||||
@@ -534,6 +594,27 @@ int mtk_eint_do_init(struct mtk_eint *eint)
|
||||
eint);
|
||||
|
||||
return 0;
|
||||
|
||||
err_eint:
|
||||
for (i = 0; i < eint->nbase; i++) {
|
||||
if (eint->cur_mask[i])
|
||||
devm_kfree(eint->dev, eint->cur_mask[i]);
|
||||
if (eint->wake_mask[i])
|
||||
devm_kfree(eint->dev, eint->wake_mask[i]);
|
||||
if (eint->pin_list[i])
|
||||
devm_kfree(eint->dev, eint->pin_list[i]);
|
||||
}
|
||||
devm_kfree(eint->dev, eint->cur_mask);
|
||||
err_cur_mask:
|
||||
devm_kfree(eint->dev, eint->wake_mask);
|
||||
err_wake_mask:
|
||||
devm_kfree(eint->dev, eint->pin_list);
|
||||
err_pin_list:
|
||||
if (eint->nbase == 1)
|
||||
devm_kfree(eint->dev, eint->pins);
|
||||
err_pins:
|
||||
devm_kfree(eint->dev, eint->base_pin_num);
|
||||
return -ENOMEM;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtk_eint_do_init);
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2014-2018 MediaTek Inc.
|
||||
* Copyright (C) 2014-2025 MediaTek Inc.
|
||||
*
|
||||
* Author: Maoguang Meng <maoguang.meng@mediatek.com>
|
||||
* Sean Wang <sean.wang@mediatek.com>
|
||||
*
|
||||
* Hao Chang <ot_chhao.chang@mediatek.com>
|
||||
* Qingliang Li <qingliang.li@mediatek.com>
|
||||
*/
|
||||
#ifndef __MTK_EINT_H
|
||||
#define __MTK_EINT_H
|
||||
@@ -40,6 +41,14 @@ struct mtk_eint_hw {
|
||||
const unsigned int *db_time;
|
||||
};
|
||||
|
||||
struct mtk_eint_pin {
|
||||
u16 number;
|
||||
u8 instance;
|
||||
u8 index;
|
||||
bool debounce;
|
||||
bool dual_edge;
|
||||
};
|
||||
|
||||
extern const unsigned int debounce_time_mt2701[];
|
||||
extern const unsigned int debounce_time_mt6765[];
|
||||
extern const unsigned int debounce_time_mt6795[];
|
||||
@@ -56,17 +65,21 @@ struct mtk_eint_xt {
|
||||
|
||||
struct mtk_eint {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
void __iomem **base;
|
||||
u8 nbase;
|
||||
u16 *base_pin_num;
|
||||
struct irq_domain *domain;
|
||||
int irq;
|
||||
|
||||
int *dual_edge;
|
||||
u32 *wake_mask;
|
||||
u32 *cur_mask;
|
||||
u16 **pin_list;
|
||||
u32 **wake_mask;
|
||||
u32 **cur_mask;
|
||||
|
||||
/* Used to fit into various EINT device */
|
||||
const struct mtk_eint_hw *hw;
|
||||
const struct mtk_eint_regs *regs;
|
||||
struct mtk_eint_pin *pins;
|
||||
u16 num_db_time;
|
||||
|
||||
/* Used to fit into various pinctrl device */
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
||||
#include "mtk-eint.h"
|
||||
@@ -367,7 +368,7 @@ static const struct mtk_eint_xt mtk_eint_xt = {
|
||||
int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
int ret;
|
||||
int ret, i, j, count_reg_names;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_EINT_MTK))
|
||||
return 0;
|
||||
@@ -379,10 +380,24 @@ int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
|
||||
if (!hw->eint)
|
||||
return -ENOMEM;
|
||||
|
||||
hw->eint->base = devm_platform_ioremap_resource_byname(pdev, "eint");
|
||||
if (IS_ERR(hw->eint->base)) {
|
||||
ret = PTR_ERR(hw->eint->base);
|
||||
goto err_free_eint;
|
||||
count_reg_names = of_property_count_strings(np, "reg-names");
|
||||
if (count_reg_names < hw->soc->nbase_names)
|
||||
return -EINVAL;
|
||||
|
||||
hw->eint->nbase = count_reg_names - hw->soc->nbase_names;
|
||||
hw->eint->base = devm_kmalloc_array(&pdev->dev, hw->eint->nbase,
|
||||
sizeof(*hw->eint->base), GFP_KERNEL | __GFP_ZERO);
|
||||
if (!hw->eint->base) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_base;
|
||||
}
|
||||
|
||||
for (i = hw->soc->nbase_names, j = 0; i < count_reg_names; i++, j++) {
|
||||
hw->eint->base[j] = of_iomap(np, i);
|
||||
if (IS_ERR(hw->eint->base[j])) {
|
||||
ret = PTR_ERR(hw->eint->base[j]);
|
||||
goto err_free_eint;
|
||||
}
|
||||
}
|
||||
|
||||
hw->eint->irq = irq_of_parse_and_map(np, 0);
|
||||
@@ -401,9 +416,19 @@ int mtk_build_eint(struct mtk_pinctrl *hw, struct platform_device *pdev)
|
||||
hw->eint->pctl = hw;
|
||||
hw->eint->gpio_xlate = &mtk_eint_xt;
|
||||
|
||||
return mtk_eint_do_init(hw->eint);
|
||||
ret = mtk_eint_do_init(hw->eint);
|
||||
if (ret)
|
||||
goto err_free_eint;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_eint:
|
||||
for (j = 0; j < hw->eint->nbase; j++) {
|
||||
if (hw->eint->base[j])
|
||||
iounmap(hw->eint->base[j]);
|
||||
}
|
||||
devm_kfree(hw->dev, hw->eint->base);
|
||||
err_free_base:
|
||||
devm_kfree(hw->dev, hw->eint);
|
||||
hw->eint = NULL;
|
||||
return ret;
|
||||
|
||||
@@ -242,6 +242,7 @@ struct mtk_pin_soc {
|
||||
unsigned int nfuncs;
|
||||
const struct mtk_eint_regs *eint_regs;
|
||||
const struct mtk_eint_hw *eint_hw;
|
||||
struct mtk_eint_pin *eint_pin;
|
||||
|
||||
/* Specific parameters per SoC */
|
||||
u8 gpio_m;
|
||||
|
||||
@@ -49,6 +49,13 @@
|
||||
__VA_ARGS__, { } }, \
|
||||
}
|
||||
|
||||
#define MTK_EINT_PIN(_number, _instance, _index, _debounce) { \
|
||||
.number = _number, \
|
||||
.instance = _instance, \
|
||||
.index = _index, \
|
||||
.debounce = _debounce, \
|
||||
}
|
||||
|
||||
#define PINCTRL_PIN_GROUP(_name_, id) \
|
||||
{ \
|
||||
.grp = PINCTRL_PINGROUP(_name_,id##_pins, ARRAY_SIZE(id##_pins)), \
|
||||
|
||||
@@ -67,6 +67,17 @@ config PINCTRL_MESON_S4
|
||||
select PINCTRL_MESON_AXG_PMX
|
||||
default y
|
||||
|
||||
config PINCTRL_AMLOGIC_A4
|
||||
bool "AMLOGIC pincontrol"
|
||||
depends on ARM64
|
||||
default y
|
||||
help
|
||||
This is the driver for the pin controller found on Amlogic SoCs.
|
||||
|
||||
This driver is simplify subsequent support for new amlogic SoCs,
|
||||
to support new Amlogic SoCs, only need to add the corresponding dts file,
|
||||
no additional binding header files or C file are added.
|
||||
|
||||
config PINCTRL_AMLOGIC_C3
|
||||
tristate "Amlogic C3 SoC pinctrl driver"
|
||||
depends on ARM64
|
||||
|
||||
@@ -10,5 +10,6 @@ obj-$(CONFIG_PINCTRL_MESON_AXG) += pinctrl-meson-axg.o
|
||||
obj-$(CONFIG_PINCTRL_MESON_G12A) += pinctrl-meson-g12a.o
|
||||
obj-$(CONFIG_PINCTRL_MESON_A1) += pinctrl-meson-a1.o
|
||||
obj-$(CONFIG_PINCTRL_MESON_S4) += pinctrl-meson-s4.o
|
||||
obj-$(CONFIG_PINCTRL_AMLOGIC_A4) += pinctrl-amlogic-a4.o
|
||||
obj-$(CONFIG_PINCTRL_AMLOGIC_C3) += pinctrl-amlogic-c3.o
|
||||
obj-$(CONFIG_PINCTRL_AMLOGIC_T7) += pinctrl-amlogic-t7.o
|
||||
|
||||
1053
drivers/pinctrl/meson/pinctrl-amlogic-a4.c
Normal file
1053
drivers/pinctrl/meson/pinctrl-amlogic-a4.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -98,12 +98,6 @@ static const u32 ds_3300mv_tbl[] = {
|
||||
17100, 25600, 34100, 42800, 48000, 56000, 77000, 82000,
|
||||
};
|
||||
|
||||
struct ma35_pin_func {
|
||||
const char *name;
|
||||
const char **groups;
|
||||
u32 ngroups;
|
||||
};
|
||||
|
||||
struct ma35_pin_setting {
|
||||
u32 offset;
|
||||
u32 shift;
|
||||
@@ -112,13 +106,6 @@ struct ma35_pin_setting {
|
||||
unsigned int nconfigs;
|
||||
};
|
||||
|
||||
struct ma35_pin_group {
|
||||
const char *name;
|
||||
unsigned int npins;
|
||||
unsigned int *pins;
|
||||
struct ma35_pin_setting *settings;
|
||||
};
|
||||
|
||||
struct ma35_pin_bank {
|
||||
void __iomem *reg_base;
|
||||
struct clk *clk;
|
||||
@@ -147,9 +134,9 @@ struct ma35_pinctrl {
|
||||
struct pinctrl_dev *pctl;
|
||||
const struct ma35_pinctrl_soc_info *info;
|
||||
struct regmap *regmap;
|
||||
struct ma35_pin_group *groups;
|
||||
struct group_desc *groups;
|
||||
unsigned int ngroups;
|
||||
struct ma35_pin_func *functions;
|
||||
struct pinfunction *functions;
|
||||
unsigned int nfunctions;
|
||||
};
|
||||
|
||||
@@ -166,7 +153,7 @@ static const char *ma35_get_group_name(struct pinctrl_dev *pctldev, unsigned int
|
||||
{
|
||||
struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return npctl->groups[selector].name;
|
||||
return npctl->groups[selector].grp.name;
|
||||
}
|
||||
|
||||
static int ma35_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
|
||||
@@ -177,19 +164,19 @@ static int ma35_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selecto
|
||||
if (selector >= npctl->ngroups)
|
||||
return -EINVAL;
|
||||
|
||||
*pins = npctl->groups[selector].pins;
|
||||
*npins = npctl->groups[selector].npins;
|
||||
*pins = npctl->groups[selector].grp.pins;
|
||||
*npins = npctl->groups[selector].grp.npins;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ma35_pin_group *ma35_pinctrl_find_group_by_name(
|
||||
const struct ma35_pinctrl *npctl, const char *name)
|
||||
static struct group_desc *
|
||||
ma35_pinctrl_find_group_by_name(const struct ma35_pinctrl *npctl, const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < npctl->ngroups; i++) {
|
||||
if (!strcmp(npctl->groups[i].name, name))
|
||||
if (!strcmp(npctl->groups[i].grp.name, name))
|
||||
return &npctl->groups[i];
|
||||
}
|
||||
return NULL;
|
||||
@@ -201,9 +188,10 @@ static int ma35_pinctrl_dt_node_to_map_func(struct pinctrl_dev *pctldev,
|
||||
unsigned int *num_maps)
|
||||
{
|
||||
struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct ma35_pin_group *grp;
|
||||
struct ma35_pin_setting *setting;
|
||||
struct pinctrl_map *new_map;
|
||||
struct device_node *parent;
|
||||
struct group_desc *grp;
|
||||
int map_num = 1;
|
||||
int i;
|
||||
|
||||
@@ -217,7 +205,7 @@ static int ma35_pinctrl_dt_node_to_map_func(struct pinctrl_dev *pctldev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
map_num += grp->npins;
|
||||
map_num += grp->grp.npins;
|
||||
new_map = kcalloc(map_num, sizeof(*new_map), GFP_KERNEL);
|
||||
if (!new_map)
|
||||
return -ENOMEM;
|
||||
@@ -229,17 +217,19 @@ static int ma35_pinctrl_dt_node_to_map_func(struct pinctrl_dev *pctldev,
|
||||
if (!parent)
|
||||
return -EINVAL;
|
||||
|
||||
setting = grp->data;
|
||||
|
||||
new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
new_map[0].data.mux.function = parent->name;
|
||||
new_map[0].data.mux.group = np->name;
|
||||
of_node_put(parent);
|
||||
|
||||
new_map++;
|
||||
for (i = 0; i < grp->npins; i++) {
|
||||
for (i = 0; i < grp->grp.npins; i++) {
|
||||
new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN;
|
||||
new_map[i].data.configs.group_or_pin = pin_get_name(pctldev, grp->pins[i]);
|
||||
new_map[i].data.configs.configs = grp->settings[i].configs;
|
||||
new_map[i].data.configs.num_configs = grp->settings[i].nconfigs;
|
||||
new_map[i].data.configs.group_or_pin = pin_get_name(pctldev, grp->grp.pins[i]);
|
||||
new_map[i].data.configs.configs = setting[i].configs;
|
||||
new_map[i].data.configs.num_configs = setting[i].nconfigs;
|
||||
}
|
||||
dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n",
|
||||
(*map)->data.mux.function, (*map)->data.mux.group, map_num);
|
||||
@@ -287,14 +277,14 @@ static int ma35_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int selecto
|
||||
unsigned int group)
|
||||
{
|
||||
struct ma35_pinctrl *npctl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct ma35_pin_group *grp = &npctl->groups[group];
|
||||
struct ma35_pin_setting *setting = grp->settings;
|
||||
struct group_desc *grp = &npctl->groups[group];
|
||||
struct ma35_pin_setting *setting = grp->data;
|
||||
u32 i, regval;
|
||||
|
||||
dev_dbg(npctl->dev, "enable function %s group %s\n",
|
||||
npctl->functions[selector].name, npctl->groups[group].name);
|
||||
npctl->functions[selector].name, grp->grp.name);
|
||||
|
||||
for (i = 0; i < grp->npins; i++) {
|
||||
for (i = 0; i < grp->grp.npins; i++) {
|
||||
regmap_read(npctl->regmap, setting->offset, ®val);
|
||||
regval &= ~GENMASK(setting->shift + MA35_MFP_BITS_PER_PORT - 1,
|
||||
setting->shift);
|
||||
@@ -529,7 +519,6 @@ static int ma35_gpiolib_register(struct platform_device *pdev, struct ma35_pinct
|
||||
bank->irqtype = 0;
|
||||
bank->irqinten = 0;
|
||||
bank->chip.label = bank->name;
|
||||
bank->chip.of_gpio_n_cells = 2;
|
||||
bank->chip.parent = &pdev->dev;
|
||||
bank->chip.request = ma35_gpio_core_to_request;
|
||||
bank->chip.direction_input = ma35_gpio_core_direction_in;
|
||||
@@ -986,22 +975,22 @@ static const struct pinconf_ops ma35_pinconf_ops = {
|
||||
.is_generic = true,
|
||||
};
|
||||
|
||||
static int ma35_pinctrl_parse_groups(struct device_node *np, struct ma35_pin_group *grp,
|
||||
static int ma35_pinctrl_parse_groups(struct fwnode_handle *fwnode, struct group_desc *grp,
|
||||
struct ma35_pinctrl *npctl, u32 index)
|
||||
{
|
||||
struct device_node *np = to_of_node(fwnode);
|
||||
struct ma35_pin_setting *pin;
|
||||
unsigned long *configs;
|
||||
unsigned int nconfigs;
|
||||
unsigned int *pins;
|
||||
int i, j, count, ret;
|
||||
u32 *elems;
|
||||
|
||||
grp->name = np->name;
|
||||
|
||||
ret = pinconf_generic_parse_dt_config(np, NULL, &configs, &nconfigs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
count = of_property_count_elems_of_size(np, "nuvoton,pins", sizeof(u32));
|
||||
count = fwnode_property_count_u32(fwnode, "nuvoton,pins");
|
||||
if (!count || count % 3)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1009,21 +998,22 @@ static int ma35_pinctrl_parse_groups(struct device_node *np, struct ma35_pin_gro
|
||||
if (!elems)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_property_read_u32_array(np, "nuvoton,pins", elems, count);
|
||||
grp->grp.name = np->name;
|
||||
|
||||
ret = fwnode_property_read_u32_array(fwnode, "nuvoton,pins", elems, count);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
grp->grp.npins = count / 3;
|
||||
|
||||
grp->npins = count / 3;
|
||||
|
||||
grp->pins = devm_kcalloc(npctl->dev, grp->npins, sizeof(*grp->pins), GFP_KERNEL);
|
||||
if (!grp->pins)
|
||||
pins = devm_kcalloc(npctl->dev, grp->grp.npins, sizeof(*pins), GFP_KERNEL);
|
||||
if (!pins)
|
||||
return -ENOMEM;
|
||||
grp->grp.pins = pins;
|
||||
|
||||
grp->settings = devm_kcalloc(npctl->dev, grp->npins, sizeof(*grp->settings), GFP_KERNEL);
|
||||
if (!grp->settings)
|
||||
pin = devm_kcalloc(npctl->dev, grp->grp.npins, sizeof(*pin), GFP_KERNEL);
|
||||
if (!pin)
|
||||
return -ENOMEM;
|
||||
|
||||
pin = grp->settings;
|
||||
grp->data = pin;
|
||||
|
||||
for (i = 0, j = 0; i < count; i += 3, j++) {
|
||||
pin->offset = elems[i] * MA35_MFP_REG_SZ_PER_BANK + MA35_MFP_REG_BASE;
|
||||
@@ -1031,19 +1021,21 @@ static int ma35_pinctrl_parse_groups(struct device_node *np, struct ma35_pin_gro
|
||||
pin->muxval = elems[i + 2];
|
||||
pin->configs = configs;
|
||||
pin->nconfigs = nconfigs;
|
||||
grp->pins[j] = npctl->info->get_pin_num(pin->offset, pin->shift);
|
||||
pins[j] = npctl->info->get_pin_num(pin->offset, pin->shift);
|
||||
pin++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ma35_pinctrl_parse_functions(struct device_node *np, struct ma35_pinctrl *npctl,
|
||||
static int ma35_pinctrl_parse_functions(struct fwnode_handle *fwnode, struct ma35_pinctrl *npctl,
|
||||
u32 index)
|
||||
{
|
||||
struct device_node *child;
|
||||
struct ma35_pin_func *func;
|
||||
struct ma35_pin_group *grp;
|
||||
struct device_node *np = to_of_node(fwnode);
|
||||
struct fwnode_handle *child;
|
||||
struct pinfunction *func;
|
||||
struct group_desc *grp;
|
||||
static u32 grp_index;
|
||||
const char **groups;
|
||||
u32 ret, i = 0;
|
||||
|
||||
dev_dbg(npctl->dev, "parse function(%d): %s\n", index, np->name);
|
||||
@@ -1055,31 +1047,34 @@ static int ma35_pinctrl_parse_functions(struct device_node *np, struct ma35_pinc
|
||||
if (func->ngroups <= 0)
|
||||
return 0;
|
||||
|
||||
func->groups = devm_kcalloc(npctl->dev, func->ngroups, sizeof(char *), GFP_KERNEL);
|
||||
if (!func->groups)
|
||||
groups = devm_kcalloc(npctl->dev, func->ngroups, sizeof(*groups), GFP_KERNEL);
|
||||
if (!groups)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
func->groups[i] = child->name;
|
||||
fwnode_for_each_child_node(fwnode, child) {
|
||||
struct device_node *node = to_of_node(child);
|
||||
|
||||
groups[i] = node->name;
|
||||
grp = &npctl->groups[grp_index++];
|
||||
ret = ma35_pinctrl_parse_groups(child, grp, npctl, i++);
|
||||
if (ret) {
|
||||
of_node_put(child);
|
||||
fwnode_handle_put(child);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
func->groups = groups;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ma35_pinctrl_probe_dt(struct platform_device *pdev, struct ma35_pinctrl *npctl)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct fwnode_handle *child;
|
||||
u32 idx = 0;
|
||||
int ret;
|
||||
|
||||
device_for_each_child_node(&pdev->dev, child) {
|
||||
if (fwnode_property_present(child, "gpio-controller"))
|
||||
continue;
|
||||
for_each_gpiochip_node(dev, child) {
|
||||
npctl->nfunctions++;
|
||||
npctl->ngroups += of_get_child_count(to_of_node(child));
|
||||
}
|
||||
@@ -1097,11 +1092,8 @@ static int ma35_pinctrl_probe_dt(struct platform_device *pdev, struct ma35_pinct
|
||||
if (!npctl->groups)
|
||||
return -ENOMEM;
|
||||
|
||||
device_for_each_child_node(&pdev->dev, child) {
|
||||
if (fwnode_property_present(child, "gpio-controller"))
|
||||
continue;
|
||||
|
||||
ret = ma35_pinctrl_parse_functions(to_of_node(child), npctl, idx++);
|
||||
for_each_gpiochip_node(dev, child) {
|
||||
ret = ma35_pinctrl_parse_functions(child, npctl, idx++);
|
||||
if (ret) {
|
||||
fwnode_handle_put(child);
|
||||
dev_err(&pdev->dev, "failed to parse function\n");
|
||||
@@ -1146,7 +1138,7 @@ int ma35_pinctrl_probe(struct platform_device *pdev, const struct ma35_pinctrl_s
|
||||
npctl->info = info;
|
||||
npctl->dev = &pdev->dev;
|
||||
|
||||
npctl->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "nuvoton,sys");
|
||||
npctl->regmap = syscon_regmap_lookup_by_phandle(dev_of_node(dev), "nuvoton,sys");
|
||||
if (IS_ERR(npctl->regmap))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(npctl->regmap),
|
||||
"No syscfg phandle specified\n");
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
|
||||
@@ -7,10 +7,8 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
@@ -504,17 +502,6 @@ static const int lkgpo2_pins[] = { 9 };
|
||||
|
||||
static const int nprd_smi_pins[] = { 190 };
|
||||
|
||||
/*
|
||||
* pin: name, number
|
||||
* group: name, npins, pins
|
||||
* function: name, ngroups, groups
|
||||
*/
|
||||
struct npcm7xx_group {
|
||||
const char *name;
|
||||
const unsigned int *pins;
|
||||
int npins;
|
||||
};
|
||||
|
||||
#define NPCM7XX_GRPS \
|
||||
NPCM7XX_GRP(smb0), \
|
||||
NPCM7XX_GRP(smb0b), \
|
||||
@@ -642,22 +629,14 @@ enum {
|
||||
#undef NPCM7XX_GRP
|
||||
};
|
||||
|
||||
static struct npcm7xx_group npcm7xx_groups[] = {
|
||||
#define NPCM7XX_GRP(x) { .name = #x, .pins = x ## _pins, \
|
||||
.npins = ARRAY_SIZE(x ## _pins) }
|
||||
static struct pingroup npcm7xx_groups[] = {
|
||||
#define NPCM7XX_GRP(x) PINCTRL_PINGROUP(#x, x ## _pins, ARRAY_SIZE(x ## _pins))
|
||||
NPCM7XX_GRPS
|
||||
#undef NPCM7XX_GRP
|
||||
};
|
||||
|
||||
#define NPCM7XX_SFUNC(a) NPCM7XX_FUNC(a, #a)
|
||||
#define NPCM7XX_FUNC(a, b...) static const char *a ## _grp[] = { b }
|
||||
#define NPCM7XX_MKFUNC(nm) { .name = #nm, .ngroups = ARRAY_SIZE(nm ## _grp), \
|
||||
.groups = nm ## _grp }
|
||||
struct npcm7xx_func {
|
||||
const char *name;
|
||||
const unsigned int ngroups;
|
||||
const char *const *groups;
|
||||
};
|
||||
|
||||
NPCM7XX_SFUNC(smb0);
|
||||
NPCM7XX_SFUNC(smb0b);
|
||||
@@ -776,7 +755,8 @@ NPCM7XX_SFUNC(lkgpo2);
|
||||
NPCM7XX_SFUNC(nprd_smi);
|
||||
|
||||
/* Function names */
|
||||
static struct npcm7xx_func npcm7xx_funcs[] = {
|
||||
static struct pinfunction npcm7xx_funcs[] = {
|
||||
#define NPCM7XX_MKFUNC(nm) PINCTRL_PINFUNCTION(#nm, nm ## _grp, ARRAY_SIZE(nm ## _grp))
|
||||
NPCM7XX_MKFUNC(smb0),
|
||||
NPCM7XX_MKFUNC(smb0b),
|
||||
NPCM7XX_MKFUNC(smb0c),
|
||||
@@ -892,6 +872,7 @@ static struct npcm7xx_func npcm7xx_funcs[] = {
|
||||
NPCM7XX_MKFUNC(lkgpo1),
|
||||
NPCM7XX_MKFUNC(lkgpo2),
|
||||
NPCM7XX_MKFUNC(nprd_smi),
|
||||
#undef NPCM7XX_MKFUNC
|
||||
};
|
||||
|
||||
#define NPCM7XX_PINCFG(a, b, c, d, e, f, g, h, i, j, k) \
|
||||
@@ -1849,22 +1830,13 @@ static struct pinctrl_desc npcm7xx_pinctrl_desc = {
|
||||
static int npcm7xx_gpio_of(struct npcm7xx_pinctrl *pctrl)
|
||||
{
|
||||
int ret = -ENXIO;
|
||||
struct resource res;
|
||||
struct device *dev = pctrl->dev;
|
||||
struct fwnode_reference_args args;
|
||||
struct fwnode_handle *child;
|
||||
int id = 0;
|
||||
|
||||
for_each_gpiochip_node(dev, child) {
|
||||
struct device_node *np = to_of_node(child);
|
||||
|
||||
ret = of_address_to_resource(np, 0, &res);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Resource fail for GPIO bank %u\n", id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pctrl->gpio_bank[id].base = ioremap(res.start, resource_size(&res));
|
||||
pctrl->gpio_bank[id].base = fwnode_iomap(child, 0);
|
||||
if (!pctrl->gpio_bank[id].base)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1886,7 +1858,7 @@ static int npcm7xx_gpio_of(struct npcm7xx_pinctrl *pctrl)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = irq_of_parse_and_map(np, 0);
|
||||
ret = fwnode_irq_get(child, 0);
|
||||
if (!ret) {
|
||||
dev_err(dev, "No IRQ for GPIO bank %u\n", id);
|
||||
return -EINVAL;
|
||||
|
||||
@@ -587,17 +587,6 @@ static const int hgpio5_pins[] = { 25 };
|
||||
static const int hgpio6_pins[] = { 59 };
|
||||
static const int hgpio7_pins[] = { 60 };
|
||||
|
||||
/*
|
||||
* pin: name, number
|
||||
* group: name, npins, pins
|
||||
* function: name, ngroups, groups
|
||||
*/
|
||||
struct npcm8xx_pingroup {
|
||||
const char *name;
|
||||
const unsigned int *pins;
|
||||
int npins;
|
||||
};
|
||||
|
||||
#define NPCM8XX_GRPS \
|
||||
NPCM8XX_GRP(gpi36), \
|
||||
NPCM8XX_GRP(gpi35), \
|
||||
@@ -829,22 +818,14 @@ enum {
|
||||
#undef NPCM8XX_GRP
|
||||
};
|
||||
|
||||
static struct npcm8xx_pingroup npcm8xx_pingroups[] = {
|
||||
#define NPCM8XX_GRP(x) { .name = #x, .pins = x ## _pins, \
|
||||
.npins = ARRAY_SIZE(x ## _pins) }
|
||||
static struct pingroup npcm8xx_pingroups[] = {
|
||||
#define NPCM8XX_GRP(x) PINCTRL_PINGROUP(#x, x ## _pins, ARRAY_SIZE(x ## _pins))
|
||||
NPCM8XX_GRPS
|
||||
#undef NPCM8XX_GRP
|
||||
};
|
||||
|
||||
#define NPCM8XX_SFUNC(a) NPCM8XX_FUNC(a, #a)
|
||||
#define NPCM8XX_FUNC(a, b...) static const char *a ## _grp[] = { b }
|
||||
#define NPCM8XX_MKFUNC(nm) { .name = #nm, .ngroups = ARRAY_SIZE(nm ## _grp), \
|
||||
.groups = nm ## _grp }
|
||||
struct npcm8xx_func {
|
||||
const char *name;
|
||||
const unsigned int ngroups;
|
||||
const char *const *groups;
|
||||
};
|
||||
|
||||
NPCM8XX_SFUNC(gpi36);
|
||||
NPCM8XX_SFUNC(gpi35);
|
||||
@@ -1067,7 +1048,8 @@ NPCM8XX_SFUNC(hgpio6);
|
||||
NPCM8XX_SFUNC(hgpio7);
|
||||
|
||||
/* Function names */
|
||||
static struct npcm8xx_func npcm8xx_funcs[] = {
|
||||
static struct pinfunction npcm8xx_funcs[] = {
|
||||
#define NPCM8XX_MKFUNC(nm) PINCTRL_PINFUNCTION(#nm, nm ## _grp, ARRAY_SIZE(nm ## _grp))
|
||||
NPCM8XX_MKFUNC(gpi36),
|
||||
NPCM8XX_MKFUNC(gpi35),
|
||||
NPCM8XX_MKFUNC(tp_jtag3),
|
||||
@@ -1287,15 +1269,18 @@ static struct npcm8xx_func npcm8xx_funcs[] = {
|
||||
NPCM8XX_MKFUNC(hgpio5),
|
||||
NPCM8XX_MKFUNC(hgpio6),
|
||||
NPCM8XX_MKFUNC(hgpio7),
|
||||
#undef NPCM8XX_MKFUNC
|
||||
};
|
||||
|
||||
#define NPCM8XX_PINCFG(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) \
|
||||
[a] { .fn0 = fn_ ## b, .reg0 = NPCM8XX_GCR_ ## c, .bit0 = d, \
|
||||
[a] = { \
|
||||
.flag = q, \
|
||||
.fn0 = fn_ ## b, .reg0 = NPCM8XX_GCR_ ## c, .bit0 = d, \
|
||||
.fn1 = fn_ ## e, .reg1 = NPCM8XX_GCR_ ## f, .bit1 = g, \
|
||||
.fn2 = fn_ ## h, .reg2 = NPCM8XX_GCR_ ## i, .bit2 = j, \
|
||||
.fn3 = fn_ ## k, .reg3 = NPCM8XX_GCR_ ## l, .bit3 = m, \
|
||||
.fn4 = fn_ ## n, .reg4 = NPCM8XX_GCR_ ## o, .bit4 = p, \
|
||||
.flag = q }
|
||||
}
|
||||
|
||||
/* Drive strength controlled by NPCM8XX_GP_N_ODSC */
|
||||
#define DRIVE_STRENGTH_LO_SHIFT 8
|
||||
@@ -2361,8 +2346,8 @@ static int npcm8xx_gpio_fw(struct npcm8xx_pinctrl *pctrl)
|
||||
return dev_err_probe(dev, ret, "gpio-ranges fail for GPIO bank %u\n", id);
|
||||
|
||||
ret = fwnode_irq_get(child, 0);
|
||||
if (!ret)
|
||||
return dev_err_probe(dev, ret, "No IRQ for GPIO bank %u\n", id);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Failed to retrieve IRQ for bank %u\n", id);
|
||||
|
||||
pctrl->gpio_bank[id].irq = ret;
|
||||
pctrl->gpio_bank[id].irq_chip = npcmgpio_irqchip;
|
||||
@@ -2439,7 +2424,7 @@ static int npcm8xx_pinctrl_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, pctrl);
|
||||
|
||||
pctrl->gcr_regmap =
|
||||
syscon_regmap_lookup_by_phandle(dev->of_node, "nuvoton,sysgcr");
|
||||
syscon_regmap_lookup_by_phandle(dev_of_node(dev), "nuvoton,sysgcr");
|
||||
if (IS_ERR(pctrl->gcr_regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(pctrl->gcr_regmap),
|
||||
"Failed to find nuvoton,sysgcr property\n");
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
// block, shared between all GPIO banks
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/fwnode.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
@@ -18,6 +17,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
@@ -482,13 +482,6 @@ static const struct pingroup wpcm450_groups[] = {
|
||||
|
||||
#define WPCM450_SFUNC(a) WPCM450_FUNC(a, #a)
|
||||
#define WPCM450_FUNC(a, b...) static const char *a ## _grp[] = { b }
|
||||
#define WPCM450_MKFUNC(nm) { .name = #nm, .ngroups = ARRAY_SIZE(nm ## _grp), \
|
||||
.groups = nm ## _grp }
|
||||
struct wpcm450_func {
|
||||
const char *name;
|
||||
const unsigned int ngroups;
|
||||
const char *const *groups;
|
||||
};
|
||||
|
||||
WPCM450_SFUNC(smb3);
|
||||
WPCM450_SFUNC(smb4);
|
||||
@@ -555,7 +548,8 @@ WPCM450_FUNC(gpio, WPCM450_GRPS);
|
||||
#undef WPCM450_GRP
|
||||
|
||||
/* Function names */
|
||||
static struct wpcm450_func wpcm450_funcs[] = {
|
||||
static struct pinfunction wpcm450_funcs[] = {
|
||||
#define WPCM450_MKFUNC(nm) PINCTRL_PINFUNCTION(#nm, nm ## _grp, ARRAY_SIZE(nm ## _grp))
|
||||
WPCM450_MKFUNC(smb3),
|
||||
WPCM450_MKFUNC(smb4),
|
||||
WPCM450_MKFUNC(smb5),
|
||||
@@ -616,6 +610,7 @@ static struct wpcm450_func wpcm450_funcs[] = {
|
||||
WPCM450_MKFUNC(hg6),
|
||||
WPCM450_MKFUNC(hg7),
|
||||
WPCM450_MKFUNC(gpio),
|
||||
#undef WPCM450_MKFUNC
|
||||
};
|
||||
|
||||
#define WPCM450_PINCFG(a, b, c, d, e, f, g) \
|
||||
@@ -1033,7 +1028,7 @@ static int wpcm450_gpio_register(struct platform_device *pdev,
|
||||
return dev_err_probe(dev, PTR_ERR(pctrl->gpio_base),
|
||||
"Resource fail for GPIO controller\n");
|
||||
|
||||
device_for_each_child_node(dev, child) {
|
||||
for_each_gpiochip_node(dev, child) {
|
||||
void __iomem *dat = NULL;
|
||||
void __iomem *set = NULL;
|
||||
void __iomem *dirout = NULL;
|
||||
@@ -1044,9 +1039,6 @@ static int wpcm450_gpio_register(struct platform_device *pdev,
|
||||
u32 reg;
|
||||
int i;
|
||||
|
||||
if (!fwnode_property_read_bool(child, "gpio-controller"))
|
||||
continue;
|
||||
|
||||
ret = fwnode_property_read_u32(child, "reg", ®);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -233,6 +233,67 @@ static void parse_dt_cfg(struct device_node *np,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pinconf_generic_parse_dt_pinmux()
|
||||
* parse the pinmux properties into generic pin mux values.
|
||||
* @np: node containing the pinmux properties
|
||||
* @dev: pincontrol core device
|
||||
* @pid: array with pin identity entries
|
||||
* @pmux: array with pin mux value entries
|
||||
* @npins: number of pins
|
||||
*
|
||||
* pinmux propertity: mux value [0,7]bits and pin identity [8,31]bits.
|
||||
*/
|
||||
int pinconf_generic_parse_dt_pinmux(struct device_node *np, struct device *dev,
|
||||
unsigned int **pid, unsigned int **pmux,
|
||||
unsigned int *npins)
|
||||
{
|
||||
unsigned int *pid_t;
|
||||
unsigned int *pmux_t;
|
||||
struct property *prop;
|
||||
unsigned int npins_t, i;
|
||||
u32 value;
|
||||
int ret;
|
||||
|
||||
prop = of_find_property(np, "pinmux", NULL);
|
||||
if (!prop) {
|
||||
dev_info(dev, "Missing pinmux property\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!pid || !pmux || !npins) {
|
||||
dev_err(dev, "parameters error\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
npins_t = prop->length / sizeof(u32);
|
||||
pid_t = devm_kcalloc(dev, npins_t, sizeof(*pid_t), GFP_KERNEL);
|
||||
pmux_t = devm_kcalloc(dev, npins_t, sizeof(*pmux_t), GFP_KERNEL);
|
||||
if (!pid_t || !pmux_t) {
|
||||
dev_err(dev, "kalloc memory fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (i = 0; i < npins_t; i++) {
|
||||
ret = of_property_read_u32_index(np, "pinmux", i, &value);
|
||||
if (ret) {
|
||||
dev_err(dev, "get pinmux value fail\n");
|
||||
goto exit;
|
||||
}
|
||||
pmux_t[i] = value & 0xff;
|
||||
pid_t[i] = (value >> 8) & 0xffffff;
|
||||
}
|
||||
*pid = pid_t;
|
||||
*pmux = pmux_t;
|
||||
*npins = npins_t;
|
||||
|
||||
return 0;
|
||||
exit:
|
||||
devm_kfree(dev, pid_t);
|
||||
devm_kfree(dev, pmux_t);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinconf_generic_parse_dt_pinmux);
|
||||
|
||||
/**
|
||||
* pinconf_generic_parse_dt_config()
|
||||
* parse the config properties into generic pinconfig values.
|
||||
@@ -295,6 +356,75 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinconf_generic_parse_dt_config);
|
||||
|
||||
int pinconf_generic_dt_node_to_map_pinmux(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map,
|
||||
unsigned int *num_maps)
|
||||
{
|
||||
struct device *dev = pctldev->dev;
|
||||
struct device_node *pnode;
|
||||
unsigned long *configs = NULL;
|
||||
unsigned int num_configs = 0;
|
||||
struct property *prop;
|
||||
unsigned int reserved_maps;
|
||||
int reserve;
|
||||
int ret;
|
||||
|
||||
prop = of_find_property(np, "pinmux", NULL);
|
||||
if (!prop) {
|
||||
dev_info(dev, "Missing pinmux property\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
pnode = of_get_parent(np);
|
||||
if (!pnode) {
|
||||
dev_info(dev, "Missing function node\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
reserved_maps = 0;
|
||||
*map = NULL;
|
||||
*num_maps = 0;
|
||||
|
||||
ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
|
||||
&num_configs);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%pOF: could not parse node property\n", np);
|
||||
return ret;
|
||||
}
|
||||
|
||||
reserve = 1;
|
||||
if (num_configs)
|
||||
reserve++;
|
||||
|
||||
ret = pinctrl_utils_reserve_map(pctldev, map, &reserved_maps,
|
||||
num_maps, reserve);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
|
||||
ret = pinctrl_utils_add_map_mux(pctldev, map,
|
||||
&reserved_maps, num_maps, np->name,
|
||||
pnode->name);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
|
||||
if (num_configs) {
|
||||
ret = pinctrl_utils_add_map_configs(pctldev, map, &reserved_maps,
|
||||
num_maps, np->name, configs,
|
||||
num_configs, PIN_MAP_TYPE_CONFIGS_GROUP);
|
||||
if (ret < 0)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
kfree(configs);
|
||||
if (ret)
|
||||
pinctrl_utils_free_map(pctldev, *map, *num_maps);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pinconf_generic_dt_node_to_map_pinmux);
|
||||
|
||||
int pinconf_generic_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np, struct pinctrl_map **map,
|
||||
unsigned int *reserved_maps, unsigned int *num_maps,
|
||||
|
||||
@@ -138,4 +138,8 @@ int pinconf_generic_parse_dt_config(struct device_node *np,
|
||||
struct pinctrl_dev *pctldev,
|
||||
unsigned long **configs,
|
||||
unsigned int *nconfigs);
|
||||
|
||||
int pinconf_generic_parse_dt_pinmux(struct device_node *np, struct device *dev,
|
||||
unsigned int **pid, unsigned int **pmux,
|
||||
unsigned int *npins);
|
||||
#endif
|
||||
|
||||
231
drivers/pinctrl/pinctrl-amdisp.c
Normal file
231
drivers/pinctrl/pinctrl-amdisp.c
Normal file
@@ -0,0 +1,231 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* AMD ISP Pinctrl Driver
|
||||
*
|
||||
* Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "pinctrl-amdisp.h"
|
||||
|
||||
#define DRV_NAME "amdisp-pinctrl"
|
||||
#define GPIO_CONTROL_PIN 4
|
||||
#define GPIO_OFFSET_0 0x0
|
||||
#define GPIO_OFFSET_1 0x4
|
||||
#define GPIO_OFFSET_2 0x50
|
||||
|
||||
static const u32 gpio_offset[] = {
|
||||
GPIO_OFFSET_0,
|
||||
GPIO_OFFSET_1,
|
||||
GPIO_OFFSET_2
|
||||
};
|
||||
|
||||
struct amdisp_pinctrl_data {
|
||||
const struct pinctrl_pin_desc *pins;
|
||||
unsigned int npins;
|
||||
const struct amdisp_function *functions;
|
||||
unsigned int nfunctions;
|
||||
const struct amdisp_pingroup *groups;
|
||||
unsigned int ngroups;
|
||||
};
|
||||
|
||||
static const struct amdisp_pinctrl_data amdisp_pinctrl_data = {
|
||||
.pins = amdisp_pins,
|
||||
.npins = ARRAY_SIZE(amdisp_pins),
|
||||
.functions = amdisp_functions,
|
||||
.nfunctions = ARRAY_SIZE(amdisp_functions),
|
||||
.groups = amdisp_groups,
|
||||
.ngroups = ARRAY_SIZE(amdisp_groups),
|
||||
};
|
||||
|
||||
struct amdisp_pinctrl {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pctrl;
|
||||
struct pinctrl_desc desc;
|
||||
struct pinctrl_gpio_range gpio_range;
|
||||
struct gpio_chip gc;
|
||||
const struct amdisp_pinctrl_data *data;
|
||||
void __iomem *gpiobase;
|
||||
raw_spinlock_t lock;
|
||||
};
|
||||
|
||||
static int amdisp_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
struct amdisp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pctrl->data->ngroups;
|
||||
}
|
||||
|
||||
static const char *amdisp_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned int group)
|
||||
{
|
||||
struct amdisp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pctrl->data->groups[group].name;
|
||||
}
|
||||
|
||||
static int amdisp_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
unsigned int group,
|
||||
const unsigned int **pins,
|
||||
unsigned int *num_pins)
|
||||
{
|
||||
struct amdisp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
*pins = pctrl->data->groups[group].pins;
|
||||
*num_pins = pctrl->data->groups[group].npins;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct pinctrl_ops amdisp_pinctrl_ops = {
|
||||
.get_groups_count = amdisp_get_groups_count,
|
||||
.get_group_name = amdisp_get_group_name,
|
||||
.get_group_pins = amdisp_get_group_pins,
|
||||
};
|
||||
|
||||
static int amdisp_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
/* amdisp gpio only has output mode */
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static int amdisp_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int amdisp_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio,
|
||||
int value)
|
||||
{
|
||||
/* Nothing to do, amdisp gpio only has output mode */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdisp_gpio_get(struct gpio_chip *gc, unsigned int gpio)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 pin_reg;
|
||||
struct amdisp_pinctrl *pctrl = gpiochip_get_data(gc);
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
pin_reg = readl(pctrl->gpiobase + gpio_offset[gpio]);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
return !!(pin_reg & BIT(GPIO_CONTROL_PIN));
|
||||
}
|
||||
|
||||
static void amdisp_gpio_set(struct gpio_chip *gc, unsigned int gpio, int value)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 pin_reg;
|
||||
struct amdisp_pinctrl *pctrl = gpiochip_get_data(gc);
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
pin_reg = readl(pctrl->gpiobase + gpio_offset[gpio]);
|
||||
if (value)
|
||||
pin_reg |= BIT(GPIO_CONTROL_PIN);
|
||||
else
|
||||
pin_reg &= ~BIT(GPIO_CONTROL_PIN);
|
||||
writel(pin_reg, pctrl->gpiobase + gpio_offset[gpio]);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
}
|
||||
|
||||
static int amdisp_gpiochip_add(struct platform_device *pdev,
|
||||
struct amdisp_pinctrl *pctrl)
|
||||
{
|
||||
struct gpio_chip *gc = &pctrl->gc;
|
||||
struct pinctrl_gpio_range *grange = &pctrl->gpio_range;
|
||||
int ret;
|
||||
|
||||
gc->label = dev_name(pctrl->dev);
|
||||
gc->parent = &pdev->dev;
|
||||
gc->names = amdisp_range_pins_name;
|
||||
gc->request = gpiochip_generic_request;
|
||||
gc->free = gpiochip_generic_free;
|
||||
gc->get_direction = amdisp_gpio_get_direction;
|
||||
gc->direction_input = amdisp_gpio_direction_input;
|
||||
gc->direction_output = amdisp_gpio_direction_output;
|
||||
gc->get = amdisp_gpio_get;
|
||||
gc->set = amdisp_gpio_set;
|
||||
gc->base = -1;
|
||||
gc->ngpio = ARRAY_SIZE(amdisp_range_pins);
|
||||
|
||||
grange->id = 0;
|
||||
grange->pin_base = 0;
|
||||
grange->base = 0;
|
||||
grange->pins = amdisp_range_pins;
|
||||
grange->npins = ARRAY_SIZE(amdisp_range_pins);
|
||||
grange->name = gc->label;
|
||||
grange->gc = gc;
|
||||
|
||||
ret = devm_gpiochip_add_data(&pdev->dev, gc, pctrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pinctrl_add_gpio_range(pctrl->pctrl, grange);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdisp_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct amdisp_pinctrl *pctrl;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
|
||||
if (!pctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
pdev->dev.init_name = DRV_NAME;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -EINVAL;
|
||||
|
||||
pctrl->gpiobase = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pctrl->gpiobase))
|
||||
return PTR_ERR(pctrl->gpiobase);
|
||||
|
||||
platform_set_drvdata(pdev, pctrl);
|
||||
|
||||
pctrl->dev = &pdev->dev;
|
||||
pctrl->data = &amdisp_pinctrl_data;
|
||||
pctrl->desc.owner = THIS_MODULE;
|
||||
pctrl->desc.pctlops = &amdisp_pinctrl_ops;
|
||||
pctrl->desc.pmxops = NULL;
|
||||
pctrl->desc.name = dev_name(&pdev->dev);
|
||||
pctrl->desc.pins = pctrl->data->pins;
|
||||
pctrl->desc.npins = pctrl->data->npins;
|
||||
ret = devm_pinctrl_register_and_init(&pdev->dev, &pctrl->desc,
|
||||
pctrl, &pctrl->pctrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pinctrl_enable(pctrl->pctrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = amdisp_gpiochip_add(pdev, pctrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver amdisp_pinctrl_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
},
|
||||
.probe = amdisp_pinctrl_probe,
|
||||
};
|
||||
module_platform_driver(amdisp_pinctrl_driver);
|
||||
|
||||
MODULE_AUTHOR("Benjamin Chan <benjamin.chan@amd.com>");
|
||||
MODULE_AUTHOR("Pratap Nirujogi <pratap.nirujogi@amd.com>");
|
||||
MODULE_DESCRIPTION("AMDISP pinctrl driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
||||
95
drivers/pinctrl/pinctrl-amdisp.h
Normal file
95
drivers/pinctrl/pinctrl-amdisp.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* AMD ISP Pinctrl Driver
|
||||
*
|
||||
* Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
static const struct pinctrl_pin_desc amdisp_pins[] = {
|
||||
PINCTRL_PIN(0, "GPIO_0"), /* sensor0 control */
|
||||
PINCTRL_PIN(1, "GPIO_1"), /* sensor1 control */
|
||||
PINCTRL_PIN(2, "GPIO_2"), /* sensor2 control */
|
||||
};
|
||||
|
||||
#define AMDISP_GPIO_PINS(pin) \
|
||||
static const unsigned int gpio##pin##_pins[] = { pin }
|
||||
AMDISP_GPIO_PINS(0);
|
||||
AMDISP_GPIO_PINS(1);
|
||||
AMDISP_GPIO_PINS(2);
|
||||
|
||||
static const unsigned int amdisp_range_pins[] = {
|
||||
0, 1, 2
|
||||
};
|
||||
|
||||
static const char * const amdisp_range_pins_name[] = {
|
||||
"gpio0", "gpio1", "gpio2"
|
||||
};
|
||||
|
||||
enum amdisp_functions {
|
||||
mux_gpio,
|
||||
mux_NA
|
||||
};
|
||||
|
||||
static const char * const gpio_groups[] = {
|
||||
"gpio0", "gpio1", "gpio2"
|
||||
};
|
||||
|
||||
/**
|
||||
* struct amdisp_function - a pinmux function
|
||||
* @name: Name of the pinmux function.
|
||||
* @groups: List of pingroups for this function.
|
||||
* @ngroups: Number of entries in @groups.
|
||||
*/
|
||||
struct amdisp_function {
|
||||
const char *name;
|
||||
const char * const *groups;
|
||||
unsigned int ngroups;
|
||||
};
|
||||
|
||||
#define FUNCTION(fname) \
|
||||
[mux_##fname] = { \
|
||||
.name = #fname, \
|
||||
.groups = fname##_groups, \
|
||||
.ngroups = ARRAY_SIZE(fname##_groups), \
|
||||
}
|
||||
|
||||
static const struct amdisp_function amdisp_functions[] = {
|
||||
FUNCTION(gpio),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct amdisp_pingroup - a pinmux group
|
||||
* @name: Name of the pinmux group.
|
||||
* @pins: List of pins for this group.
|
||||
* @npins: Number of entries in @pins.
|
||||
* @funcs: List of functions belongs to this group.
|
||||
* @nfuncs: Number of entries in @funcs.
|
||||
* @offset: Group offset in amdisp pinmux groups.
|
||||
*/
|
||||
struct amdisp_pingroup {
|
||||
const char *name;
|
||||
const unsigned int *pins;
|
||||
unsigned int npins;
|
||||
unsigned int *funcs;
|
||||
unsigned int nfuncs;
|
||||
unsigned int offset;
|
||||
};
|
||||
|
||||
#define PINGROUP(id, f0) \
|
||||
{ \
|
||||
.name = "gpio" #id, \
|
||||
.pins = gpio##id##_pins, \
|
||||
.npins = ARRAY_SIZE(gpio##id##_pins), \
|
||||
.funcs = (int[]){ \
|
||||
mux_##f0, \
|
||||
}, \
|
||||
.nfuncs = 1, \
|
||||
.offset = id, \
|
||||
}
|
||||
|
||||
static const struct amdisp_pingroup amdisp_groups[] = {
|
||||
PINGROUP(0, gpio),
|
||||
PINGROUP(1, gpio),
|
||||
PINGROUP(2, gpio),
|
||||
};
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
/* Port Select configures the port */
|
||||
#define CY8C95X0_PORTSEL 0x18
|
||||
|
||||
/* Port settings, write PORTSEL first */
|
||||
#define CY8C95X0_INTMASK 0x19
|
||||
#define CY8C95X0_SELPWM 0x1A
|
||||
@@ -53,6 +54,9 @@
|
||||
#define CY8C95X0_DRV_PP_FAST 0x21
|
||||
#define CY8C95X0_DRV_PP_SLOW 0x22
|
||||
#define CY8C95X0_DRV_HIZ 0x23
|
||||
|
||||
/* Internal device configuration */
|
||||
#define CY8C95X0_ENABLE_WDE 0x2D
|
||||
#define CY8C95X0_DEVID 0x2E
|
||||
#define CY8C95X0_WATCHDOG 0x2F
|
||||
#define CY8C95X0_COMMAND 0x30
|
||||
@@ -137,7 +141,7 @@ static const struct dmi_system_id cy8c95x0_dmi_acpi_irq_info[] = {
|
||||
* @irq_trig_low: I/O bits affected by a low voltage level
|
||||
* @irq_trig_high: I/O bits affected by a high voltage level
|
||||
* @push_pull: I/O bits configured as push pull driver
|
||||
* @shiftmask: Mask used to compensate for Gport2 width
|
||||
* @map: Mask used to compensate for Gport2 width
|
||||
* @nport: Number of Gports in this chip
|
||||
* @gpio_chip: gpiolib chip
|
||||
* @driver_data: private driver data
|
||||
@@ -158,7 +162,7 @@ struct cy8c95x0_pinctrl {
|
||||
DECLARE_BITMAP(irq_trig_low, MAX_LINE);
|
||||
DECLARE_BITMAP(irq_trig_high, MAX_LINE);
|
||||
DECLARE_BITMAP(push_pull, MAX_LINE);
|
||||
DECLARE_BITMAP(shiftmask, MAX_LINE);
|
||||
DECLARE_BITMAP(map, MAX_LINE);
|
||||
unsigned int nport;
|
||||
struct gpio_chip gpio_chip;
|
||||
unsigned long driver_data;
|
||||
@@ -310,9 +314,6 @@ static const char * const cy8c95x0_groups[] = {
|
||||
"gp77",
|
||||
};
|
||||
|
||||
static int cy8c95x0_pinmux_direction(struct cy8c95x0_pinctrl *chip,
|
||||
unsigned int pin, bool input);
|
||||
|
||||
static inline u8 cypress_get_port(struct cy8c95x0_pinctrl *chip, unsigned int pin)
|
||||
{
|
||||
/* Account for GPORT2 which only has 4 bits */
|
||||
@@ -477,20 +478,14 @@ static const struct regmap_config cy8c9520_i2c_regmap = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline int cy8c95x0_regmap_update_bits_base(struct cy8c95x0_pinctrl *chip,
|
||||
unsigned int reg,
|
||||
unsigned int port,
|
||||
unsigned int mask,
|
||||
unsigned int val,
|
||||
bool *change, bool async,
|
||||
bool force)
|
||||
/* Caller should never modify PORTSEL directly */
|
||||
static int cy8c95x0_regmap_update_bits_base(struct cy8c95x0_pinctrl *chip,
|
||||
unsigned int reg, unsigned int port,
|
||||
unsigned int mask, unsigned int val,
|
||||
bool *change, bool async, bool force)
|
||||
{
|
||||
int ret, off, i;
|
||||
|
||||
/* Caller should never modify PORTSEL directly */
|
||||
if (reg == CY8C95X0_PORTSEL)
|
||||
return -EINVAL;
|
||||
|
||||
/* Registers behind the PORTSEL mux have their own range in regmap */
|
||||
if (cy8c95x0_muxed_register(reg)) {
|
||||
off = CY8C95X0_MUX_REGMAP_TO_OFFSET(reg, port);
|
||||
@@ -507,7 +502,8 @@ static inline int cy8c95x0_regmap_update_bits_base(struct cy8c95x0_pinctrl *chip
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Mimic what hardware does and update the cache when a WC bit is written.
|
||||
/*
|
||||
* Mimic what hardware does and update the cache when a WC bit is written.
|
||||
* Allows to mark the registers as non-volatile and reduces I/O cycles.
|
||||
*/
|
||||
if (cy8c95x0_wc_register(reg) && (mask & val)) {
|
||||
@@ -523,7 +519,7 @@ static inline int cy8c95x0_regmap_update_bits_base(struct cy8c95x0_pinctrl *chip
|
||||
regcache_cache_only(chip->regmap, false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -575,12 +571,13 @@ static int cy8c95x0_regmap_update_bits(struct cy8c95x0_pinctrl *chip, unsigned i
|
||||
}
|
||||
|
||||
/**
|
||||
* cy8c95x0_regmap_read() - reads a register using the regmap cache
|
||||
* cy8c95x0_regmap_read_bits() - reads a register using the regmap cache
|
||||
* @chip: The pinctrl to work on
|
||||
* @reg: The register to read from. Can be direct access or muxed register.
|
||||
* @port: The port to be used for muxed registers or quick path direct access
|
||||
* registers. Otherwise unused.
|
||||
* @read_val: Value read from hardware or cache
|
||||
* @mask: Bitmask to apply
|
||||
* @val: Value read from hardware or cache
|
||||
*
|
||||
* This function handles the register reads from the direct access registers and
|
||||
* the muxed registers while caching all register accesses, internally handling
|
||||
@@ -590,10 +587,12 @@ static int cy8c95x0_regmap_update_bits(struct cy8c95x0_pinctrl *chip, unsigned i
|
||||
*
|
||||
* Return: 0 for successful request, else a corresponding error value
|
||||
*/
|
||||
static int cy8c95x0_regmap_read(struct cy8c95x0_pinctrl *chip, unsigned int reg,
|
||||
unsigned int port, unsigned int *read_val)
|
||||
static int cy8c95x0_regmap_read_bits(struct cy8c95x0_pinctrl *chip, unsigned int reg,
|
||||
unsigned int port, unsigned int mask, unsigned int *val)
|
||||
{
|
||||
int off, ret;
|
||||
unsigned int off;
|
||||
unsigned int tmp;
|
||||
int ret;
|
||||
|
||||
/* Registers behind the PORTSEL mux have their own range in regmap */
|
||||
if (cy8c95x0_muxed_register(reg)) {
|
||||
@@ -605,11 +604,14 @@ static int cy8c95x0_regmap_read(struct cy8c95x0_pinctrl *chip, unsigned int reg,
|
||||
else
|
||||
off = reg;
|
||||
}
|
||||
guard(mutex)(&chip->i2c_lock);
|
||||
|
||||
ret = regmap_read(chip->regmap, off, read_val);
|
||||
scoped_guard(mutex, &chip->i2c_lock)
|
||||
ret = regmap_read(chip->regmap, off, &tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
*val = tmp & mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cy8c95x0_write_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
|
||||
@@ -617,26 +619,18 @@ static int cy8c95x0_write_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
|
||||
{
|
||||
DECLARE_BITMAP(tmask, MAX_LINE);
|
||||
DECLARE_BITMAP(tval, MAX_LINE);
|
||||
unsigned long bits, offset;
|
||||
int write_val;
|
||||
u8 bits;
|
||||
int ret;
|
||||
|
||||
/* Add the 4 bit gap of Gport2 */
|
||||
bitmap_andnot(tmask, mask, chip->shiftmask, MAX_LINE);
|
||||
bitmap_shift_left(tmask, tmask, 4, MAX_LINE);
|
||||
bitmap_replace(tmask, tmask, mask, chip->shiftmask, BANK_SZ * 3);
|
||||
bitmap_scatter(tmask, mask, chip->map, MAX_LINE);
|
||||
bitmap_scatter(tval, val, chip->map, MAX_LINE);
|
||||
|
||||
bitmap_andnot(tval, val, chip->shiftmask, MAX_LINE);
|
||||
bitmap_shift_left(tval, tval, 4, MAX_LINE);
|
||||
bitmap_replace(tval, tval, val, chip->shiftmask, BANK_SZ * 3);
|
||||
for_each_set_clump8(offset, bits, tmask, chip->tpin) {
|
||||
unsigned int i = offset / 8;
|
||||
|
||||
for (unsigned int i = 0; i < chip->nport; i++) {
|
||||
/* Skip over unused banks */
|
||||
bits = bitmap_get_value8(tmask, i * BANK_SZ);
|
||||
if (!bits)
|
||||
continue;
|
||||
|
||||
write_val = bitmap_get_value8(tval, i * BANK_SZ);
|
||||
write_val = bitmap_get_value8(tval, offset);
|
||||
|
||||
ret = cy8c95x0_regmap_update_bits(chip, reg, i, bits, write_val);
|
||||
if (ret < 0) {
|
||||
@@ -653,40 +647,54 @@ static int cy8c95x0_read_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
|
||||
{
|
||||
DECLARE_BITMAP(tmask, MAX_LINE);
|
||||
DECLARE_BITMAP(tval, MAX_LINE);
|
||||
DECLARE_BITMAP(tmp, MAX_LINE);
|
||||
int read_val;
|
||||
u8 bits;
|
||||
unsigned long bits, offset;
|
||||
unsigned int read_val;
|
||||
int ret;
|
||||
|
||||
/* Add the 4 bit gap of Gport2 */
|
||||
bitmap_andnot(tmask, mask, chip->shiftmask, MAX_LINE);
|
||||
bitmap_shift_left(tmask, tmask, 4, MAX_LINE);
|
||||
bitmap_replace(tmask, tmask, mask, chip->shiftmask, BANK_SZ * 3);
|
||||
bitmap_scatter(tmask, mask, chip->map, MAX_LINE);
|
||||
bitmap_scatter(tval, val, chip->map, MAX_LINE);
|
||||
|
||||
bitmap_andnot(tval, val, chip->shiftmask, MAX_LINE);
|
||||
bitmap_shift_left(tval, tval, 4, MAX_LINE);
|
||||
bitmap_replace(tval, tval, val, chip->shiftmask, BANK_SZ * 3);
|
||||
for_each_set_clump8(offset, bits, tmask, chip->tpin) {
|
||||
unsigned int i = offset / 8;
|
||||
|
||||
for (unsigned int i = 0; i < chip->nport; i++) {
|
||||
/* Skip over unused banks */
|
||||
bits = bitmap_get_value8(tmask, i * BANK_SZ);
|
||||
if (!bits)
|
||||
continue;
|
||||
|
||||
ret = cy8c95x0_regmap_read(chip, reg, i, &read_val);
|
||||
ret = cy8c95x0_regmap_read_bits(chip, reg, i, bits, &read_val);
|
||||
if (ret < 0) {
|
||||
dev_err(chip->dev, "failed reading register %d, port %u: err %d\n", reg, i, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
read_val &= bits;
|
||||
read_val |= bitmap_get_value8(tval, i * BANK_SZ) & ~bits;
|
||||
bitmap_set_value8(tval, read_val, i * BANK_SZ);
|
||||
read_val |= bitmap_get_value8(tval, offset) & ~bits;
|
||||
bitmap_set_value8(tval, read_val, offset);
|
||||
}
|
||||
|
||||
/* Fill the 4 bit gap of Gport2 */
|
||||
bitmap_shift_right(tmp, tval, 4, MAX_LINE);
|
||||
bitmap_replace(val, tmp, tval, chip->shiftmask, MAX_LINE);
|
||||
bitmap_gather(val, tval, chip->map, MAX_LINE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cy8c95x0_pinmux_direction(struct cy8c95x0_pinctrl *chip, unsigned int pin, bool input)
|
||||
{
|
||||
u8 port = cypress_get_port(chip, pin);
|
||||
u8 bit = cypress_get_pin_mask(chip, pin);
|
||||
int ret;
|
||||
|
||||
ret = cy8c95x0_regmap_write_bits(chip, CY8C95X0_DIRECTION, port, bit, input ? bit : 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Disable driving the pin by forcing it to HighZ. Only setting
|
||||
* the direction register isn't sufficient in Push-Pull mode.
|
||||
*/
|
||||
if (input && test_bit(pin, chip->push_pull)) {
|
||||
ret = cy8c95x0_regmap_write_bits(chip, CY8C95X0_DRV_HIZ, port, bit, bit);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
__clear_bit(pin, chip->push_pull);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -717,10 +725,10 @@ static int cy8c95x0_gpio_get_value(struct gpio_chip *gc, unsigned int off)
|
||||
struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
|
||||
u8 port = cypress_get_port(chip, off);
|
||||
u8 bit = cypress_get_pin_mask(chip, off);
|
||||
u32 reg_val;
|
||||
unsigned int reg_val;
|
||||
int ret;
|
||||
|
||||
ret = cy8c95x0_regmap_read(chip, CY8C95X0_INPUT, port, ®_val);
|
||||
ret = cy8c95x0_regmap_read_bits(chip, CY8C95X0_INPUT, port, bit, ®_val);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* NOTE:
|
||||
@@ -731,7 +739,7 @@ static int cy8c95x0_gpio_get_value(struct gpio_chip *gc, unsigned int off)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return !!(reg_val & bit);
|
||||
return reg_val ? 1 : 0;
|
||||
}
|
||||
|
||||
static void cy8c95x0_gpio_set_value(struct gpio_chip *gc, unsigned int off,
|
||||
@@ -749,14 +757,14 @@ static int cy8c95x0_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
|
||||
struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
|
||||
u8 port = cypress_get_port(chip, off);
|
||||
u8 bit = cypress_get_pin_mask(chip, off);
|
||||
u32 reg_val;
|
||||
unsigned int reg_val;
|
||||
int ret;
|
||||
|
||||
ret = cy8c95x0_regmap_read(chip, CY8C95X0_DIRECTION, port, ®_val);
|
||||
ret = cy8c95x0_regmap_read_bits(chip, CY8C95X0_DIRECTION, port, bit, ®_val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (reg_val & bit)
|
||||
if (reg_val)
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
@@ -769,8 +777,8 @@ static int cy8c95x0_gpio_get_pincfg(struct cy8c95x0_pinctrl *chip,
|
||||
enum pin_config_param param = pinconf_to_config_param(*config);
|
||||
u8 port = cypress_get_port(chip, off);
|
||||
u8 bit = cypress_get_pin_mask(chip, off);
|
||||
unsigned int reg_val;
|
||||
unsigned int reg;
|
||||
u32 reg_val;
|
||||
u16 arg = 0;
|
||||
int ret;
|
||||
|
||||
@@ -827,16 +835,16 @@ static int cy8c95x0_gpio_get_pincfg(struct cy8c95x0_pinctrl *chip,
|
||||
* Writing 1 to one of the drive mode registers will automatically
|
||||
* clear conflicting set bits in the other drive mode registers.
|
||||
*/
|
||||
ret = cy8c95x0_regmap_read(chip, reg, port, ®_val);
|
||||
ret = cy8c95x0_regmap_read_bits(chip, reg, port, bit, ®_val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (reg_val & bit)
|
||||
if (reg_val)
|
||||
arg = 1;
|
||||
if (param == PIN_CONFIG_OUTPUT_ENABLE)
|
||||
arg = !arg;
|
||||
|
||||
*config = pinconf_to_config_packed(param, (u16)arg);
|
||||
*config = pinconf_to_config_packed(param, arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1095,7 +1103,7 @@ static irqreturn_t cy8c95x0_irq_handler(int irq, void *devid)
|
||||
if (!ret)
|
||||
return IRQ_RETVAL(0);
|
||||
|
||||
ret = 0;
|
||||
ret = false;
|
||||
for_each_set_bit(level, pending, MAX_LINE) {
|
||||
/* Already accounted for 4bit gap in GPort2 */
|
||||
nested_irq = irq_find_mapping(gc->irq.domain, level);
|
||||
@@ -1114,7 +1122,7 @@ static irqreturn_t cy8c95x0_irq_handler(int irq, void *devid)
|
||||
else
|
||||
handle_nested_irq(nested_irq);
|
||||
|
||||
ret = 1;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return IRQ_RETVAL(ret);
|
||||
@@ -1248,32 +1256,6 @@ static int cy8c95x0_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
return cy8c95x0_set_mode(chip, pin, false);
|
||||
}
|
||||
|
||||
static int cy8c95x0_pinmux_direction(struct cy8c95x0_pinctrl *chip,
|
||||
unsigned int pin, bool input)
|
||||
{
|
||||
u8 port = cypress_get_port(chip, pin);
|
||||
u8 bit = cypress_get_pin_mask(chip, pin);
|
||||
int ret;
|
||||
|
||||
ret = cy8c95x0_regmap_write_bits(chip, CY8C95X0_DIRECTION, port, bit, input ? bit : 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Disable driving the pin by forcing it to HighZ. Only setting
|
||||
* the direction register isn't sufficient in Push-Pull mode.
|
||||
*/
|
||||
if (input && test_bit(pin, chip->push_pull)) {
|
||||
ret = cy8c95x0_regmap_write_bits(chip, CY8C95X0_DRV_HIZ, port, bit, bit);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
__clear_bit(pin, chip->push_pull);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cy8c95x0_gpio_set_direction(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range,
|
||||
unsigned int pin, bool input)
|
||||
@@ -1305,7 +1287,7 @@ static int cy8c95x0_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
unsigned long *configs, unsigned int num_configs)
|
||||
{
|
||||
struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
|
||||
int ret = 0;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
@@ -1314,7 +1296,7 @@ static int cy8c95x0_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinconf_ops cy8c95x0_pinconf_ops = {
|
||||
@@ -1486,8 +1468,11 @@ static int cy8c95x0_probe(struct i2c_client *client)
|
||||
return PTR_ERR(chip->regmap);
|
||||
|
||||
bitmap_zero(chip->push_pull, MAX_LINE);
|
||||
bitmap_zero(chip->shiftmask, MAX_LINE);
|
||||
bitmap_set(chip->shiftmask, 0, 20);
|
||||
|
||||
/* Setup HW pins mapping */
|
||||
bitmap_fill(chip->map, MAX_LINE);
|
||||
bitmap_clear(chip->map, 20, 4);
|
||||
|
||||
mutex_init(&chip->i2c_lock);
|
||||
|
||||
if (dmi_first_match(cy8c95x0_dmi_acpi_irq_info)) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Ingenic SoCs pinctrl driver
|
||||
*
|
||||
* Copyright (c) 2017 Paul Cercueil <paul@crapouillou.net>
|
||||
* Copyright (c) 2017, 2019 Paul Boddie <paul@boddie.org.uk>
|
||||
* Copyright (c) 2017, 2019, 2020, 2023 Paul Boddie <paul@boddie.org.uk>
|
||||
* Copyright (c) 2019, 2020 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
|
||||
*/
|
||||
|
||||
@@ -58,6 +58,8 @@
|
||||
#define JZ4770_GPIO_FLAG 0x50
|
||||
#define JZ4770_GPIO_PEN 0x70
|
||||
|
||||
#define X1600_GPIO_PU 0x80
|
||||
|
||||
#define X1830_GPIO_PEL 0x110
|
||||
#define X1830_GPIO_PEH 0x120
|
||||
#define X1830_GPIO_SR 0x150
|
||||
@@ -112,6 +114,7 @@ enum jz_version {
|
||||
ID_JZ4780,
|
||||
ID_X1000,
|
||||
ID_X1500,
|
||||
ID_X1600,
|
||||
ID_X1830,
|
||||
ID_X2000,
|
||||
ID_X2100,
|
||||
@@ -162,6 +165,7 @@ static const unsigned long enabled_socs =
|
||||
IS_ENABLED(CONFIG_MACH_JZ4780) << ID_JZ4780 |
|
||||
IS_ENABLED(CONFIG_MACH_X1000) << ID_X1000 |
|
||||
IS_ENABLED(CONFIG_MACH_X1500) << ID_X1500 |
|
||||
IS_ENABLED(CONFIG_MACH_X1600) << ID_X1600 |
|
||||
IS_ENABLED(CONFIG_MACH_X1830) << ID_X1830 |
|
||||
IS_ENABLED(CONFIG_MACH_X2000) << ID_X2000 |
|
||||
IS_ENABLED(CONFIG_MACH_X2100) << ID_X2100;
|
||||
@@ -206,6 +210,14 @@ static int jz4730_nand_cs5_pins[] = { 0x57, };
|
||||
static int jz4730_pwm_pwm0_pins[] = { 0x5e, };
|
||||
static int jz4730_pwm_pwm1_pins[] = { 0x5f, };
|
||||
|
||||
static int jz4730_mii_pins[] = { 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
|
||||
0x77, 0x78, 0x19, 0x7a, 0x1b, 0x7c, };
|
||||
|
||||
static int jz4730_i2s_mclk_pins[] = { 0x44, };
|
||||
static int jz4730_i2s_acreset_pins[] = { 0x45, };
|
||||
static int jz4730_i2s_data_pins[] = { 0x46, 0x47, };
|
||||
static int jz4730_i2s_clock_pins[] = { 0x4d, 0x4e, };
|
||||
|
||||
static u8 jz4730_lcd_8bit_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, };
|
||||
|
||||
static const struct group_desc jz4730_groups[] = {
|
||||
@@ -227,6 +239,12 @@ static const struct group_desc jz4730_groups[] = {
|
||||
INGENIC_PIN_GROUP("nand-cs5", jz4730_nand_cs5, 1),
|
||||
INGENIC_PIN_GROUP("pwm0", jz4730_pwm_pwm0, 1),
|
||||
INGENIC_PIN_GROUP("pwm1", jz4730_pwm_pwm1, 1),
|
||||
INGENIC_PIN_GROUP("mii", jz4730_mii, 1),
|
||||
INGENIC_PIN_GROUP("i2s-mclk-out", jz4730_i2s_mclk, 1),
|
||||
INGENIC_PIN_GROUP("i2s-acreset", jz4730_i2s_acreset, 1),
|
||||
INGENIC_PIN_GROUP("i2s-data", jz4730_i2s_data, 1),
|
||||
INGENIC_PIN_GROUP("i2s-master", jz4730_i2s_clock, 1),
|
||||
INGENIC_PIN_GROUP("i2s-slave", jz4730_i2s_clock, 2),
|
||||
};
|
||||
|
||||
static const char *jz4730_mmc_groups[] = { "mmc-1bit", "mmc-4bit", };
|
||||
@@ -242,6 +260,8 @@ static const char *jz4730_nand_groups[] = {
|
||||
};
|
||||
static const char *jz4730_pwm0_groups[] = { "pwm0", };
|
||||
static const char *jz4730_pwm1_groups[] = { "pwm1", };
|
||||
static const char *jz4730_mii_groups[] = { "mii", };
|
||||
static const char *jz4730_i2s_groups[] = { "i2s-data", "i2s-master", "i2s-slave", };
|
||||
|
||||
static const struct function_desc jz4730_functions[] = {
|
||||
INGENIC_PIN_FUNCTION("mmc", jz4730_mmc),
|
||||
@@ -253,6 +273,8 @@ static const struct function_desc jz4730_functions[] = {
|
||||
INGENIC_PIN_FUNCTION("nand", jz4730_nand),
|
||||
INGENIC_PIN_FUNCTION("pwm0", jz4730_pwm0),
|
||||
INGENIC_PIN_FUNCTION("pwm1", jz4730_pwm1),
|
||||
INGENIC_PIN_FUNCTION("mii", jz4730_mii),
|
||||
INGENIC_PIN_FUNCTION("i2s", jz4730_i2s),
|
||||
};
|
||||
|
||||
static const struct ingenic_chip_info jz4730_chip_info = {
|
||||
@@ -2351,6 +2373,233 @@ static const struct ingenic_chip_info x1500_chip_info = {
|
||||
.access_table = &x1000_access_table,
|
||||
};
|
||||
|
||||
static const u32 x1600_pull_ups[4] = {
|
||||
0xffffffff, 0xdffbf7bf, 0x987e0000, 0x0000003f,
|
||||
};
|
||||
|
||||
static const u32 x1600_pull_downs[4] = {
|
||||
0x00000000, 0x00000000, 0x07000007, 0x00000000,
|
||||
};
|
||||
|
||||
static int x1600_uart0_data_pins[] = { 0x27, 0x28, };
|
||||
static int x1600_uart0_hwflow_pins[] = { 0x29, 0x2a, };
|
||||
static int x1600_uart1_data_pins[] = { 0x23, 0x22, };
|
||||
static int x1600_uart1_hwflow_pins[] = { 0x25, 0x24, };
|
||||
static int x1600_uart2_data_a_pins[] = { 0x1f, 0x1e, };
|
||||
static int x1600_uart2_data_b_pins[] = { 0x21, 0x20, };
|
||||
static int x1600_uart3_data_b_pins[] = { 0x25, 0x24, };
|
||||
static int x1600_uart3_data_d_pins[] = { 0x65, 0x64, };
|
||||
static int x1600_sfc_pins[] = { 0x53, 0x54, 0x55, 0x56, 0x51, 0x52, 0x24, };
|
||||
static int x1600_ssi_dt_a_pins[] = { 0x1e, };
|
||||
static int x1600_ssi_dt_b_pins[] = { 0x2d, };
|
||||
static int x1600_ssi_dr_a_pins[] = { 0x1d, };
|
||||
static int x1600_ssi_dr_b_pins[] = { 0x2e, };
|
||||
static int x1600_ssi_clk_a_pins[] = { 0x1f, };
|
||||
static int x1600_ssi_clk_b_pins[] = { 0x2c, };
|
||||
static int x1600_ssi_ce0_a_pins[] = { 0x1c, };
|
||||
static int x1600_ssi_ce0_b_pins[] = { 0x31, };
|
||||
static int x1600_ssi_ce1_a_pins[] = { 0x22, };
|
||||
static int x1600_ssi_ce1_b_pins[] = { 0x30, };
|
||||
static int x1600_mmc0_1bit_b_pins[] = { 0x2c, 0x2d, 0x2e, };
|
||||
static int x1600_mmc0_4bit_b_pins[] = { 0x2f, 0x30, 0x31, };
|
||||
static int x1600_mmc0_1bit_c_pins[] = { 0x51, 0x53, 0x54, };
|
||||
static int x1600_mmc0_4bit_c_pins[] = { 0x56, 0x55, 0x52, };
|
||||
static int x1600_mmc1_1bit_pins[] = { 0x60, 0x61, 0x62, };
|
||||
static int x1600_mmc1_4bit_pins[] = { 0x63, 0x64, 0x65, };
|
||||
static int x1600_i2c0_a_pins[] = { 0x1d, 0x1c, };
|
||||
static int x1600_i2c0_b_pins[] = { 0x3f, 0x3e, };
|
||||
static int x1600_i2c1_b_15_pins[] = { 0x30, 0x2f, };
|
||||
static int x1600_i2c1_b_19_pins[] = { 0x34, 0x33, };
|
||||
static int x1600_i2s_data_tx_pins[] = { 0x39, };
|
||||
static int x1600_i2s_data_rx_pins[] = { 0x35, };
|
||||
static int x1600_i2s_clk_rx_pins[] = { 0x37, 0x38, };
|
||||
static int x1600_i2s_clk_tx_pins[] = { 0x3b, 0x3c, };
|
||||
static int x1600_i2s_sysclk_pins[] = { 0x36, 0x3a, };
|
||||
|
||||
static int x1600_cim_pins[] = {
|
||||
0x14, 0x16, 0x15, 0x18, 0x13,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
};
|
||||
|
||||
static int x1600_slcd_8bit_pins[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x17, 0x19, 0x1a, 0x1b,
|
||||
};
|
||||
|
||||
static int x1600_slcd_16bit_pins[] = {
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
};
|
||||
|
||||
static int x1600_lcd_16bit_pins[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x18, 0x19, 0x1a, 0x1b,
|
||||
};
|
||||
|
||||
static int x1600_lcd_18bit_pins[] = {
|
||||
0x10, 0x11,
|
||||
};
|
||||
|
||||
static int x1600_lcd_24bit_pins[] = {
|
||||
0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
};
|
||||
|
||||
static int x1600_pwm_pwm0_pins[] = { 0x40, };
|
||||
static int x1600_pwm_pwm1_pins[] = { 0x41, };
|
||||
static int x1600_pwm_pwm2_pins[] = { 0x42, };
|
||||
static int x1600_pwm_pwm3_pins[] = { 0x58, };
|
||||
static int x1600_pwm_pwm4_pins[] = { 0x59, };
|
||||
static int x1600_pwm_pwm5_b_pins[] = { 0x33, };
|
||||
static int x1600_pwm_pwm5_c_pins[] = { 0x5a, };
|
||||
static int x1600_pwm_pwm6_b9_pins[] = { 0x29, };
|
||||
static int x1600_pwm_pwm6_b20_pins[] = { 0x34, };
|
||||
static int x1600_pwm_pwm7_b10_pins[] = { 0x2a, };
|
||||
static int x1600_pwm_pwm7_b21_pins[] = { 0x35, };
|
||||
|
||||
static int x1600_mac_pins[] = {
|
||||
0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c,
|
||||
};
|
||||
|
||||
static int x1600_sfc_funcs[] = { 0, 0, 0, 0, 0, 0, 2, };
|
||||
|
||||
static const struct group_desc x1600_groups[] = {
|
||||
INGENIC_PIN_GROUP("uart0-data", x1600_uart0_data, 0),
|
||||
INGENIC_PIN_GROUP("uart0-hwflow", x1600_uart0_hwflow, 0),
|
||||
INGENIC_PIN_GROUP("uart1-data", x1600_uart1_data, 1),
|
||||
INGENIC_PIN_GROUP("uart1-hwflow", x1600_uart1_hwflow, 1),
|
||||
INGENIC_PIN_GROUP("uart2-data-a", x1600_uart2_data_a, 2),
|
||||
INGENIC_PIN_GROUP("uart2-data-b", x1600_uart2_data_b, 1),
|
||||
INGENIC_PIN_GROUP("uart3-data-b", x1600_uart3_data_b, 0),
|
||||
INGENIC_PIN_GROUP("uart3-data-d", x1600_uart3_data_d, 2),
|
||||
INGENIC_PIN_GROUP_FUNCS("sfc", x1600_sfc, x1600_sfc_funcs),
|
||||
INGENIC_PIN_GROUP("ssi-dt-a", x1600_ssi_dt_a, 0),
|
||||
INGENIC_PIN_GROUP("ssi-dt-b", x1600_ssi_dt_b, 1),
|
||||
INGENIC_PIN_GROUP("ssi-dr-a", x1600_ssi_dr_a, 0),
|
||||
INGENIC_PIN_GROUP("ssi-dr-b", x1600_ssi_dr_b, 1),
|
||||
INGENIC_PIN_GROUP("ssi-clk-a", x1600_ssi_clk_a, 0),
|
||||
INGENIC_PIN_GROUP("ssi-clk-b", x1600_ssi_clk_b, 1),
|
||||
INGENIC_PIN_GROUP("ssi-ce0-a", x1600_ssi_ce0_a, 0),
|
||||
INGENIC_PIN_GROUP("ssi-ce0-b", x1600_ssi_ce0_b, 1),
|
||||
INGENIC_PIN_GROUP("ssi-ce1-a", x1600_ssi_ce1_a, 2),
|
||||
INGENIC_PIN_GROUP("ssi-ce1-b", x1600_ssi_ce1_b, 1),
|
||||
INGENIC_PIN_GROUP("mmc0-1bit-b", x1600_mmc0_1bit_b, 0),
|
||||
INGENIC_PIN_GROUP("mmc0-4bit-b", x1600_mmc0_4bit_b, 0),
|
||||
INGENIC_PIN_GROUP("mmc0-1bit-c", x1600_mmc0_1bit_c, 1),
|
||||
INGENIC_PIN_GROUP("mmc0-4bit-c", x1600_mmc0_4bit_c, 1),
|
||||
INGENIC_PIN_GROUP("mmc1-1bit", x1600_mmc1_1bit, 0),
|
||||
INGENIC_PIN_GROUP("mmc1-4bit", x1600_mmc1_4bit, 0),
|
||||
INGENIC_PIN_GROUP("i2c0-data-a", x1600_i2c0_a, 2),
|
||||
INGENIC_PIN_GROUP("i2c0-data-b", x1600_i2c0_b, 0),
|
||||
INGENIC_PIN_GROUP("i2c1-data-b-15", x1600_i2c1_b_15, 2),
|
||||
INGENIC_PIN_GROUP("i2c1-data-b-19", x1600_i2c1_b_19, 0),
|
||||
INGENIC_PIN_GROUP("i2s-data-tx", x1600_i2s_data_tx, 0),
|
||||
INGENIC_PIN_GROUP("i2s-data-rx", x1600_i2s_data_rx, 0),
|
||||
INGENIC_PIN_GROUP("i2s-clk-rx", x1600_i2s_clk_rx, 0),
|
||||
INGENIC_PIN_GROUP("i2s-clk-tx", x1600_i2s_clk_tx, 0),
|
||||
INGENIC_PIN_GROUP("i2s-sysclk", x1600_i2s_sysclk, 0),
|
||||
INGENIC_PIN_GROUP("cim-data", x1600_cim, 2),
|
||||
INGENIC_PIN_GROUP("slcd-8bit", x1600_slcd_8bit, 1),
|
||||
INGENIC_PIN_GROUP("slcd-16bit", x1600_slcd_16bit, 1),
|
||||
INGENIC_PIN_GROUP("lcd-16bit", x1600_lcd_16bit, 0),
|
||||
INGENIC_PIN_GROUP("lcd-18bit", x1600_lcd_18bit, 0),
|
||||
INGENIC_PIN_GROUP("lcd-24bit", x1600_lcd_24bit, 0),
|
||||
INGENIC_PIN_GROUP("pwm0", x1600_pwm_pwm0, 0),
|
||||
INGENIC_PIN_GROUP("pwm1", x1600_pwm_pwm1, 0),
|
||||
INGENIC_PIN_GROUP("pwm2", x1600_pwm_pwm2, 0),
|
||||
INGENIC_PIN_GROUP("pwm3", x1600_pwm_pwm3, 1),
|
||||
INGENIC_PIN_GROUP("pwm4", x1600_pwm_pwm4, 1),
|
||||
INGENIC_PIN_GROUP("pwm5-b", x1600_pwm_pwm5_b, 2),
|
||||
INGENIC_PIN_GROUP("pwm5-c", x1600_pwm_pwm5_c, 1),
|
||||
INGENIC_PIN_GROUP("pwm6-b9", x1600_pwm_pwm6_b9, 1),
|
||||
INGENIC_PIN_GROUP("pwm6-b20", x1600_pwm_pwm6_b20, 2),
|
||||
INGENIC_PIN_GROUP("pwm7-b10", x1600_pwm_pwm7_b10, 1),
|
||||
INGENIC_PIN_GROUP("pwm7-b21", x1600_pwm_pwm7_b21, 2),
|
||||
INGENIC_PIN_GROUP("mac", x1600_mac, 1),
|
||||
};
|
||||
|
||||
static const char * const x1600_uart0_groups[] = { "uart0-data", "uart0-hwflow", };
|
||||
static const char * const x1600_uart1_groups[] = { "uart1-data", "uart1-hwflow", };
|
||||
static const char * const x1600_uart2_groups[] = { "uart2-data-a", "uart2-data-b", };
|
||||
static const char * const x1600_uart3_groups[] = { "uart3-data-b", "uart3-data-d", };
|
||||
|
||||
static const char * const x1600_sfc_groups[] = { "sfc", };
|
||||
|
||||
static const char * const x1600_ssi_groups[] = {
|
||||
"ssi-dt-a", "ssi-dt-b",
|
||||
"ssi-dr-a", "ssi-dr-b",
|
||||
"ssi-clk-a", "ssi-clk-b",
|
||||
"ssi-ce0-a", "ssi-ce0-b",
|
||||
"ssi-ce1-a", "ssi-ce1-b",
|
||||
};
|
||||
|
||||
static const char * const x1600_mmc0_groups[] = { "mmc0-1bit-b", "mmc0-4bit-b",
|
||||
"mmc0-1bit-c", "mmc0-4bit-c",
|
||||
};
|
||||
|
||||
static const char * const x1600_mmc1_groups[] = { "mmc1-1bit", "mmc1-4bit", };
|
||||
|
||||
static const char * const x1600_i2c0_groups[] = { "i2c0-data-a", "i2c0-data-b", };
|
||||
static const char * const x1600_i2c1_groups[] = { "i2c1-data-b-15", "i2c1-data-b-19", };
|
||||
|
||||
static const char * const x1600_i2s_groups[] = {
|
||||
"i2s-data-tx", "i2s-data-rx", "i2s-clk-rx", "i2s-clk-tx", "i2s-sysclk",
|
||||
};
|
||||
|
||||
static const char * const x1600_cim_groups[] = { "cim-data", };
|
||||
|
||||
static const char * const x1600_lcd_groups[] = { "slcd-8bit", "slcd-16bit",
|
||||
"lcd-16bit", "lcd-18bit", "lcd-24bit", "lcd-no-pins",
|
||||
};
|
||||
|
||||
static const char * const x1600_pwm0_groups[] = { "pwm0", };
|
||||
static const char * const x1600_pwm1_groups[] = { "pwm1", };
|
||||
static const char * const x1600_pwm2_groups[] = { "pwm2", };
|
||||
static const char * const x1600_pwm3_groups[] = { "pwm3", };
|
||||
static const char * const x1600_pwm4_groups[] = { "pwm4", };
|
||||
static const char * const x1600_pwm5_groups[] = { "pwm5-b", "pwm5-c", };
|
||||
static const char * const x1600_pwm6_groups[] = { "pwm6-b9", "pwm6-b20", };
|
||||
static const char * const x1600_pwm7_groups[] = { "pwm7-b10", "pwm7-b21", };
|
||||
|
||||
static const char * const x1600_mac_groups[] = { "mac", };
|
||||
|
||||
static const struct function_desc x1600_functions[] = {
|
||||
INGENIC_PIN_FUNCTION("uart0", x1600_uart0),
|
||||
INGENIC_PIN_FUNCTION("uart1", x1600_uart1),
|
||||
INGENIC_PIN_FUNCTION("uart2", x1600_uart2),
|
||||
INGENIC_PIN_FUNCTION("uart3", x1600_uart3),
|
||||
INGENIC_PIN_FUNCTION("sfc", x1600_sfc),
|
||||
INGENIC_PIN_FUNCTION("ssi", x1600_ssi),
|
||||
INGENIC_PIN_FUNCTION("mmc0", x1600_mmc0),
|
||||
INGENIC_PIN_FUNCTION("mmc1", x1600_mmc1),
|
||||
INGENIC_PIN_FUNCTION("i2c0", x1600_i2c0),
|
||||
INGENIC_PIN_FUNCTION("i2c1", x1600_i2c1),
|
||||
INGENIC_PIN_FUNCTION("i2s", x1600_i2s),
|
||||
INGENIC_PIN_FUNCTION("cim", x1600_cim),
|
||||
INGENIC_PIN_FUNCTION("lcd", x1600_lcd),
|
||||
INGENIC_PIN_FUNCTION("pwm0", x1600_pwm0),
|
||||
INGENIC_PIN_FUNCTION("pwm1", x1600_pwm1),
|
||||
INGENIC_PIN_FUNCTION("pwm2", x1600_pwm2),
|
||||
INGENIC_PIN_FUNCTION("pwm3", x1600_pwm3),
|
||||
INGENIC_PIN_FUNCTION("pwm4", x1600_pwm4),
|
||||
INGENIC_PIN_FUNCTION("pwm5", x1600_pwm5),
|
||||
INGENIC_PIN_FUNCTION("pwm6", x1600_pwm6),
|
||||
INGENIC_PIN_FUNCTION("pwm7", x1600_pwm7),
|
||||
INGENIC_PIN_FUNCTION("mac", x1600_mac),
|
||||
};
|
||||
|
||||
static const struct ingenic_chip_info x1600_chip_info = {
|
||||
.num_chips = 4,
|
||||
.reg_offset = 0x100,
|
||||
.version = ID_X1600,
|
||||
.groups = x1600_groups,
|
||||
.num_groups = ARRAY_SIZE(x1600_groups),
|
||||
.functions = x1600_functions,
|
||||
.num_functions = ARRAY_SIZE(x1600_functions),
|
||||
.pull_ups = x1600_pull_ups,
|
||||
.pull_downs = x1600_pull_downs,
|
||||
.access_table = &x1000_access_table,
|
||||
};
|
||||
|
||||
static const u32 x1830_pull_ups[4] = {
|
||||
0x5fdfffc0, 0xffffefff, 0x1ffffbff, 0x0fcff3fc,
|
||||
};
|
||||
@@ -3860,7 +4109,9 @@ static int ingenic_pinconf_get(struct pinctrl_dev *pctldev,
|
||||
pulldown = (bias == GPIO_PULL_DOWN) && (jzpc->info->pull_downs[offt] & BIT(idx));
|
||||
|
||||
} else {
|
||||
if (is_soc_or_above(jzpc, ID_JZ4770))
|
||||
if (is_soc_or_above(jzpc, ID_X1600))
|
||||
pull = ingenic_get_pin_config(jzpc, pin, X1600_GPIO_PU);
|
||||
else if (is_soc_or_above(jzpc, ID_JZ4770))
|
||||
pull = !ingenic_get_pin_config(jzpc, pin, JZ4770_GPIO_PEN);
|
||||
else if (is_soc_or_above(jzpc, ID_JZ4740))
|
||||
pull = !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_PULL_DIS);
|
||||
@@ -3959,6 +4210,8 @@ static void ingenic_set_bias(struct ingenic_pinctrl *jzpc,
|
||||
REG_SET(X1830_GPIO_PEH), bias << idxh);
|
||||
}
|
||||
|
||||
} else if (is_soc_or_above(jzpc, ID_X1600)) {
|
||||
ingenic_config_pin(jzpc, pin, X1600_GPIO_PU, bias);
|
||||
} else if (is_soc_or_above(jzpc, ID_JZ4770)) {
|
||||
ingenic_config_pin(jzpc, pin, JZ4770_GPIO_PEN, !bias);
|
||||
} else if (is_soc_or_above(jzpc, ID_JZ4740)) {
|
||||
@@ -4150,6 +4403,7 @@ static const struct of_device_id ingenic_gpio_of_matches[] __initconst = {
|
||||
{ .compatible = "ingenic,jz4775-gpio" },
|
||||
{ .compatible = "ingenic,jz4780-gpio" },
|
||||
{ .compatible = "ingenic,x1000-gpio" },
|
||||
{ .compatible = "ingenic,x1600-gpio" },
|
||||
{ .compatible = "ingenic,x1830-gpio" },
|
||||
{ .compatible = "ingenic,x2000-gpio" },
|
||||
{ .compatible = "ingenic,x2100-gpio" },
|
||||
@@ -4397,6 +4651,10 @@ static const struct of_device_id ingenic_pinctrl_of_matches[] = {
|
||||
.compatible = "ingenic,x1500-pinctrl",
|
||||
.data = IF_ENABLED(CONFIG_MACH_X1500, &x1500_chip_info)
|
||||
},
|
||||
{
|
||||
.compatible = "ingenic,x1600-pinctrl",
|
||||
.data = IF_ENABLED(CONFIG_MACH_X1600, &x1600_chip_info)
|
||||
},
|
||||
{
|
||||
.compatible = "ingenic,x1830-pinctrl",
|
||||
.data = IF_ENABLED(CONFIG_MACH_X1830, &x1830_chip_info)
|
||||
|
||||
@@ -382,6 +382,7 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
|
||||
{
|
||||
struct mcp23s08 *mcp = data;
|
||||
int intcap, intcon, intf, i, gpio, gpio_orig, intcap_mask, defval, gpinten;
|
||||
bool need_unmask = false;
|
||||
unsigned long int enabled_interrupts;
|
||||
unsigned int child_irq;
|
||||
bool intf_set, intcap_changed, gpio_bit_changed,
|
||||
@@ -396,9 +397,6 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (mcp_read(mcp, MCP_INTCAP, &intcap))
|
||||
goto unlock;
|
||||
|
||||
if (mcp_read(mcp, MCP_INTCON, &intcon))
|
||||
goto unlock;
|
||||
|
||||
@@ -408,6 +406,16 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
|
||||
if (mcp_read(mcp, MCP_DEFVAL, &defval))
|
||||
goto unlock;
|
||||
|
||||
/* Mask level interrupts to avoid their immediate reactivation after clearing */
|
||||
if (intcon) {
|
||||
need_unmask = true;
|
||||
if (mcp_write(mcp, MCP_GPINTEN, gpinten & ~intcon))
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (mcp_read(mcp, MCP_INTCAP, &intcap))
|
||||
goto unlock;
|
||||
|
||||
/* This clears the interrupt(configurable on S18) */
|
||||
if (mcp_read(mcp, MCP_GPIO, &gpio))
|
||||
goto unlock;
|
||||
@@ -470,9 +478,18 @@ static irqreturn_t mcp23s08_irq(int irq, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
if (need_unmask) {
|
||||
mutex_lock(&mcp->lock);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
||||
unlock:
|
||||
if (need_unmask)
|
||||
if (mcp_write(mcp, MCP_GPINTEN, gpinten))
|
||||
dev_err(mcp->chip.parent, "can't unmask GPINTEN\n");
|
||||
|
||||
mutex_unlock(&mcp->lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -1393,12 +1393,6 @@ static int pistachio_gpio_register(struct pistachio_pinctrl *pctl)
|
||||
dev_err(pctl->dev, "Failed to retrieve IRQ for bank %u\n", i);
|
||||
goto err;
|
||||
}
|
||||
if (!ret) {
|
||||
fwnode_handle_put(child);
|
||||
dev_err(pctl->dev, "No IRQ for bank %u\n", i);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
irq = ret;
|
||||
|
||||
bank = &pctl->gpio_banks[i];
|
||||
|
||||
@@ -2003,6 +2003,115 @@ static int rk3399_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RK3528_DRV_BITS_PER_PIN 8
|
||||
#define RK3528_DRV_PINS_PER_REG 2
|
||||
#define RK3528_DRV_GPIO0_OFFSET 0x100
|
||||
#define RK3528_DRV_GPIO1_OFFSET 0x20120
|
||||
#define RK3528_DRV_GPIO2_OFFSET 0x30160
|
||||
#define RK3528_DRV_GPIO3_OFFSET 0x20190
|
||||
#define RK3528_DRV_GPIO4_OFFSET 0x101C0
|
||||
|
||||
static int rk3528_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
|
||||
int pin_num, struct regmap **regmap,
|
||||
int *reg, u8 *bit)
|
||||
{
|
||||
struct rockchip_pinctrl *info = bank->drvdata;
|
||||
|
||||
*regmap = info->regmap_base;
|
||||
|
||||
if (bank->bank_num == 0)
|
||||
*reg = RK3528_DRV_GPIO0_OFFSET;
|
||||
else if (bank->bank_num == 1)
|
||||
*reg = RK3528_DRV_GPIO1_OFFSET;
|
||||
else if (bank->bank_num == 2)
|
||||
*reg = RK3528_DRV_GPIO2_OFFSET;
|
||||
else if (bank->bank_num == 3)
|
||||
*reg = RK3528_DRV_GPIO3_OFFSET;
|
||||
else if (bank->bank_num == 4)
|
||||
*reg = RK3528_DRV_GPIO4_OFFSET;
|
||||
else
|
||||
dev_err(info->dev, "unsupported bank_num %d\n", bank->bank_num);
|
||||
|
||||
*reg += ((pin_num / RK3528_DRV_PINS_PER_REG) * 4);
|
||||
*bit = pin_num % RK3528_DRV_PINS_PER_REG;
|
||||
*bit *= RK3528_DRV_BITS_PER_PIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RK3528_PULL_BITS_PER_PIN 2
|
||||
#define RK3528_PULL_PINS_PER_REG 8
|
||||
#define RK3528_PULL_GPIO0_OFFSET 0x200
|
||||
#define RK3528_PULL_GPIO1_OFFSET 0x20210
|
||||
#define RK3528_PULL_GPIO2_OFFSET 0x30220
|
||||
#define RK3528_PULL_GPIO3_OFFSET 0x20230
|
||||
#define RK3528_PULL_GPIO4_OFFSET 0x10240
|
||||
|
||||
static int rk3528_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
|
||||
int pin_num, struct regmap **regmap,
|
||||
int *reg, u8 *bit)
|
||||
{
|
||||
struct rockchip_pinctrl *info = bank->drvdata;
|
||||
|
||||
*regmap = info->regmap_base;
|
||||
|
||||
if (bank->bank_num == 0)
|
||||
*reg = RK3528_PULL_GPIO0_OFFSET;
|
||||
else if (bank->bank_num == 1)
|
||||
*reg = RK3528_PULL_GPIO1_OFFSET;
|
||||
else if (bank->bank_num == 2)
|
||||
*reg = RK3528_PULL_GPIO2_OFFSET;
|
||||
else if (bank->bank_num == 3)
|
||||
*reg = RK3528_PULL_GPIO3_OFFSET;
|
||||
else if (bank->bank_num == 4)
|
||||
*reg = RK3528_PULL_GPIO4_OFFSET;
|
||||
else
|
||||
dev_err(info->dev, "unsupported bank_num %d\n", bank->bank_num);
|
||||
|
||||
*reg += ((pin_num / RK3528_PULL_PINS_PER_REG) * 4);
|
||||
*bit = pin_num % RK3528_PULL_PINS_PER_REG;
|
||||
*bit *= RK3528_PULL_BITS_PER_PIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RK3528_SMT_BITS_PER_PIN 1
|
||||
#define RK3528_SMT_PINS_PER_REG 8
|
||||
#define RK3528_SMT_GPIO0_OFFSET 0x400
|
||||
#define RK3528_SMT_GPIO1_OFFSET 0x20410
|
||||
#define RK3528_SMT_GPIO2_OFFSET 0x30420
|
||||
#define RK3528_SMT_GPIO3_OFFSET 0x20430
|
||||
#define RK3528_SMT_GPIO4_OFFSET 0x10440
|
||||
|
||||
static int rk3528_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
|
||||
int pin_num,
|
||||
struct regmap **regmap,
|
||||
int *reg, u8 *bit)
|
||||
{
|
||||
struct rockchip_pinctrl *info = bank->drvdata;
|
||||
|
||||
*regmap = info->regmap_base;
|
||||
|
||||
if (bank->bank_num == 0)
|
||||
*reg = RK3528_SMT_GPIO0_OFFSET;
|
||||
else if (bank->bank_num == 1)
|
||||
*reg = RK3528_SMT_GPIO1_OFFSET;
|
||||
else if (bank->bank_num == 2)
|
||||
*reg = RK3528_SMT_GPIO2_OFFSET;
|
||||
else if (bank->bank_num == 3)
|
||||
*reg = RK3528_SMT_GPIO3_OFFSET;
|
||||
else if (bank->bank_num == 4)
|
||||
*reg = RK3528_SMT_GPIO4_OFFSET;
|
||||
else
|
||||
dev_err(info->dev, "unsupported bank_num %d\n", bank->bank_num);
|
||||
|
||||
*reg += ((pin_num / RK3528_SMT_PINS_PER_REG) * 4);
|
||||
*bit = pin_num % RK3528_SMT_PINS_PER_REG;
|
||||
*bit *= RK3528_SMT_BITS_PER_PIN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RK3562_DRV_BITS_PER_PIN 8
|
||||
#define RK3562_DRV_PINS_PER_REG 2
|
||||
#define RK3562_DRV_GPIO0_OFFSET 0x20070
|
||||
@@ -2640,7 +2749,8 @@ static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank,
|
||||
rmask_bits = RK3588_DRV_BITS_PER_PIN;
|
||||
ret = strength;
|
||||
goto config;
|
||||
} else if (ctrl->type == RK3562 ||
|
||||
} else if (ctrl->type == RK3528 ||
|
||||
ctrl->type == RK3562 ||
|
||||
ctrl->type == RK3568) {
|
||||
rmask_bits = RK3568_DRV_BITS_PER_PIN;
|
||||
ret = (1 << (strength + 1)) - 1;
|
||||
@@ -2785,6 +2895,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num)
|
||||
case RK3328:
|
||||
case RK3368:
|
||||
case RK3399:
|
||||
case RK3528:
|
||||
case RK3562:
|
||||
case RK3568:
|
||||
case RK3576:
|
||||
@@ -2846,6 +2957,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
|
||||
case RK3328:
|
||||
case RK3368:
|
||||
case RK3399:
|
||||
case RK3528:
|
||||
case RK3562:
|
||||
case RK3568:
|
||||
case RK3576:
|
||||
@@ -3115,6 +3227,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl,
|
||||
case RK3328:
|
||||
case RK3368:
|
||||
case RK3399:
|
||||
case RK3528:
|
||||
case RK3562:
|
||||
case RK3568:
|
||||
case RK3576:
|
||||
@@ -4237,6 +4350,49 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = {
|
||||
.drv_calc_reg = rk3399_calc_drv_reg_and_bit,
|
||||
};
|
||||
|
||||
static struct rockchip_pin_bank rk3528_pin_banks[] = {
|
||||
PIN_BANK_IOMUX_FLAGS_OFFSET(0, 32, "gpio0",
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
0, 0, 0, 0),
|
||||
PIN_BANK_IOMUX_FLAGS_OFFSET(1, 32, "gpio1",
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
0x20020, 0x20028, 0x20030, 0x20038),
|
||||
PIN_BANK_IOMUX_FLAGS_OFFSET(2, 32, "gpio2",
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
0x30040, 0, 0, 0),
|
||||
PIN_BANK_IOMUX_FLAGS_OFFSET(3, 32, "gpio3",
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
0x20060, 0x20068, 0x20070, 0),
|
||||
PIN_BANK_IOMUX_FLAGS_OFFSET(4, 32, "gpio4",
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
IOMUX_WIDTH_4BIT,
|
||||
0x10080, 0x10088, 0x10090, 0x10098),
|
||||
};
|
||||
|
||||
static struct rockchip_pin_ctrl rk3528_pin_ctrl = {
|
||||
.pin_banks = rk3528_pin_banks,
|
||||
.nr_banks = ARRAY_SIZE(rk3528_pin_banks),
|
||||
.label = "RK3528-GPIO",
|
||||
.type = RK3528,
|
||||
.pull_calc_reg = rk3528_calc_pull_reg_and_bit,
|
||||
.drv_calc_reg = rk3528_calc_drv_reg_and_bit,
|
||||
.schmitt_calc_reg = rk3528_calc_schmitt_reg_and_bit,
|
||||
};
|
||||
|
||||
static struct rockchip_pin_bank rk3562_pin_banks[] = {
|
||||
PIN_BANK_IOMUX_FLAGS_OFFSET(0, 32, "gpio0",
|
||||
IOMUX_WIDTH_4BIT,
|
||||
@@ -4404,6 +4560,8 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = {
|
||||
.data = &rk3368_pin_ctrl },
|
||||
{ .compatible = "rockchip,rk3399-pinctrl",
|
||||
.data = &rk3399_pin_ctrl },
|
||||
{ .compatible = "rockchip,rk3528-pinctrl",
|
||||
.data = &rk3528_pin_ctrl },
|
||||
{ .compatible = "rockchip,rk3562-pinctrl",
|
||||
.data = &rk3562_pin_ctrl },
|
||||
{ .compatible = "rockchip,rk3568-pinctrl",
|
||||
|
||||
@@ -196,6 +196,7 @@ enum rockchip_pinctrl_type {
|
||||
RK3328,
|
||||
RK3368,
|
||||
RK3399,
|
||||
RK3528,
|
||||
RK3562,
|
||||
RK3568,
|
||||
RK3576,
|
||||
|
||||
@@ -281,9 +281,8 @@ static int pxa2xx_build_functions(struct pxa_pinctrl *pctl)
|
||||
for (df = pctl->ppins[i].functions; df->name; df++)
|
||||
if (!pxa2xx_find_function(pctl, df->name, functions))
|
||||
(functions + pctl->nfuncs++)->name = df->name;
|
||||
pctl->functions = devm_kmemdup(pctl->dev, functions,
|
||||
pctl->nfuncs * sizeof(*functions),
|
||||
GFP_KERNEL);
|
||||
pctl->functions = devm_kmemdup_array(pctl->dev, functions, pctl->nfuncs,
|
||||
sizeof(*functions), GFP_KERNEL);
|
||||
if (!pctl->functions)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -314,7 +313,8 @@ static int pxa2xx_build_groups(struct pxa_pinctrl *pctl)
|
||||
pctl->ppins[j].pin.name;
|
||||
func = pctl->functions + i;
|
||||
func->ngroups = ngroups;
|
||||
func->groups = devm_kmemdup(pctl->dev, gtmp, ngroups * sizeof(*gtmp), GFP_KERNEL);
|
||||
func->groups = devm_kmemdup_array(pctl->dev, gtmp, ngroups,
|
||||
sizeof(*gtmp), GFP_KERNEL);
|
||||
if (!func->groups)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -138,10 +138,10 @@ config PINCTRL_MSM8916
|
||||
Qualcomm TLMM block found on the Qualcomm 8916 platform.
|
||||
|
||||
config PINCTRL_MSM8917
|
||||
tristate "Qualcomm 8917 pin controller driver"
|
||||
tristate "Qualcomm 8917/8937 pin controller driver"
|
||||
help
|
||||
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
|
||||
Qualcomm TLMM block found on the Qualcomm MSM8917 platform.
|
||||
Qualcomm TLMM block found on the Qualcomm MSM8917, MSM8937 platform.
|
||||
|
||||
config PINCTRL_MSM8953
|
||||
tristate "Qualcomm 8953 pin controller driver"
|
||||
@@ -437,4 +437,14 @@ config PINCTRL_X1E80100
|
||||
Say Y here to compile statically, or M here to compile it as a module.
|
||||
If unsure, say N.
|
||||
|
||||
config PINCTRL_TLMM_TEST
|
||||
tristate "Qualcomm TLMM test driver"
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
depends on KUNIT
|
||||
help
|
||||
This driver provides test cases for the interrupt capabilities of
|
||||
TLMM driver (pinctrl-msm). Specify a floating gpio to use for testing
|
||||
using the module parameter "gpio" and execute the kunit suite.
|
||||
If unsure, say N.
|
||||
|
||||
endif
|
||||
|
||||
@@ -71,3 +71,4 @@ obj-$(CONFIG_PINCTRL_SM8750) += pinctrl-sm8750.o
|
||||
obj-$(CONFIG_PINCTRL_SC8280XP_LPASS_LPI) += pinctrl-sc8280xp-lpass-lpi.o
|
||||
obj-$(CONFIG_PINCTRL_LPASS_LPI) += pinctrl-lpass-lpi.o
|
||||
obj-$(CONFIG_PINCTRL_X1E80100) += pinctrl-x1e80100.o
|
||||
obj-$(CONFIG_PINCTRL_TLMM_TEST) += tlmm-test.o
|
||||
|
||||
@@ -1045,8 +1045,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
const struct msm_pingroup *g;
|
||||
u32 intr_target_mask = GENMASK(2, 0);
|
||||
unsigned long flags;
|
||||
bool was_enabled;
|
||||
u32 val;
|
||||
u32 val, oldval;
|
||||
|
||||
if (msm_gpio_needs_dual_edge_parent_workaround(d, type)) {
|
||||
set_bit(d->hwirq, pctrl->dual_edge_irqs);
|
||||
@@ -1108,8 +1107,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
* internal circuitry of TLMM, toggling the RAW_STATUS
|
||||
* could cause the INTR_STATUS to be set for EDGE interrupts.
|
||||
*/
|
||||
val = msm_readl_intr_cfg(pctrl, g);
|
||||
was_enabled = val & BIT(g->intr_raw_status_bit);
|
||||
val = oldval = 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);
|
||||
@@ -1162,9 +1160,11 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
/*
|
||||
* The first time we set RAW_STATUS_EN it could trigger an interrupt.
|
||||
* Clear the interrupt. This is safe because we have
|
||||
* IRQCHIP_SET_TYPE_MASKED.
|
||||
* IRQCHIP_SET_TYPE_MASKED. When changing the interrupt type, we could
|
||||
* also still have a non-matching interrupt latched, so clear whenever
|
||||
* making changes to the interrupt configuration.
|
||||
*/
|
||||
if (!was_enabled)
|
||||
if (val != oldval)
|
||||
msm_ack_intr_status(pctrl, g);
|
||||
|
||||
if (test_bit(d->hwirq, pctrl->dual_edge_irqs))
|
||||
|
||||
@@ -539,6 +539,7 @@ enum msm8917_functions {
|
||||
msm_mux_webcam_standby,
|
||||
msm_mux_wsa_io,
|
||||
msm_mux_wsa_irq,
|
||||
msm_mux_wsa_reset,
|
||||
msm_mux__,
|
||||
};
|
||||
|
||||
@@ -1123,6 +1124,10 @@ static const char * const wsa_io_groups[] = {
|
||||
"gpio94", "gpio95",
|
||||
};
|
||||
|
||||
static const char * const wsa_reset_groups[] = {
|
||||
"gpio96",
|
||||
};
|
||||
|
||||
static const char * const blsp_spi8_groups[] = {
|
||||
"gpio96", "gpio97", "gpio98", "gpio99",
|
||||
};
|
||||
@@ -1378,6 +1383,7 @@ static const struct pinfunction msm8917_functions[] = {
|
||||
MSM_PIN_FUNCTION(webcam_standby),
|
||||
MSM_PIN_FUNCTION(wsa_io),
|
||||
MSM_PIN_FUNCTION(wsa_irq),
|
||||
MSM_PIN_FUNCTION(wsa_reset),
|
||||
};
|
||||
|
||||
static const struct msm_pingroup msm8917_groups[] = {
|
||||
@@ -1616,5 +1622,5 @@ static void __exit msm8917_pinctrl_exit(void)
|
||||
}
|
||||
module_exit(msm8917_pinctrl_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Qualcomm msm8917 pinctrl driver");
|
||||
MODULE_DESCRIPTION("Qualcomm msm8917/msm8937 pinctrl driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022,2025, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2023, Linaro Limited
|
||||
*/
|
||||
|
||||
@@ -467,6 +467,7 @@ enum sa8775p_functions {
|
||||
msm_mux_edp2_lcd,
|
||||
msm_mux_edp3_hot,
|
||||
msm_mux_edp3_lcd,
|
||||
msm_mux_egpio,
|
||||
msm_mux_emac0_mcg0,
|
||||
msm_mux_emac0_mcg1,
|
||||
msm_mux_emac0_mcg2,
|
||||
@@ -744,6 +745,13 @@ static const char * const edp3_lcd_groups[] = {
|
||||
"gpio49",
|
||||
};
|
||||
|
||||
static const char *const egpio_groups[] = {
|
||||
"gpio126", "gpio127", "gpio128", "gpio129", "gpio130", "gpio131",
|
||||
"gpio132", "gpio133", "gpio134", "gpio135", "gpio136", "gpio137",
|
||||
"gpio138", "gpio139", "gpio140", "gpio141", "gpio142", "gpio143",
|
||||
"gpio144", "gpio145", "gpio146", "gpio147", "gpio148",
|
||||
};
|
||||
|
||||
static const char * const emac0_mcg0_groups[] = {
|
||||
"gpio12",
|
||||
};
|
||||
@@ -1209,6 +1217,7 @@ static const struct pinfunction sa8775p_functions[] = {
|
||||
MSM_PIN_FUNCTION(edp2_lcd),
|
||||
MSM_PIN_FUNCTION(edp3_hot),
|
||||
MSM_PIN_FUNCTION(edp3_lcd),
|
||||
MSM_PIN_FUNCTION(egpio),
|
||||
MSM_PIN_FUNCTION(emac0_mcg0),
|
||||
MSM_PIN_FUNCTION(emac0_mcg1),
|
||||
MSM_PIN_FUNCTION(emac0_mcg2),
|
||||
@@ -1454,29 +1463,29 @@ static const struct msm_pingroup sa8775p_groups[] = {
|
||||
[123] = PINGROUP(123, hs2_mi2s, phase_flag, _, _, _, _, _, _, _),
|
||||
[124] = PINGROUP(124, hs2_mi2s, phase_flag, _, _, _, _, _, _, _),
|
||||
[125] = PINGROUP(125, hs2_mi2s, phase_flag, _, _, _, _, _, _, _),
|
||||
[126] = PINGROUP(126, _, _, _, _, _, _, _, _, _),
|
||||
[127] = PINGROUP(127, _, _, _, _, _, _, _, _, _),
|
||||
[128] = PINGROUP(128, _, _, _, _, _, _, _, _, _),
|
||||
[129] = PINGROUP(129, _, _, _, _, _, _, _, _, _),
|
||||
[130] = PINGROUP(130, _, _, _, _, _, _, _, _, _),
|
||||
[131] = PINGROUP(131, _, _, _, _, _, _, _, _, _),
|
||||
[132] = PINGROUP(132, _, _, _, _, _, _, _, _, _),
|
||||
[133] = PINGROUP(133, _, _, _, _, _, _, _, _, _),
|
||||
[134] = PINGROUP(134, _, _, _, _, _, _, _, _, _),
|
||||
[135] = PINGROUP(135, _, _, _, _, _, _, _, _, _),
|
||||
[136] = PINGROUP(136, _, _, _, _, _, _, _, _, _),
|
||||
[137] = PINGROUP(137, _, _, _, _, _, _, _, _, _),
|
||||
[138] = PINGROUP(138, _, _, _, _, _, _, _, _, _),
|
||||
[139] = PINGROUP(139, _, _, _, _, _, _, _, _, _),
|
||||
[140] = PINGROUP(140, _, _, _, _, _, _, _, _, _),
|
||||
[141] = PINGROUP(141, _, _, _, _, _, _, _, _, _),
|
||||
[142] = PINGROUP(142, _, _, _, _, _, _, _, _, _),
|
||||
[143] = PINGROUP(143, _, _, _, _, _, _, _, _, _),
|
||||
[144] = PINGROUP(144, dbg_out, _, _, _, _, _, _, _, _),
|
||||
[145] = PINGROUP(145, _, _, _, _, _, _, _, _, _),
|
||||
[146] = PINGROUP(146, _, _, _, _, _, _, _, _, _),
|
||||
[147] = PINGROUP(147, _, _, _, _, _, _, _, _, _),
|
||||
[148] = PINGROUP(148, _, _, _, _, _, _, _, _, _),
|
||||
[126] = PINGROUP(126, _, _, _, _, _, _, _, _, egpio),
|
||||
[127] = PINGROUP(127, _, _, _, _, _, _, _, _, egpio),
|
||||
[128] = PINGROUP(128, _, _, _, _, _, _, _, _, egpio),
|
||||
[129] = PINGROUP(129, _, _, _, _, _, _, _, _, egpio),
|
||||
[130] = PINGROUP(130, _, _, _, _, _, _, _, _, egpio),
|
||||
[131] = PINGROUP(131, _, _, _, _, _, _, _, _, egpio),
|
||||
[132] = PINGROUP(132, _, _, _, _, _, _, _, _, egpio),
|
||||
[133] = PINGROUP(133, _, _, _, _, _, _, _, _, egpio),
|
||||
[134] = PINGROUP(134, _, _, _, _, _, _, _, _, egpio),
|
||||
[135] = PINGROUP(135, _, _, _, _, _, _, _, _, egpio),
|
||||
[136] = PINGROUP(136, _, _, _, _, _, _, _, _, egpio),
|
||||
[137] = PINGROUP(137, _, _, _, _, _, _, _, _, egpio),
|
||||
[138] = PINGROUP(138, _, _, _, _, _, _, _, _, egpio),
|
||||
[139] = PINGROUP(139, _, _, _, _, _, _, _, _, egpio),
|
||||
[140] = PINGROUP(140, _, _, _, _, _, _, _, _, egpio),
|
||||
[141] = PINGROUP(141, _, _, _, _, _, _, _, _, egpio),
|
||||
[142] = PINGROUP(142, _, _, _, _, _, _, _, _, egpio),
|
||||
[143] = PINGROUP(143, _, _, _, _, _, _, _, _, egpio),
|
||||
[144] = PINGROUP(144, dbg_out, _, _, _, _, _, _, _, egpio),
|
||||
[145] = PINGROUP(145, _, _, _, _, _, _, _, _, egpio),
|
||||
[146] = PINGROUP(146, _, _, _, _, _, _, _, _, egpio),
|
||||
[147] = PINGROUP(147, _, _, _, _, _, _, _, _, egpio),
|
||||
[148] = PINGROUP(148, _, _, _, _, _, _, _, _, egpio),
|
||||
[149] = UFS_RESET(ufs_reset, 0x1a2000),
|
||||
[150] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x199000, 15, 0),
|
||||
[151] = SDC_QDSD_PINGROUP(sdc1_clk, 0x199000, 13, 6),
|
||||
@@ -1511,6 +1520,7 @@ static const struct msm_pinctrl_soc_data sa8775p_pinctrl = {
|
||||
.ngpios = 150,
|
||||
.wakeirq_map = sa8775p_pdc_map,
|
||||
.nwakeirq_map = ARRAY_SIZE(sa8775p_pdc_map),
|
||||
.egpio_func = 9,
|
||||
};
|
||||
|
||||
static int sa8775p_pinctrl_probe(struct platform_device *pdev)
|
||||
|
||||
663
drivers/pinctrl/qcom/tlmm-test.c
Normal file
663
drivers/pinctrl/qcom/tlmm-test.c
Normal file
@@ -0,0 +1,663 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2025, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "tlmm-test: " fmt
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
/*
|
||||
* This TLMM test module serves the purpose of validating that the TLMM driver
|
||||
* (pinctrl-msm) delivers expected number of interrupts in response to changing
|
||||
* GPIO state.
|
||||
*
|
||||
* To achieve this without external equipment the test takes a module parameter
|
||||
* "gpio", which the tester is expected to specify an unused and non-connected
|
||||
* pin. The GPIO state is then driven by adjusting the bias of the pin, at
|
||||
* suitable times through the different test cases.
|
||||
*
|
||||
* Upon execution, the test initialization will find the TLMM node (subject to
|
||||
* tlmm_of_match[] allow listing) and create the necessary references
|
||||
* dynamically, rather then relying on e.g. Devicetree and phandles.
|
||||
*/
|
||||
|
||||
#define MSM_PULL_MASK GENMASK(2, 0)
|
||||
#define MSM_PULL_DOWN 1
|
||||
#define MSM_PULL_UP 3
|
||||
#define TLMM_REG_SIZE 0x1000
|
||||
|
||||
static int tlmm_test_gpio = -1;
|
||||
module_param_named(gpio, tlmm_test_gpio, int, 0600);
|
||||
|
||||
static struct {
|
||||
void __iomem *base;
|
||||
void __iomem *reg;
|
||||
int irq;
|
||||
|
||||
u32 low_val;
|
||||
u32 high_val;
|
||||
} tlmm_suite;
|
||||
|
||||
/**
|
||||
* struct tlmm_test_priv - Per-test context
|
||||
* @intr_count: number of times hard handler was hit with TLMM_TEST_COUNT op set
|
||||
* @thread_count: number of times thread handler was hit with TLMM_TEST_COUNT op set
|
||||
* @intr_op: operations to be performed by the hard IRQ handler
|
||||
* @intr_op_remain: number of times the TLMM_TEST_THEN_* operations should be
|
||||
* performed by the hard IRQ handler
|
||||
* @thread_op: operations to be performed by the threaded IRQ handler
|
||||
* @thread_op_remain: number of times the TLMM_TEST_THEN_* operations should
|
||||
* be performed by the threaded IRQ handler
|
||||
*/
|
||||
struct tlmm_test_priv {
|
||||
atomic_t intr_count;
|
||||
atomic_t thread_count;
|
||||
|
||||
unsigned int intr_op;
|
||||
atomic_t intr_op_remain;
|
||||
|
||||
unsigned int thread_op;
|
||||
atomic_t thread_op_remain;
|
||||
};
|
||||
|
||||
/* Operation masks for @intr_op and @thread_op */
|
||||
#define TLMM_TEST_COUNT BIT(0)
|
||||
#define TLMM_TEST_OUTPUT_LOW BIT(1)
|
||||
#define TLMM_TEST_OUTPUT_HIGH BIT(2)
|
||||
#define TLMM_TEST_THEN_HIGH BIT(3)
|
||||
#define TLMM_TEST_THEN_LOW BIT(4)
|
||||
#define TLMM_TEST_WAKE_THREAD BIT(5)
|
||||
|
||||
static void tlmm_output_low(void)
|
||||
{
|
||||
writel(tlmm_suite.low_val, tlmm_suite.reg);
|
||||
readl(tlmm_suite.reg);
|
||||
}
|
||||
|
||||
static void tlmm_output_high(void)
|
||||
{
|
||||
writel(tlmm_suite.high_val, tlmm_suite.reg);
|
||||
readl(tlmm_suite.reg);
|
||||
}
|
||||
|
||||
static irqreturn_t tlmm_test_intr_fn(int irq, void *dev_id)
|
||||
{
|
||||
struct tlmm_test_priv *priv = dev_id;
|
||||
|
||||
if (priv->intr_op & TLMM_TEST_COUNT)
|
||||
atomic_inc(&priv->intr_count);
|
||||
|
||||
if (priv->intr_op & TLMM_TEST_OUTPUT_LOW)
|
||||
tlmm_output_low();
|
||||
if (priv->intr_op & TLMM_TEST_OUTPUT_HIGH)
|
||||
tlmm_output_high();
|
||||
|
||||
if (atomic_dec_if_positive(&priv->intr_op_remain) > 0) {
|
||||
udelay(1);
|
||||
|
||||
if (priv->intr_op & TLMM_TEST_THEN_LOW)
|
||||
tlmm_output_low();
|
||||
if (priv->intr_op & TLMM_TEST_THEN_HIGH)
|
||||
tlmm_output_high();
|
||||
}
|
||||
|
||||
return priv->intr_op & TLMM_TEST_WAKE_THREAD ? IRQ_WAKE_THREAD : IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t tlmm_test_intr_thread_fn(int irq, void *dev_id)
|
||||
{
|
||||
struct tlmm_test_priv *priv = dev_id;
|
||||
|
||||
if (priv->thread_op & TLMM_TEST_COUNT)
|
||||
atomic_inc(&priv->thread_count);
|
||||
|
||||
if (priv->thread_op & TLMM_TEST_OUTPUT_LOW)
|
||||
tlmm_output_low();
|
||||
if (priv->thread_op & TLMM_TEST_OUTPUT_HIGH)
|
||||
tlmm_output_high();
|
||||
|
||||
if (atomic_dec_if_positive(&priv->thread_op_remain) > 0) {
|
||||
udelay(1);
|
||||
if (priv->thread_op & TLMM_TEST_THEN_LOW)
|
||||
tlmm_output_low();
|
||||
if (priv->thread_op & TLMM_TEST_THEN_HIGH)
|
||||
tlmm_output_high();
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void tlmm_test_request_hard_irq(struct kunit *test, unsigned long irqflags)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
int ret;
|
||||
|
||||
ret = request_irq(tlmm_suite.irq, tlmm_test_intr_fn, irqflags, test->name, priv);
|
||||
KUNIT_EXPECT_EQ(test, ret, 0);
|
||||
}
|
||||
|
||||
static void tlmm_test_request_threaded_irq(struct kunit *test, unsigned long irqflags)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
int ret;
|
||||
|
||||
ret = request_threaded_irq(tlmm_suite.irq,
|
||||
tlmm_test_intr_fn, tlmm_test_intr_thread_fn,
|
||||
irqflags, test->name, priv);
|
||||
|
||||
KUNIT_EXPECT_EQ(test, ret, 0);
|
||||
}
|
||||
|
||||
static void tlmm_test_silent(struct kunit *test, unsigned long irqflags)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT;
|
||||
|
||||
/* GPIO line at non-triggering level */
|
||||
if (irqflags == IRQF_TRIGGER_LOW || irqflags == IRQF_TRIGGER_FALLING)
|
||||
tlmm_output_high();
|
||||
else
|
||||
tlmm_output_low();
|
||||
|
||||
tlmm_test_request_hard_irq(test, irqflags);
|
||||
msleep(100);
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that no RISING interrupts are triggered on a silent pin
|
||||
*/
|
||||
static void tlmm_test_silent_rising(struct kunit *test)
|
||||
{
|
||||
tlmm_test_silent(test, IRQF_TRIGGER_RISING);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that no FALLING interrupts are triggered on a silent pin
|
||||
*/
|
||||
static void tlmm_test_silent_falling(struct kunit *test)
|
||||
{
|
||||
tlmm_test_silent(test, IRQF_TRIGGER_FALLING);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that no LOW interrupts are triggered on a silent pin
|
||||
*/
|
||||
static void tlmm_test_silent_low(struct kunit *test)
|
||||
{
|
||||
tlmm_test_silent(test, IRQF_TRIGGER_LOW);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that no HIGH interrupts are triggered on a silent pin
|
||||
*/
|
||||
static void tlmm_test_silent_high(struct kunit *test)
|
||||
{
|
||||
tlmm_test_silent(test, IRQF_TRIGGER_HIGH);
|
||||
}
|
||||
|
||||
/*
|
||||
* Square wave with 10 high pulses, assert that we get 10 rising interrupts
|
||||
*/
|
||||
static void tlmm_test_rising(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
int i;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT;
|
||||
|
||||
tlmm_output_low();
|
||||
|
||||
tlmm_test_request_hard_irq(test, IRQF_TRIGGER_RISING);
|
||||
for (i = 0; i < 10; i++) {
|
||||
tlmm_output_low();
|
||||
msleep(20);
|
||||
tlmm_output_high();
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Square wave with 10 low pulses, assert that we get 10 falling interrupts
|
||||
*/
|
||||
static void tlmm_test_falling(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
int i;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT;
|
||||
|
||||
tlmm_output_high();
|
||||
|
||||
tlmm_test_request_hard_irq(test, IRQF_TRIGGER_FALLING);
|
||||
for (i = 0; i < 10; i++) {
|
||||
tlmm_output_high();
|
||||
msleep(20);
|
||||
tlmm_output_low();
|
||||
msleep(20);
|
||||
}
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drive line low 10 times, handler drives it high to "clear the interrupt
|
||||
* source", assert we get 10 interrupts
|
||||
*/
|
||||
static void tlmm_test_low(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
int i;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_HIGH;
|
||||
atomic_set(&priv->intr_op_remain, 9);
|
||||
|
||||
tlmm_output_high();
|
||||
|
||||
tlmm_test_request_hard_irq(test, IRQF_TRIGGER_LOW);
|
||||
for (i = 0; i < 10; i++) {
|
||||
msleep(20);
|
||||
tlmm_output_low();
|
||||
}
|
||||
msleep(100);
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drive line high 10 times, handler drives it low to "clear the interrupt
|
||||
* source", assert we get 10 interrupts
|
||||
*/
|
||||
static void tlmm_test_high(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
int i;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_LOW;
|
||||
atomic_set(&priv->intr_op_remain, 9);
|
||||
|
||||
tlmm_output_low();
|
||||
|
||||
tlmm_test_request_hard_irq(test, IRQF_TRIGGER_HIGH);
|
||||
for (i = 0; i < 10; i++) {
|
||||
msleep(20);
|
||||
tlmm_output_high();
|
||||
}
|
||||
msleep(100);
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler drives GPIO high to "clear the interrupt source", then low to
|
||||
* simulate a new interrupt, repeated 10 times, assert we get 10 interrupts
|
||||
*/
|
||||
static void tlmm_test_falling_in_handler(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_HIGH | TLMM_TEST_THEN_LOW;
|
||||
atomic_set(&priv->intr_op_remain, 10);
|
||||
|
||||
tlmm_output_high();
|
||||
|
||||
tlmm_test_request_hard_irq(test, IRQF_TRIGGER_FALLING);
|
||||
msleep(20);
|
||||
tlmm_output_low();
|
||||
msleep(100);
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler drives GPIO low to "clear the interrupt source", then high to
|
||||
* simulate a new interrupt, repeated 10 times, assert we get 10 interrupts
|
||||
*/
|
||||
static void tlmm_test_rising_in_handler(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_LOW | TLMM_TEST_THEN_HIGH;
|
||||
atomic_set(&priv->intr_op_remain, 10);
|
||||
|
||||
tlmm_output_low();
|
||||
|
||||
tlmm_test_request_hard_irq(test, IRQF_TRIGGER_RISING);
|
||||
msleep(20);
|
||||
tlmm_output_high();
|
||||
msleep(100);
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Square wave with 10 high pulses, assert that we get 10 rising hard and
|
||||
* 10 threaded interrupts
|
||||
*/
|
||||
static void tlmm_test_thread_rising(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
int i;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_WAKE_THREAD;
|
||||
priv->thread_op = TLMM_TEST_COUNT;
|
||||
|
||||
tlmm_output_low();
|
||||
|
||||
tlmm_test_request_threaded_irq(test, IRQF_TRIGGER_RISING);
|
||||
for (i = 0; i < 10; i++) {
|
||||
tlmm_output_low();
|
||||
msleep(20);
|
||||
tlmm_output_high();
|
||||
msleep(20);
|
||||
}
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->thread_count), 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Square wave with 10 low pulses, assert that we get 10 falling interrupts
|
||||
*/
|
||||
static void tlmm_test_thread_falling(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
int i;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_WAKE_THREAD;
|
||||
priv->thread_op = TLMM_TEST_COUNT;
|
||||
|
||||
tlmm_output_high();
|
||||
|
||||
tlmm_test_request_threaded_irq(test, IRQF_TRIGGER_FALLING);
|
||||
for (i = 0; i < 10; i++) {
|
||||
tlmm_output_high();
|
||||
msleep(20);
|
||||
tlmm_output_low();
|
||||
msleep(20);
|
||||
}
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->thread_count), 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drive line high 10 times, threaded handler drives it low to "clear the
|
||||
* interrupt source", assert we get 10 interrupts
|
||||
*/
|
||||
static void tlmm_test_thread_high(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
int i;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_WAKE_THREAD;
|
||||
priv->thread_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_LOW;
|
||||
|
||||
tlmm_output_low();
|
||||
|
||||
tlmm_test_request_threaded_irq(test, IRQF_TRIGGER_HIGH | IRQF_ONESHOT);
|
||||
for (i = 0; i < 10; i++) {
|
||||
tlmm_output_high();
|
||||
msleep(20);
|
||||
}
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->thread_count), 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Drive line low 10 times, threaded handler drives it high to "clear the
|
||||
* interrupt source", assert we get 10 interrupts
|
||||
*/
|
||||
static void tlmm_test_thread_low(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
int i;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_WAKE_THREAD;
|
||||
priv->thread_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_HIGH;
|
||||
|
||||
tlmm_output_high();
|
||||
|
||||
tlmm_test_request_threaded_irq(test, IRQF_TRIGGER_LOW | IRQF_ONESHOT);
|
||||
for (i = 0; i < 10; i++) {
|
||||
tlmm_output_low();
|
||||
msleep(20);
|
||||
}
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->thread_count), 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler drives GPIO low to "clear the interrupt source", then high in the
|
||||
* threaded handler to simulate a new interrupt, repeated 10 times, assert we
|
||||
* get 10 interrupts
|
||||
*/
|
||||
static void tlmm_test_thread_rising_in_handler(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_LOW | TLMM_TEST_WAKE_THREAD;
|
||||
priv->thread_op = TLMM_TEST_COUNT | TLMM_TEST_THEN_HIGH;
|
||||
atomic_set(&priv->thread_op_remain, 10);
|
||||
|
||||
tlmm_output_low();
|
||||
|
||||
tlmm_test_request_threaded_irq(test, IRQF_TRIGGER_RISING);
|
||||
msleep(20);
|
||||
tlmm_output_high();
|
||||
msleep(100);
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->thread_count), 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handler drives GPIO high to "clear the interrupt source", then low in the
|
||||
* threaded handler to simulate a new interrupt, repeated 10 times, assert we
|
||||
* get 10 interrupts
|
||||
*/
|
||||
static void tlmm_test_thread_falling_in_handler(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT | TLMM_TEST_OUTPUT_HIGH | TLMM_TEST_WAKE_THREAD;
|
||||
priv->thread_op = TLMM_TEST_COUNT | TLMM_TEST_THEN_LOW;
|
||||
atomic_set(&priv->thread_op_remain, 10);
|
||||
|
||||
tlmm_output_high();
|
||||
|
||||
tlmm_test_request_threaded_irq(test, IRQF_TRIGGER_FALLING);
|
||||
msleep(20);
|
||||
tlmm_output_low();
|
||||
msleep(100);
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 10);
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->thread_count), 10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Validate that edge interrupts occurring while irq is disabled is delivered
|
||||
* once the interrupt is reenabled.
|
||||
*/
|
||||
static void tlmm_test_rising_while_disabled(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv = test->priv;
|
||||
unsigned int after_edge;
|
||||
unsigned int before_edge;
|
||||
|
||||
priv->intr_op = TLMM_TEST_COUNT;
|
||||
atomic_set(&priv->thread_op_remain, 10);
|
||||
|
||||
tlmm_output_low();
|
||||
|
||||
tlmm_test_request_hard_irq(test, IRQF_TRIGGER_RISING);
|
||||
msleep(20);
|
||||
|
||||
disable_irq(tlmm_suite.irq);
|
||||
before_edge = atomic_read(&priv->intr_count);
|
||||
|
||||
tlmm_output_high();
|
||||
msleep(20);
|
||||
after_edge = atomic_read(&priv->intr_count);
|
||||
|
||||
msleep(20);
|
||||
enable_irq(tlmm_suite.irq);
|
||||
msleep(20);
|
||||
|
||||
free_irq(tlmm_suite.irq, priv);
|
||||
|
||||
KUNIT_ASSERT_EQ(test, before_edge, 0);
|
||||
KUNIT_ASSERT_EQ(test, after_edge, 0);
|
||||
KUNIT_ASSERT_EQ(test, atomic_read(&priv->intr_count), 1);
|
||||
}
|
||||
|
||||
static int tlmm_test_init(struct kunit *test)
|
||||
{
|
||||
struct tlmm_test_priv *priv;
|
||||
|
||||
priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
|
||||
|
||||
atomic_set(&priv->intr_count, 0);
|
||||
atomic_set(&priv->thread_count, 0);
|
||||
|
||||
atomic_set(&priv->intr_op_remain, 0);
|
||||
atomic_set(&priv->thread_op_remain, 0);
|
||||
|
||||
test->priv = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: When adding compatibles to this list, ensure that TLMM_REG_SIZE and
|
||||
* pull configuration values are supported and correct.
|
||||
*/
|
||||
static const struct of_device_id tlmm_of_match[] = {
|
||||
{ .compatible = "qcom,sc8280xp-tlmm" },
|
||||
{ .compatible = "qcom,x1e80100-tlmm" },
|
||||
{}
|
||||
};
|
||||
|
||||
static int tlmm_test_init_suite(struct kunit_suite *suite)
|
||||
{
|
||||
struct of_phandle_args args = {};
|
||||
struct resource res;
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
if (tlmm_test_gpio < 0) {
|
||||
pr_err("use the tlmm-test.gpio module parameter to specify which GPIO to use\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct device_node *tlmm __free(device_node) = of_find_matching_node(NULL, tlmm_of_match);
|
||||
if (!tlmm) {
|
||||
pr_err("failed to find tlmm node\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(tlmm, 0, &res);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
tlmm_suite.base = ioremap(res.start, resource_size(&res));
|
||||
if (!tlmm_suite.base)
|
||||
return -ENOMEM;
|
||||
|
||||
args.np = tlmm;
|
||||
args.args_count = 2;
|
||||
args.args[0] = tlmm_test_gpio;
|
||||
args.args[1] = 0;
|
||||
|
||||
tlmm_suite.irq = irq_create_of_mapping(&args);
|
||||
if (!tlmm_suite.irq) {
|
||||
pr_err("failed to map TLMM irq %d\n", args.args[0]);
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
tlmm_suite.reg = tlmm_suite.base + tlmm_test_gpio * TLMM_REG_SIZE;
|
||||
val = readl(tlmm_suite.reg) & ~MSM_PULL_MASK;
|
||||
tlmm_suite.low_val = val | MSM_PULL_DOWN;
|
||||
tlmm_suite.high_val = val | MSM_PULL_UP;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unmap:
|
||||
iounmap(tlmm_suite.base);
|
||||
tlmm_suite.base = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void tlmm_test_exit_suite(struct kunit_suite *suite)
|
||||
{
|
||||
irq_dispose_mapping(tlmm_suite.irq);
|
||||
iounmap(tlmm_suite.base);
|
||||
|
||||
tlmm_suite.base = NULL;
|
||||
tlmm_suite.irq = -1;
|
||||
}
|
||||
|
||||
static struct kunit_case tlmm_test_cases[] = {
|
||||
KUNIT_CASE(tlmm_test_silent_rising),
|
||||
KUNIT_CASE(tlmm_test_silent_falling),
|
||||
KUNIT_CASE(tlmm_test_silent_low),
|
||||
KUNIT_CASE(tlmm_test_silent_high),
|
||||
KUNIT_CASE(tlmm_test_rising),
|
||||
KUNIT_CASE(tlmm_test_falling),
|
||||
KUNIT_CASE(tlmm_test_high),
|
||||
KUNIT_CASE(tlmm_test_low),
|
||||
KUNIT_CASE(tlmm_test_rising_in_handler),
|
||||
KUNIT_CASE(tlmm_test_falling_in_handler),
|
||||
KUNIT_CASE(tlmm_test_thread_rising),
|
||||
KUNIT_CASE(tlmm_test_thread_falling),
|
||||
KUNIT_CASE(tlmm_test_thread_high),
|
||||
KUNIT_CASE(tlmm_test_thread_low),
|
||||
KUNIT_CASE(tlmm_test_thread_rising_in_handler),
|
||||
KUNIT_CASE(tlmm_test_thread_falling_in_handler),
|
||||
KUNIT_CASE(tlmm_test_rising_while_disabled),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite tlmm_test_suite = {
|
||||
.name = "tlmm-test",
|
||||
.init = tlmm_test_init,
|
||||
.suite_init = tlmm_test_init_suite,
|
||||
.suite_exit = tlmm_test_exit_suite,
|
||||
.test_cases = tlmm_test_cases,
|
||||
};
|
||||
|
||||
kunit_test_suites(&tlmm_test_suite);
|
||||
|
||||
MODULE_DESCRIPTION("Qualcomm TLMM test");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -246,6 +246,9 @@ static int rza2_gpio_register(struct rza2_pinctrl_priv *priv)
|
||||
int ret;
|
||||
|
||||
chip.label = devm_kasprintf(priv->dev, GFP_KERNEL, "%pOFn", np);
|
||||
if (!chip.label)
|
||||
return -ENOMEM;
|
||||
|
||||
chip.parent = priv->dev;
|
||||
chip.ngpio = priv->npins;
|
||||
|
||||
@@ -256,6 +259,8 @@ static int rza2_gpio_register(struct rza2_pinctrl_priv *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
of_node_put(of_args.np);
|
||||
|
||||
if ((of_args.args[0] != 0) ||
|
||||
(of_args.args[1] != 0) ||
|
||||
(of_args.args[2] != priv->npins)) {
|
||||
|
||||
@@ -318,6 +318,7 @@ struct rzg2l_pinctrl_pin_settings {
|
||||
* @pmc: PMC registers cache
|
||||
* @pfc: PFC registers cache
|
||||
* @iolh: IOLH registers cache
|
||||
* @pupd: PUPD registers cache
|
||||
* @ien: IEN registers cache
|
||||
* @sd_ch: SD_CH registers cache
|
||||
* @eth_poc: ET_POC registers cache
|
||||
@@ -331,6 +332,7 @@ struct rzg2l_pinctrl_reg_cache {
|
||||
u32 *pfc;
|
||||
u32 *iolh[2];
|
||||
u32 *ien[2];
|
||||
u32 *pupd[2];
|
||||
u8 sd_ch[2];
|
||||
u8 eth_poc[2];
|
||||
u8 eth_mode;
|
||||
@@ -2712,6 +2714,11 @@ static int rzg2l_pinctrl_reg_cache_alloc(struct rzg2l_pinctrl *pctrl)
|
||||
if (!cache->ien[i])
|
||||
return -ENOMEM;
|
||||
|
||||
cache->pupd[i] = devm_kcalloc(pctrl->dev, nports, sizeof(*cache->pupd[i]),
|
||||
GFP_KERNEL);
|
||||
if (!cache->pupd[i])
|
||||
return -ENOMEM;
|
||||
|
||||
/* Allocate dedicated cache. */
|
||||
dedicated_cache->iolh[i] = devm_kcalloc(pctrl->dev, n_dedicated_pins,
|
||||
sizeof(*dedicated_cache->iolh[i]),
|
||||
@@ -2756,6 +2763,8 @@ static int rzg2l_gpio_register(struct rzg2l_pinctrl *pctrl)
|
||||
if (ret)
|
||||
return dev_err_probe(pctrl->dev, ret, "Unable to parse gpio-ranges\n");
|
||||
|
||||
of_node_put(of_args.np);
|
||||
|
||||
if (of_args.args[0] != 0 || of_args.args[1] != 0 ||
|
||||
of_args.args[2] != pctrl->data->n_port_pins)
|
||||
return dev_err_probe(pctrl->dev, -EINVAL,
|
||||
@@ -2953,7 +2962,7 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen
|
||||
struct rzg2l_pinctrl_reg_cache *cache = pctrl->cache;
|
||||
|
||||
for (u32 port = 0; port < nports; port++) {
|
||||
bool has_iolh, has_ien;
|
||||
bool has_iolh, has_ien, has_pupd;
|
||||
u32 off, caps;
|
||||
u8 pincnt;
|
||||
u64 cfg;
|
||||
@@ -2965,6 +2974,7 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen
|
||||
caps = FIELD_GET(PIN_CFG_MASK, cfg);
|
||||
has_iolh = !!(caps & (PIN_CFG_IOLH_A | PIN_CFG_IOLH_B | PIN_CFG_IOLH_C));
|
||||
has_ien = !!(caps & PIN_CFG_IEN);
|
||||
has_pupd = !!(caps & PIN_CFG_PUPD);
|
||||
|
||||
if (suspend)
|
||||
RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PFC(off), cache->pfc[port]);
|
||||
@@ -2983,6 +2993,15 @@ static void rzg2l_pinctrl_pm_setup_regs(struct rzg2l_pinctrl *pctrl, bool suspen
|
||||
}
|
||||
}
|
||||
|
||||
if (has_pupd) {
|
||||
RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PUPD(off),
|
||||
cache->pupd[0][port]);
|
||||
if (pincnt >= 4) {
|
||||
RZG2L_PCTRL_REG_ACCESS32(suspend, pctrl->base + PUPD(off),
|
||||
cache->pupd[1][port]);
|
||||
}
|
||||
}
|
||||
|
||||
RZG2L_PCTRL_REG_ACCESS16(suspend, pctrl->base + PM(off), cache->pm[port]);
|
||||
RZG2L_PCTRL_REG_ACCESS8(suspend, pctrl->base + P(off), cache->p[port]);
|
||||
|
||||
@@ -3386,6 +3405,7 @@ static struct platform_driver rzg2l_pinctrl_driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = of_match_ptr(rzg2l_pinctrl_of_table),
|
||||
.pm = pm_sleep_ptr(&rzg2l_pinctrl_pm_ops),
|
||||
.suppress_bind_attrs = true,
|
||||
},
|
||||
.probe = rzg2l_pinctrl_probe,
|
||||
};
|
||||
|
||||
@@ -940,6 +940,8 @@ static int rzv2m_gpio_register(struct rzv2m_pinctrl *pctrl)
|
||||
return ret;
|
||||
}
|
||||
|
||||
of_node_put(of_args.np);
|
||||
|
||||
if (of_args.args[0] != 0 || of_args.args[1] != 0 ||
|
||||
of_args.args[2] != pctrl->data->n_port_pins) {
|
||||
dev_err(pctrl->dev, "gpio-ranges does not match selected SOC\n");
|
||||
|
||||
@@ -40,6 +40,15 @@ static const struct samsung_pin_bank_type exynos5433_bank_type_alive = {
|
||||
.reg_offset = { 0x00, 0x04, 0x08, 0x0c, },
|
||||
};
|
||||
|
||||
/*
|
||||
* Bank type for alive type. Bit fields:
|
||||
* CON: 4, DAT: 1, PUD: 2, DRV: 3
|
||||
*/
|
||||
static const struct samsung_pin_bank_type exynos7870_bank_type_alive = {
|
||||
.fld_width = { 4, 1, 2, 3, },
|
||||
.reg_offset = { 0x00, 0x04, 0x08, 0x0c, },
|
||||
};
|
||||
|
||||
/*
|
||||
* Bank type for non-alive type. Bit fields:
|
||||
* CON: 4, DAT: 1, PUD: 4, DRV: 4, CONPDN: 2, PUDPDN: 4
|
||||
@@ -70,6 +79,174 @@ static const struct samsung_pin_bank_type exynos8895_bank_type_off = {
|
||||
/* Pad retention control code for accessing PMU regmap */
|
||||
static atomic_t exynos_shared_retention_refcnt;
|
||||
|
||||
/* pin banks of exynos2200 pin-controller - ALIVE */
|
||||
static const struct samsung_pin_bank_data exynos2200_pin_banks0[] __initconst = {
|
||||
EXYNOS850_PIN_BANK_EINTW(8, 0x0, "gpa0", 0x00),
|
||||
EXYNOS850_PIN_BANK_EINTW(8, 0x20, "gpa1", 0x04),
|
||||
EXYNOS850_PIN_BANK_EINTW(8, 0x40, "gpa2", 0x08),
|
||||
EXYNOS850_PIN_BANK_EINTW(8, 0x60, "gpa3", 0x0c),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0x80, "gpa4", 0x10),
|
||||
EXYNOS_PIN_BANK_EINTN(4, 0xa0, "gpq0"),
|
||||
EXYNOS_PIN_BANK_EINTN(2, 0xc0, "gpq1"),
|
||||
EXYNOS_PIN_BANK_EINTN(2, 0xe0, "gpq2"),
|
||||
};
|
||||
|
||||
/* pin banks of exynos2200 pin-controller - CMGP */
|
||||
static const struct samsung_pin_bank_data exynos2200_pin_banks1[] __initconst = {
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0x0, "gpm0", 0x00),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0x20, "gpm1", 0x04),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0x40, "gpm2", 0x08),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0x60, "gpm3", 0x0c),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0x80, "gpm4", 0x10),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0xa0, "gpm5", 0x14),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0xc0, "gpm6", 0x18),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0xe0, "gpm7", 0x1c),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0x100, "gpm8", 0x20),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0x120, "gpm9", 0x24),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0x140, "gpm10", 0x28),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0x160, "gpm11", 0x2c),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0x180, "gpm12", 0x30),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0x1a0, "gpm13", 0x34),
|
||||
EXYNOS850_PIN_BANK_EINTW(1, 0x1c0, "gpm14", 0x38),
|
||||
EXYNOS850_PIN_BANK_EINTW(1, 0x1e0, "gpm15", 0x3c),
|
||||
EXYNOS850_PIN_BANK_EINTW(1, 0x200, "gpm16", 0x40),
|
||||
EXYNOS850_PIN_BANK_EINTW(1, 0x220, "gpm17", 0x44),
|
||||
EXYNOS850_PIN_BANK_EINTW(1, 0x240, "gpm20", 0x48),
|
||||
EXYNOS850_PIN_BANK_EINTW(1, 0x260, "gpm21", 0x4c),
|
||||
EXYNOS850_PIN_BANK_EINTW(1, 0x280, "gpm22", 0x50),
|
||||
EXYNOS850_PIN_BANK_EINTW(1, 0x2a0, "gpm23", 0x54),
|
||||
EXYNOS850_PIN_BANK_EINTW(1, 0x2c0, "gpm24", 0x58),
|
||||
};
|
||||
|
||||
/* pin banks of exynos2200 pin-controller - HSI1 */
|
||||
static const struct samsung_pin_bank_data exynos2200_pin_banks2[] __initconst = {
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x0, "gpf0", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos2200 pin-controller - UFS */
|
||||
static const struct samsung_pin_bank_data exynos2200_pin_banks3[] __initconst = {
|
||||
EXYNOS850_PIN_BANK_EINTG(7, 0x0, "gpf1", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos2200 pin-controller - HSI1UFS */
|
||||
static const struct samsung_pin_bank_data exynos2200_pin_banks4[] __initconst = {
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x0, "gpf2", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos2200 pin-controller - PERIC0 */
|
||||
static const struct samsung_pin_bank_data exynos2200_pin_banks5[] __initconst = {
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x0, "gpb0", 0x00),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x20, "gpb1", 0x04),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x40, "gpb2", 0x08),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x60, "gpb3", 0x0c),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x80, "gpp4", 0x10),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0xa0, "gpc0", 0x14),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0xc0, "gpc1", 0x18),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0xe0, "gpc2", 0x1c),
|
||||
EXYNOS850_PIN_BANK_EINTG(7, 0x100, "gpg1", 0x20),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x120, "gpg2", 0x24),
|
||||
};
|
||||
|
||||
/* pin banks of exynos2200 pin-controller - PERIC1 */
|
||||
static const struct samsung_pin_bank_data exynos2200_pin_banks6[] __initconst = {
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x0, "gpp7", 0x00),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x20, "gpp8", 0x04),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x40, "gpp9", 0x08),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x60, "gpp10", 0x0c),
|
||||
};
|
||||
|
||||
/* pin banks of exynos2200 pin-controller - PERIC2 */
|
||||
static const struct samsung_pin_bank_data exynos2200_pin_banks7[] __initconst = {
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x0, "gpp0", 0x00),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x20, "gpp1", 0x04),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x40, "gpp2", 0x08),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x60, "gpp3", 0x0c),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x80, "gpp5", 0x10),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0xa0, "gpp6", 0x14),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0xc0, "gpp11", 0x18),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0xe0, "gpc3", 0x1c),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x100, "gpc4", 0x20),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x120, "gpc5", 0x24),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x140, "gpc6", 0x28),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x160, "gpc7", 0x2c),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x180, "gpc8", 0x30),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x1a0, "gpc9", 0x34),
|
||||
EXYNOS850_PIN_BANK_EINTG(5, 0x1c0, "gpg0", 0x38),
|
||||
};
|
||||
|
||||
/* pin banks of exynos2200 pin-controller - VTS */
|
||||
static const struct samsung_pin_bank_data exynos2200_pin_banks8[] __initconst = {
|
||||
EXYNOS850_PIN_BANK_EINTG(7, 0x0, "gpv0", 0x00),
|
||||
};
|
||||
|
||||
static const struct samsung_pin_ctrl exynos2200_pin_ctrl[] = {
|
||||
{
|
||||
/* pin-controller instance 0 ALIVE data */
|
||||
.pin_banks = exynos2200_pin_banks0,
|
||||
.nr_banks = ARRAY_SIZE(exynos2200_pin_banks0),
|
||||
.eint_gpio_init = exynos_eint_gpio_init,
|
||||
.eint_wkup_init = exynos_eint_wkup_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
}, {
|
||||
/* pin-controller instance 1 CMGP data */
|
||||
.pin_banks = exynos2200_pin_banks1,
|
||||
.nr_banks = ARRAY_SIZE(exynos2200_pin_banks1),
|
||||
.eint_gpio_init = exynos_eint_gpio_init,
|
||||
.eint_wkup_init = exynos_eint_wkup_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
}, {
|
||||
/* pin-controller instance 2 HSI1 data */
|
||||
.pin_banks = exynos2200_pin_banks2,
|
||||
.nr_banks = ARRAY_SIZE(exynos2200_pin_banks2),
|
||||
}, {
|
||||
/* pin-controller instance 3 UFS data */
|
||||
.pin_banks = exynos2200_pin_banks3,
|
||||
.nr_banks = ARRAY_SIZE(exynos2200_pin_banks3),
|
||||
.eint_gpio_init = exynos_eint_gpio_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
}, {
|
||||
/* pin-controller instance 4 HSI1UFS data */
|
||||
.pin_banks = exynos2200_pin_banks4,
|
||||
.nr_banks = ARRAY_SIZE(exynos2200_pin_banks4),
|
||||
.eint_gpio_init = exynos_eint_gpio_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
}, {
|
||||
/* pin-controller instance 5 PERIC0 data */
|
||||
.pin_banks = exynos2200_pin_banks5,
|
||||
.nr_banks = ARRAY_SIZE(exynos2200_pin_banks5),
|
||||
.eint_gpio_init = exynos_eint_gpio_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
}, {
|
||||
/* pin-controller instance 6 PERIC1 data */
|
||||
.pin_banks = exynos2200_pin_banks6,
|
||||
.nr_banks = ARRAY_SIZE(exynos2200_pin_banks6),
|
||||
.eint_gpio_init = exynos_eint_gpio_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
}, {
|
||||
/* pin-controller instance 7 PERIC2 data */
|
||||
.pin_banks = exynos2200_pin_banks7,
|
||||
.nr_banks = ARRAY_SIZE(exynos2200_pin_banks7),
|
||||
.eint_gpio_init = exynos_eint_gpio_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
}, {
|
||||
/* pin-controller instance 8 VTS data */
|
||||
.pin_banks = exynos2200_pin_banks8,
|
||||
.nr_banks = ARRAY_SIZE(exynos2200_pin_banks8),
|
||||
},
|
||||
};
|
||||
|
||||
const struct samsung_pinctrl_of_match_data exynos2200_of_data __initconst = {
|
||||
.ctrl = exynos2200_pin_ctrl,
|
||||
.num_ctrl = ARRAY_SIZE(exynos2200_pin_ctrl),
|
||||
};
|
||||
|
||||
/* pin banks of exynos5433 pin-controller - ALIVE */
|
||||
static const struct samsung_pin_bank_data exynos5433_pin_banks0[] __initconst = {
|
||||
/* Must start with EINTG banks, ordered by EINT group number. */
|
||||
@@ -450,6 +627,136 @@ const struct samsung_pinctrl_of_match_data exynos7_of_data __initconst = {
|
||||
.num_ctrl = ARRAY_SIZE(exynos7_pin_ctrl),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7870 pin-controller 0 (ALIVE) */
|
||||
static const struct samsung_pin_bank_data exynos7870_pin_banks0[] __initconst = {
|
||||
EXYNOS7870_PIN_BANK_EINTN(6, 0x000, "etc0"),
|
||||
EXYNOS7870_PIN_BANK_EINTN(3, 0x020, "etc1"),
|
||||
EXYNOS7870_PIN_BANK_EINTW(8, 0x040, "gpa0", 0x00),
|
||||
EXYNOS7870_PIN_BANK_EINTW(8, 0x060, "gpa1", 0x04),
|
||||
EXYNOS7870_PIN_BANK_EINTW(8, 0x080, "gpa2", 0x08),
|
||||
EXYNOS7870_PIN_BANK_EINTN(2, 0x0c0, "gpq0"),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7870 pin-controller 1 (DISPAUD) */
|
||||
static const struct samsung_pin_bank_data exynos7870_pin_banks1[] __initconst = {
|
||||
EXYNOS8895_PIN_BANK_EINTG(4, 0x000, "gpz0", 0x00),
|
||||
EXYNOS8895_PIN_BANK_EINTG(6, 0x020, "gpz1", 0x04),
|
||||
EXYNOS8895_PIN_BANK_EINTG(4, 0x040, "gpz2", 0x08),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7870 pin-controller 2 (ESE) */
|
||||
static const struct samsung_pin_bank_data exynos7870_pin_banks2[] __initconst = {
|
||||
EXYNOS8895_PIN_BANK_EINTG(5, 0x000, "gpc7", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7870 pin-controller 3 (FSYS) */
|
||||
static const struct samsung_pin_bank_data exynos7870_pin_banks3[] __initconst = {
|
||||
EXYNOS8895_PIN_BANK_EINTG(3, 0x000, "gpr0", 0x00),
|
||||
EXYNOS8895_PIN_BANK_EINTG(8, 0x020, "gpr1", 0x04),
|
||||
EXYNOS8895_PIN_BANK_EINTG(2, 0x040, "gpr2", 0x08),
|
||||
EXYNOS8895_PIN_BANK_EINTG(4, 0x060, "gpr3", 0x0c),
|
||||
EXYNOS8895_PIN_BANK_EINTG(6, 0x080, "gpr4", 0x10),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7870 pin-controller 4 (MIF) */
|
||||
static const struct samsung_pin_bank_data exynos7870_pin_banks4[] __initconst = {
|
||||
EXYNOS8895_PIN_BANK_EINTG(2, 0x000, "gpm0", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7870 pin-controller 5 (NFC) */
|
||||
static const struct samsung_pin_bank_data exynos7870_pin_banks5[] __initconst = {
|
||||
EXYNOS8895_PIN_BANK_EINTG(4, 0x000, "gpc2", 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7870 pin-controller 6 (TOP) */
|
||||
static const struct samsung_pin_bank_data exynos7870_pin_banks6[] __initconst = {
|
||||
EXYNOS8895_PIN_BANK_EINTG(4, 0x000, "gpb0", 0x00),
|
||||
EXYNOS8895_PIN_BANK_EINTG(3, 0x020, "gpc0", 0x04),
|
||||
EXYNOS8895_PIN_BANK_EINTG(4, 0x040, "gpc1", 0x08),
|
||||
EXYNOS8895_PIN_BANK_EINTG(4, 0x060, "gpc4", 0x0c),
|
||||
EXYNOS8895_PIN_BANK_EINTG(2, 0x080, "gpc5", 0x10),
|
||||
EXYNOS8895_PIN_BANK_EINTG(4, 0x0a0, "gpc6", 0x14),
|
||||
EXYNOS8895_PIN_BANK_EINTG(2, 0x0c0, "gpc8", 0x18),
|
||||
EXYNOS8895_PIN_BANK_EINTG(2, 0x0e0, "gpc9", 0x1c),
|
||||
EXYNOS8895_PIN_BANK_EINTG(7, 0x100, "gpd1", 0x20),
|
||||
EXYNOS8895_PIN_BANK_EINTG(6, 0x120, "gpd2", 0x24),
|
||||
EXYNOS8895_PIN_BANK_EINTG(8, 0x140, "gpd3", 0x28),
|
||||
EXYNOS8895_PIN_BANK_EINTG(7, 0x160, "gpd4", 0x2c),
|
||||
EXYNOS8895_PIN_BANK_EINTG(3, 0x1a0, "gpe0", 0x34),
|
||||
EXYNOS8895_PIN_BANK_EINTG(4, 0x1c0, "gpf0", 0x38),
|
||||
EXYNOS8895_PIN_BANK_EINTG(2, 0x1e0, "gpf1", 0x3c),
|
||||
EXYNOS8895_PIN_BANK_EINTG(2, 0x200, "gpf2", 0x40),
|
||||
EXYNOS8895_PIN_BANK_EINTG(4, 0x220, "gpf3", 0x44),
|
||||
EXYNOS8895_PIN_BANK_EINTG(5, 0x240, "gpf4", 0x48),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7870 pin-controller 7 (TOUCH) */
|
||||
static const struct samsung_pin_bank_data exynos7870_pin_banks7[] __initconst = {
|
||||
EXYNOS8895_PIN_BANK_EINTG(3, 0x000, "gpc3", 0x00),
|
||||
};
|
||||
|
||||
static const struct samsung_pin_ctrl exynos7870_pin_ctrl[] __initconst = {
|
||||
{
|
||||
/* pin-controller instance 0 Alive data */
|
||||
.pin_banks = exynos7870_pin_banks0,
|
||||
.nr_banks = ARRAY_SIZE(exynos7870_pin_banks0),
|
||||
.eint_wkup_init = exynos_eint_wkup_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
}, {
|
||||
/* pin-controller instance 1 DISPAUD data */
|
||||
.pin_banks = exynos7870_pin_banks1,
|
||||
.nr_banks = ARRAY_SIZE(exynos7870_pin_banks1),
|
||||
}, {
|
||||
/* pin-controller instance 2 ESE data */
|
||||
.pin_banks = exynos7870_pin_banks2,
|
||||
.nr_banks = ARRAY_SIZE(exynos7870_pin_banks2),
|
||||
.eint_gpio_init = exynos_eint_gpio_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
}, {
|
||||
/* pin-controller instance 3 FSYS data */
|
||||
.pin_banks = exynos7870_pin_banks3,
|
||||
.nr_banks = ARRAY_SIZE(exynos7870_pin_banks3),
|
||||
.eint_gpio_init = exynos_eint_gpio_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
}, {
|
||||
/* pin-controller instance 4 MIF data */
|
||||
.pin_banks = exynos7870_pin_banks4,
|
||||
.nr_banks = ARRAY_SIZE(exynos7870_pin_banks4),
|
||||
.eint_gpio_init = exynos_eint_gpio_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
}, {
|
||||
/* pin-controller instance 5 NFC data */
|
||||
.pin_banks = exynos7870_pin_banks5,
|
||||
.nr_banks = ARRAY_SIZE(exynos7870_pin_banks5),
|
||||
.eint_gpio_init = exynos_eint_gpio_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
}, {
|
||||
/* pin-controller instance 6 TOP data */
|
||||
.pin_banks = exynos7870_pin_banks6,
|
||||
.nr_banks = ARRAY_SIZE(exynos7870_pin_banks6),
|
||||
.eint_gpio_init = exynos_eint_gpio_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
}, {
|
||||
/* pin-controller instance 7 TOUCH data */
|
||||
.pin_banks = exynos7870_pin_banks7,
|
||||
.nr_banks = ARRAY_SIZE(exynos7870_pin_banks7),
|
||||
.eint_gpio_init = exynos_eint_gpio_init,
|
||||
.suspend = exynos_pinctrl_suspend,
|
||||
.resume = exynos_pinctrl_resume,
|
||||
},
|
||||
};
|
||||
|
||||
const struct samsung_pinctrl_of_match_data exynos7870_of_data __initconst = {
|
||||
.ctrl = exynos7870_pin_ctrl,
|
||||
.num_ctrl = ARRAY_SIZE(exynos7870_pin_ctrl),
|
||||
};
|
||||
|
||||
/* pin banks of exynos7885 pin-controller 0 (ALIVE) */
|
||||
static const struct samsung_pin_bank_data exynos7885_pin_banks0[] __initconst = {
|
||||
EXYNOS_PIN_BANK_EINTN(3, 0x000, "etc0"),
|
||||
@@ -1370,83 +1677,83 @@ const struct samsung_pinctrl_of_match_data fsd_of_data __initconst = {
|
||||
|
||||
/* pin banks of gs101 pin-controller (ALIVE) */
|
||||
static const struct samsung_pin_bank_data gs101_pin_alive[] = {
|
||||
EXYNOS850_PIN_BANK_EINTW(8, 0x0, "gpa0", 0x00),
|
||||
EXYNOS850_PIN_BANK_EINTW(7, 0x20, "gpa1", 0x04),
|
||||
EXYNOS850_PIN_BANK_EINTW(5, 0x40, "gpa2", 0x08),
|
||||
EXYNOS850_PIN_BANK_EINTW(4, 0x60, "gpa3", 0x0c),
|
||||
EXYNOS850_PIN_BANK_EINTW(4, 0x80, "gpa4", 0x10),
|
||||
EXYNOS850_PIN_BANK_EINTW(7, 0xa0, "gpa5", 0x14),
|
||||
EXYNOS850_PIN_BANK_EINTW(8, 0xc0, "gpa9", 0x18),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0xe0, "gpa10", 0x1c),
|
||||
GS101_PIN_BANK_EINTW(8, 0x0, "gpa0", 0x00, 0x00),
|
||||
GS101_PIN_BANK_EINTW(7, 0x20, "gpa1", 0x04, 0x08),
|
||||
GS101_PIN_BANK_EINTW(5, 0x40, "gpa2", 0x08, 0x10),
|
||||
GS101_PIN_BANK_EINTW(4, 0x60, "gpa3", 0x0c, 0x18),
|
||||
GS101_PIN_BANK_EINTW(4, 0x80, "gpa4", 0x10, 0x1c),
|
||||
GS101_PIN_BANK_EINTW(7, 0xa0, "gpa5", 0x14, 0x20),
|
||||
GS101_PIN_BANK_EINTW(8, 0xc0, "gpa9", 0x18, 0x28),
|
||||
GS101_PIN_BANK_EINTW(2, 0xe0, "gpa10", 0x1c, 0x30),
|
||||
};
|
||||
|
||||
/* pin banks of gs101 pin-controller (FAR_ALIVE) */
|
||||
static const struct samsung_pin_bank_data gs101_pin_far_alive[] = {
|
||||
EXYNOS850_PIN_BANK_EINTW(8, 0x0, "gpa6", 0x00),
|
||||
EXYNOS850_PIN_BANK_EINTW(4, 0x20, "gpa7", 0x04),
|
||||
EXYNOS850_PIN_BANK_EINTW(8, 0x40, "gpa8", 0x08),
|
||||
EXYNOS850_PIN_BANK_EINTW(2, 0x60, "gpa11", 0x0c),
|
||||
GS101_PIN_BANK_EINTW(8, 0x0, "gpa6", 0x00, 0x00),
|
||||
GS101_PIN_BANK_EINTW(4, 0x20, "gpa7", 0x04, 0x08),
|
||||
GS101_PIN_BANK_EINTW(8, 0x40, "gpa8", 0x08, 0x0c),
|
||||
GS101_PIN_BANK_EINTW(2, 0x60, "gpa11", 0x0c, 0x14),
|
||||
};
|
||||
|
||||
/* pin banks of gs101 pin-controller (GSACORE) */
|
||||
static const struct samsung_pin_bank_data gs101_pin_gsacore[] = {
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x0, "gps0", 0x00),
|
||||
EXYNOS850_PIN_BANK_EINTG(8, 0x20, "gps1", 0x04),
|
||||
EXYNOS850_PIN_BANK_EINTG(3, 0x40, "gps2", 0x08),
|
||||
GS101_PIN_BANK_EINTG(2, 0x0, "gps0", 0x00, 0x00),
|
||||
GS101_PIN_BANK_EINTG(8, 0x20, "gps1", 0x04, 0x04),
|
||||
GS101_PIN_BANK_EINTG(3, 0x40, "gps2", 0x08, 0x0c),
|
||||
};
|
||||
|
||||
/* pin banks of gs101 pin-controller (GSACTRL) */
|
||||
static const struct samsung_pin_bank_data gs101_pin_gsactrl[] = {
|
||||
EXYNOS850_PIN_BANK_EINTW(6, 0x0, "gps3", 0x00),
|
||||
GS101_PIN_BANK_EINTW(6, 0x0, "gps3", 0x00, 0x00),
|
||||
};
|
||||
|
||||
/* pin banks of gs101 pin-controller (PERIC0) */
|
||||
static const struct samsung_pin_bank_data gs101_pin_peric0[] = {
|
||||
EXYNOS850_PIN_BANK_EINTG(5, 0x0, "gpp0", 0x00),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x20, "gpp1", 0x04),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x40, "gpp2", 0x08),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x60, "gpp3", 0x0c),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x80, "gpp4", 0x10),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0xa0, "gpp5", 0x14),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0xc0, "gpp6", 0x18),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0xe0, "gpp7", 0x1c),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x100, "gpp8", 0x20),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x120, "gpp9", 0x24),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x140, "gpp10", 0x28),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x160, "gpp11", 0x2c),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x180, "gpp12", 0x30),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x1a0, "gpp13", 0x34),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x1c0, "gpp14", 0x38),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x1e0, "gpp15", 0x3c),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x200, "gpp16", 0x40),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x220, "gpp17", 0x44),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x240, "gpp18", 0x48),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x260, "gpp19", 0x4c),
|
||||
GS101_PIN_BANK_EINTG(5, 0x0, "gpp0", 0x00, 0x00),
|
||||
GS101_PIN_BANK_EINTG(4, 0x20, "gpp1", 0x04, 0x08),
|
||||
GS101_PIN_BANK_EINTG(4, 0x40, "gpp2", 0x08, 0x0c),
|
||||
GS101_PIN_BANK_EINTG(2, 0x60, "gpp3", 0x0c, 0x10),
|
||||
GS101_PIN_BANK_EINTG(4, 0x80, "gpp4", 0x10, 0x14),
|
||||
GS101_PIN_BANK_EINTG(2, 0xa0, "gpp5", 0x14, 0x18),
|
||||
GS101_PIN_BANK_EINTG(4, 0xc0, "gpp6", 0x18, 0x1c),
|
||||
GS101_PIN_BANK_EINTG(2, 0xe0, "gpp7", 0x1c, 0x20),
|
||||
GS101_PIN_BANK_EINTG(4, 0x100, "gpp8", 0x20, 0x24),
|
||||
GS101_PIN_BANK_EINTG(2, 0x120, "gpp9", 0x24, 0x28),
|
||||
GS101_PIN_BANK_EINTG(4, 0x140, "gpp10", 0x28, 0x2c),
|
||||
GS101_PIN_BANK_EINTG(2, 0x160, "gpp11", 0x2c, 0x30),
|
||||
GS101_PIN_BANK_EINTG(4, 0x180, "gpp12", 0x30, 0x34),
|
||||
GS101_PIN_BANK_EINTG(2, 0x1a0, "gpp13", 0x34, 0x38),
|
||||
GS101_PIN_BANK_EINTG(4, 0x1c0, "gpp14", 0x38, 0x3c),
|
||||
GS101_PIN_BANK_EINTG(2, 0x1e0, "gpp15", 0x3c, 0x40),
|
||||
GS101_PIN_BANK_EINTG(4, 0x200, "gpp16", 0x40, 0x44),
|
||||
GS101_PIN_BANK_EINTG(2, 0x220, "gpp17", 0x44, 0x48),
|
||||
GS101_PIN_BANK_EINTG(4, 0x240, "gpp18", 0x48, 0x4c),
|
||||
GS101_PIN_BANK_EINTG(4, 0x260, "gpp19", 0x4c, 0x50),
|
||||
};
|
||||
|
||||
/* pin banks of gs101 pin-controller (PERIC1) */
|
||||
static const struct samsung_pin_bank_data gs101_pin_peric1[] = {
|
||||
EXYNOS850_PIN_BANK_EINTG(8, 0x0, "gpp20", 0x00),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x20, "gpp21", 0x04),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x40, "gpp22", 0x08),
|
||||
EXYNOS850_PIN_BANK_EINTG(8, 0x60, "gpp23", 0x0c),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0x80, "gpp24", 0x10),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0xa0, "gpp25", 0x14),
|
||||
EXYNOS850_PIN_BANK_EINTG(5, 0xc0, "gpp26", 0x18),
|
||||
EXYNOS850_PIN_BANK_EINTG(4, 0xe0, "gpp27", 0x1c),
|
||||
GS101_PIN_BANK_EINTG(8, 0x0, "gpp20", 0x00, 0x00),
|
||||
GS101_PIN_BANK_EINTG(4, 0x20, "gpp21", 0x04, 0x08),
|
||||
GS101_PIN_BANK_EINTG(2, 0x40, "gpp22", 0x08, 0x0c),
|
||||
GS101_PIN_BANK_EINTG(8, 0x60, "gpp23", 0x0c, 0x10),
|
||||
GS101_PIN_BANK_EINTG(4, 0x80, "gpp24", 0x10, 0x18),
|
||||
GS101_PIN_BANK_EINTG(4, 0xa0, "gpp25", 0x14, 0x1c),
|
||||
GS101_PIN_BANK_EINTG(5, 0xc0, "gpp26", 0x18, 0x20),
|
||||
GS101_PIN_BANK_EINTG(4, 0xe0, "gpp27", 0x1c, 0x28),
|
||||
};
|
||||
|
||||
/* pin banks of gs101 pin-controller (HSI1) */
|
||||
static const struct samsung_pin_bank_data gs101_pin_hsi1[] = {
|
||||
EXYNOS850_PIN_BANK_EINTG(6, 0x0, "gph0", 0x00),
|
||||
EXYNOS850_PIN_BANK_EINTG(7, 0x20, "gph1", 0x04),
|
||||
GS101_PIN_BANK_EINTG(6, 0x0, "gph0", 0x00, 0x00),
|
||||
GS101_PIN_BANK_EINTG(7, 0x20, "gph1", 0x04, 0x08),
|
||||
};
|
||||
|
||||
/* pin banks of gs101 pin-controller (HSI2) */
|
||||
static const struct samsung_pin_bank_data gs101_pin_hsi2[] = {
|
||||
EXYNOS850_PIN_BANK_EINTG(6, 0x0, "gph2", 0x00),
|
||||
EXYNOS850_PIN_BANK_EINTG(2, 0x20, "gph3", 0x04),
|
||||
EXYNOS850_PIN_BANK_EINTG(6, 0x40, "gph4", 0x08),
|
||||
GS101_PIN_BANK_EINTG(6, 0x0, "gph2", 0x00, 0x00),
|
||||
GS101_PIN_BANK_EINTG(2, 0x20, "gph3", 0x04, 0x08),
|
||||
GS101_PIN_BANK_EINTG(6, 0x40, "gph4", 0x08, 0x0c),
|
||||
};
|
||||
|
||||
static const struct samsung_pin_ctrl gs101_pin_ctrl[] __initconst = {
|
||||
|
||||
@@ -112,6 +112,25 @@
|
||||
.pctl_res_idx = pctl_idx, \
|
||||
} \
|
||||
|
||||
#define EXYNOS7870_PIN_BANK_EINTN(pins, reg, id) \
|
||||
{ \
|
||||
.type = &exynos7870_bank_type_alive, \
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_NONE, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
#define EXYNOS7870_PIN_BANK_EINTW(pins, reg, id, offs) \
|
||||
{ \
|
||||
.type = &exynos7870_bank_type_alive, \
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_WKUP, \
|
||||
.eint_offset = offs, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
#define EXYNOS850_PIN_BANK_EINTN(pins, reg, id) \
|
||||
{ \
|
||||
.type = &exynos850_bank_type_alive, \
|
||||
@@ -175,6 +194,28 @@
|
||||
.name = id \
|
||||
}
|
||||
|
||||
#define GS101_PIN_BANK_EINTG(pins, reg, id, offs, fltcon_offs) \
|
||||
{ \
|
||||
.type = &exynos850_bank_type_off, \
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_GPIO, \
|
||||
.eint_offset = offs, \
|
||||
.eint_fltcon_offset = fltcon_offs, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
#define GS101_PIN_BANK_EINTW(pins, reg, id, offs, fltcon_offs) \
|
||||
{ \
|
||||
.type = &exynos850_bank_type_alive, \
|
||||
.pctl_offset = reg, \
|
||||
.nr_pins = pins, \
|
||||
.eint_type = EINT_TYPE_WKUP, \
|
||||
.eint_offset = offs, \
|
||||
.eint_fltcon_offset = fltcon_offs, \
|
||||
.name = id \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct exynos_weint_data: irq specific data for all the wakeup interrupts
|
||||
* generated by the external wakeup interrupt controller.
|
||||
|
||||
@@ -1230,6 +1230,7 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
|
||||
bank->eint_con_offset = bdata->eint_con_offset;
|
||||
bank->eint_mask_offset = bdata->eint_mask_offset;
|
||||
bank->eint_pend_offset = bdata->eint_pend_offset;
|
||||
bank->eint_fltcon_offset = bdata->eint_fltcon_offset;
|
||||
bank->name = bdata->name;
|
||||
|
||||
raw_spin_lock_init(&bank->slock);
|
||||
@@ -1469,10 +1470,14 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
|
||||
#ifdef CONFIG_PINCTRL_EXYNOS_ARM64
|
||||
{ .compatible = "google,gs101-pinctrl",
|
||||
.data = &gs101_of_data },
|
||||
{ .compatible = "samsung,exynos2200-pinctrl",
|
||||
.data = &exynos2200_of_data },
|
||||
{ .compatible = "samsung,exynos5433-pinctrl",
|
||||
.data = &exynos5433_of_data },
|
||||
{ .compatible = "samsung,exynos7-pinctrl",
|
||||
.data = &exynos7_of_data },
|
||||
{ .compatible = "samsung,exynos7870-pinctrl",
|
||||
.data = &exynos7870_of_data },
|
||||
{ .compatible = "samsung,exynos7885-pinctrl",
|
||||
.data = &exynos7885_of_data },
|
||||
{ .compatible = "samsung,exynos850-pinctrl",
|
||||
|
||||
@@ -144,6 +144,7 @@ struct samsung_pin_bank_type {
|
||||
* @eint_con_offset: ExynosAuto SoC-specific EINT control register offset of bank.
|
||||
* @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
|
||||
* @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
|
||||
* @eint_fltcon_offset: GS101 SoC-specific EINT filter config register offset.
|
||||
* @name: name to be prefixed for each pin in this pin bank.
|
||||
*/
|
||||
struct samsung_pin_bank_data {
|
||||
@@ -158,6 +159,7 @@ struct samsung_pin_bank_data {
|
||||
u32 eint_con_offset;
|
||||
u32 eint_mask_offset;
|
||||
u32 eint_pend_offset;
|
||||
u32 eint_fltcon_offset;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
@@ -175,6 +177,7 @@ struct samsung_pin_bank_data {
|
||||
* @eint_con_offset: ExynosAuto SoC-specific EINT register or interrupt offset of bank.
|
||||
* @eint_mask_offset: ExynosAuto SoC-specific EINT mask register offset of bank.
|
||||
* @eint_pend_offset: ExynosAuto SoC-specific EINT pend register offset of bank.
|
||||
* @eint_fltcon_offset: GS101 SoC-specific EINT filter config register offset.
|
||||
* @name: name to be prefixed for each pin in this pin bank.
|
||||
* @id: id of the bank, propagated to the pin range.
|
||||
* @pin_base: starting pin number of the bank.
|
||||
@@ -201,6 +204,7 @@ struct samsung_pin_bank {
|
||||
u32 eint_con_offset;
|
||||
u32 eint_mask_offset;
|
||||
u32 eint_pend_offset;
|
||||
u32 eint_fltcon_offset;
|
||||
const char *name;
|
||||
u32 id;
|
||||
|
||||
@@ -373,6 +377,7 @@ struct samsung_pmx_func {
|
||||
};
|
||||
|
||||
/* list of all exported SoC specific data */
|
||||
extern const struct samsung_pinctrl_of_match_data exynos2200_of_data;
|
||||
extern const struct samsung_pinctrl_of_match_data exynos3250_of_data;
|
||||
extern const struct samsung_pinctrl_of_match_data exynos4210_of_data;
|
||||
extern const struct samsung_pinctrl_of_match_data exynos4x12_of_data;
|
||||
@@ -382,6 +387,7 @@ extern const struct samsung_pinctrl_of_match_data exynos5410_of_data;
|
||||
extern const struct samsung_pinctrl_of_match_data exynos5420_of_data;
|
||||
extern const struct samsung_pinctrl_of_match_data exynos5433_of_data;
|
||||
extern const struct samsung_pinctrl_of_match_data exynos7_of_data;
|
||||
extern const struct samsung_pinctrl_of_match_data exynos7870_of_data;
|
||||
extern const struct samsung_pinctrl_of_match_data exynos7885_of_data;
|
||||
extern const struct samsung_pinctrl_of_match_data exynos850_of_data;
|
||||
extern const struct samsung_pinctrl_of_match_data exynos8895_of_data;
|
||||
|
||||
@@ -3,17 +3,21 @@
|
||||
# Sophgo SoC PINCTRL drivers
|
||||
#
|
||||
|
||||
config PINCTRL_SOPHGO_CV18XX
|
||||
bool
|
||||
config PINCTRL_SOPHGO_COMMON
|
||||
tristate
|
||||
select GENERIC_PINCTRL_GROUPS
|
||||
select GENERIC_PINMUX_FUNCTIONS
|
||||
select GENERIC_PINCONF
|
||||
|
||||
config PINCTRL_SOPHGO_CV18XX_OPS
|
||||
bool
|
||||
|
||||
config PINCTRL_SOPHGO_CV1800B
|
||||
tristate "Sophgo CV1800B SoC Pinctrl driver"
|
||||
depends on ARCH_SOPHGO || COMPILE_TEST
|
||||
depends on OF
|
||||
select PINCTRL_SOPHGO_CV18XX
|
||||
select PINCTRL_SOPHGO_COMMON
|
||||
select PINCTRL_SOPHGO_CV18XX_OPS
|
||||
help
|
||||
Say Y to select the pinctrl driver for CV1800B SoC.
|
||||
This pin controller allows selecting the mux function for
|
||||
@@ -24,7 +28,8 @@ config PINCTRL_SOPHGO_CV1812H
|
||||
tristate "Sophgo CV1812H SoC Pinctrl driver"
|
||||
depends on ARCH_SOPHGO || COMPILE_TEST
|
||||
depends on OF
|
||||
select PINCTRL_SOPHGO_CV18XX
|
||||
select PINCTRL_SOPHGO_COMMON
|
||||
select PINCTRL_SOPHGO_CV18XX_OPS
|
||||
help
|
||||
Say Y to select the pinctrl driver for CV1812H SoC.
|
||||
This pin controller allows selecting the mux function for
|
||||
@@ -35,7 +40,8 @@ config PINCTRL_SOPHGO_SG2000
|
||||
tristate "Sophgo SG2000 SoC Pinctrl driver"
|
||||
depends on ARCH_SOPHGO || COMPILE_TEST
|
||||
depends on OF
|
||||
select PINCTRL_SOPHGO_CV18XX
|
||||
select PINCTRL_SOPHGO_COMMON
|
||||
select PINCTRL_SOPHGO_CV18XX_OPS
|
||||
help
|
||||
Say Y to select the pinctrl driver for SG2000 SoC.
|
||||
This pin controller allows selecting the mux function for
|
||||
@@ -46,9 +52,37 @@ config PINCTRL_SOPHGO_SG2002
|
||||
tristate "Sophgo SG2002 SoC Pinctrl driver"
|
||||
depends on ARCH_SOPHGO || COMPILE_TEST
|
||||
depends on OF
|
||||
select PINCTRL_SOPHGO_CV18XX
|
||||
select PINCTRL_SOPHGO_COMMON
|
||||
select PINCTRL_SOPHGO_CV18XX_OPS
|
||||
help
|
||||
Say Y to select the pinctrl driver for SG2002 SoC.
|
||||
This pin controller allows selecting the mux function for
|
||||
each pin. This driver can also be built as a module called
|
||||
pinctrl-sg2002.
|
||||
|
||||
config PINCTRL_SOPHGO_SG2042_OPS
|
||||
bool
|
||||
|
||||
config PINCTRL_SOPHGO_SG2042
|
||||
tristate "Sophgo SG2042 SoC Pinctrl driver"
|
||||
depends on ARCH_SOPHGO || COMPILE_TEST
|
||||
depends on OF
|
||||
select PINCTRL_SOPHGO_COMMON
|
||||
select PINCTRL_SOPHGO_SG2042_OPS
|
||||
help
|
||||
Say Y to select the pinctrl driver for SG2042 SoC.
|
||||
This pin controller allows selecting the mux function for
|
||||
each pin. This driver can also be built as a module called
|
||||
pinctrl-sg2042.
|
||||
|
||||
config PINCTRL_SOPHGO_SG2044
|
||||
tristate "Sophgo SG2044 SoC Pinctrl driver"
|
||||
depends on ARCH_SOPHGO || COMPILE_TEST
|
||||
depends on OF
|
||||
select PINCTRL_SOPHGO_COMMON
|
||||
select PINCTRL_SOPHGO_SG2042_OPS
|
||||
help
|
||||
Say Y to select the pinctrl driver for SG2044 SoC.
|
||||
This pin controller allows selecting the mux function for
|
||||
each pin. This driver can also be built as a module called
|
||||
pinctrl-sg2044.
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-$(CONFIG_PINCTRL_SOPHGO_CV18XX) += pinctrl-cv18xx.o
|
||||
obj-$(CONFIG_PINCTRL_SOPHGO_COMMON) += pinctrl-sophgo.o
|
||||
pinctrl-sophgo-objs += pinctrl-sophgo-common.o
|
||||
pinctrl-sophgo-$(CONFIG_PINCTRL_SOPHGO_CV18XX_OPS) += pinctrl-cv18xx.o
|
||||
pinctrl-sophgo-$(CONFIG_PINCTRL_SOPHGO_SG2042_OPS) += pinctrl-sg2042-ops.o
|
||||
|
||||
obj-$(CONFIG_PINCTRL_SOPHGO_CV1800B) += pinctrl-cv1800b.o
|
||||
obj-$(CONFIG_PINCTRL_SOPHGO_CV1812H) += pinctrl-cv1812h.o
|
||||
obj-$(CONFIG_PINCTRL_SOPHGO_SG2000) += pinctrl-sg2000.o
|
||||
obj-$(CONFIG_PINCTRL_SOPHGO_SG2002) += pinctrl-sg2002.o
|
||||
obj-$(CONFIG_PINCTRL_SOPHGO_SG2042) += pinctrl-sg2042.o
|
||||
obj-$(CONFIG_PINCTRL_SOPHGO_SG2044) += pinctrl-sg2044.o
|
||||
|
||||
@@ -34,8 +34,9 @@ static const char *const cv1800b_power_domain_desc[] = {
|
||||
[VDDIO_SD0_SPI] = "VDDIO_SD0_SPI",
|
||||
};
|
||||
|
||||
static int cv1800b_get_pull_up(struct cv1800_pin *pin, const u32 *psmap)
|
||||
static int cv1800b_get_pull_up(const struct sophgo_pin *sp, const u32 *psmap)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
|
||||
@@ -54,8 +55,9 @@ static int cv1800b_get_pull_up(struct cv1800_pin *pin, const u32 *psmap)
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int cv1800b_get_pull_down(struct cv1800_pin *pin, const u32 *psmap)
|
||||
static int cv1800b_get_pull_down(const struct sophgo_pin *sp, const u32 *psmap)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
|
||||
@@ -108,9 +110,10 @@ static const u32 cv1800b_eth_oc_map[] = {
|
||||
17800
|
||||
};
|
||||
|
||||
static int cv1800b_get_oc_map(struct cv1800_pin *pin, const u32 *psmap,
|
||||
static int cv1800b_get_oc_map(const struct sophgo_pin *sp, const u32 *psmap,
|
||||
const u32 **map)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
|
||||
@@ -153,9 +156,10 @@ static const u32 cv1800b_18od33_3v3_schmitt_map[] = {
|
||||
1100000
|
||||
};
|
||||
|
||||
static int cv1800b_get_schmitt_map(struct cv1800_pin *pin, const u32 *psmap,
|
||||
static int cv1800b_get_schmitt_map(const struct sophgo_pin *sp, const u32 *psmap,
|
||||
const u32 **map)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
|
||||
@@ -177,11 +181,11 @@ static int cv1800b_get_schmitt_map(struct cv1800_pin *pin, const u32 *psmap,
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static const struct cv1800_vddio_cfg_ops cv1800b_vddio_cfg_ops = {
|
||||
static const struct sophgo_vddio_cfg_ops cv1800b_vddio_cfg_ops = {
|
||||
.get_pull_up = cv1800b_get_pull_up,
|
||||
.get_pull_down = cv1800b_get_pull_down,
|
||||
.get_oc_map = cv1800b_get_oc_map,
|
||||
.get_schmitt_map = cv1800b_get_schmitt_map,
|
||||
.get_schmitt_map = cv1800b_get_schmitt_map,
|
||||
};
|
||||
|
||||
static const struct pinctrl_pin_desc cv1800b_pins[] = {
|
||||
@@ -433,13 +437,18 @@ static const struct cv1800_pin cv1800b_pin_data[ARRAY_SIZE(cv1800b_pins)] = {
|
||||
CV1800_PINCONF_AREA_SYS, 0x120, 5),
|
||||
};
|
||||
|
||||
static const struct cv1800_pinctrl_data cv1800b_pindata = {
|
||||
static const struct sophgo_pinctrl_data cv1800b_pindata = {
|
||||
.pins = cv1800b_pins,
|
||||
.pindata = cv1800b_pin_data,
|
||||
.pdnames = cv1800b_power_domain_desc,
|
||||
.vddio_ops = &cv1800b_vddio_cfg_ops,
|
||||
.cfg_ops = &cv1800_cfg_ops,
|
||||
.pctl_ops = &cv1800_pctrl_ops,
|
||||
.pmx_ops = &cv1800_pmx_ops,
|
||||
.pconf_ops = &cv1800_pconf_ops,
|
||||
.npins = ARRAY_SIZE(cv1800b_pins),
|
||||
.npd = ARRAY_SIZE(cv1800b_power_domain_desc),
|
||||
.npds = ARRAY_SIZE(cv1800b_power_domain_desc),
|
||||
.pinsize = sizeof(struct cv1800_pin),
|
||||
};
|
||||
|
||||
static const struct of_device_id cv1800b_pinctrl_ids[] = {
|
||||
@@ -449,7 +458,7 @@ static const struct of_device_id cv1800b_pinctrl_ids[] = {
|
||||
MODULE_DEVICE_TABLE(of, cv1800b_pinctrl_ids);
|
||||
|
||||
static struct platform_driver cv1800b_pinctrl_driver = {
|
||||
.probe = cv1800_pinctrl_probe,
|
||||
.probe = sophgo_pinctrl_probe,
|
||||
.driver = {
|
||||
.name = "cv1800b-pinctrl",
|
||||
.suppress_bind_attrs = true,
|
||||
|
||||
@@ -40,8 +40,9 @@ static const char *const cv1812h_power_domain_desc[] = {
|
||||
[VDDIO_VIVO] = "VDDIO_VIVO",
|
||||
};
|
||||
|
||||
static int cv1812h_get_pull_up(struct cv1800_pin *pin, const u32 *psmap)
|
||||
static int cv1812h_get_pull_up(const struct sophgo_pin *sp, const u32 *psmap)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
|
||||
@@ -60,8 +61,9 @@ static int cv1812h_get_pull_up(struct cv1800_pin *pin, const u32 *psmap)
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int cv1812h_get_pull_down(struct cv1800_pin *pin, const u32 *psmap)
|
||||
static int cv1812h_get_pull_down(const struct sophgo_pin *sp, const u32 *psmap)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
|
||||
@@ -114,9 +116,10 @@ static const u32 cv1812h_eth_oc_map[] = {
|
||||
17800
|
||||
};
|
||||
|
||||
static int cv1812h_get_oc_map(struct cv1800_pin *pin, const u32 *psmap,
|
||||
static int cv1812h_get_oc_map(const struct sophgo_pin *sp, const u32 *psmap,
|
||||
const u32 **map)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
|
||||
@@ -159,9 +162,10 @@ static const u32 cv1812h_18od33_3v3_schmitt_map[] = {
|
||||
1100000
|
||||
};
|
||||
|
||||
static int cv1812h_get_schmitt_map(struct cv1800_pin *pin, const u32 *psmap,
|
||||
static int cv1812h_get_schmitt_map(const struct sophgo_pin *sp, const u32 *psmap,
|
||||
const u32 **map)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
|
||||
@@ -183,11 +187,11 @@ static int cv1812h_get_schmitt_map(struct cv1800_pin *pin, const u32 *psmap,
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static const struct cv1800_vddio_cfg_ops cv1812h_vddio_cfg_ops = {
|
||||
static const struct sophgo_vddio_cfg_ops cv1812h_vddio_cfg_ops = {
|
||||
.get_pull_up = cv1812h_get_pull_up,
|
||||
.get_pull_down = cv1812h_get_pull_down,
|
||||
.get_oc_map = cv1812h_get_oc_map,
|
||||
.get_schmitt_map = cv1812h_get_schmitt_map,
|
||||
.get_schmitt_map = cv1812h_get_schmitt_map,
|
||||
};
|
||||
|
||||
static const struct pinctrl_pin_desc cv1812h_pins[] = {
|
||||
@@ -742,13 +746,18 @@ static const struct cv1800_pin cv1812h_pin_data[ARRAY_SIZE(cv1812h_pins)] = {
|
||||
CV1800_PINCONF_AREA_RTC, 0x028),
|
||||
};
|
||||
|
||||
static const struct cv1800_pinctrl_data cv1812h_pindata = {
|
||||
static const struct sophgo_pinctrl_data cv1812h_pindata = {
|
||||
.pins = cv1812h_pins,
|
||||
.pindata = cv1812h_pin_data,
|
||||
.pdnames = cv1812h_power_domain_desc,
|
||||
.vddio_ops = &cv1812h_vddio_cfg_ops,
|
||||
.cfg_ops = &cv1800_cfg_ops,
|
||||
.pctl_ops = &cv1800_pctrl_ops,
|
||||
.pmx_ops = &cv1800_pmx_ops,
|
||||
.pconf_ops = &cv1800_pconf_ops,
|
||||
.npins = ARRAY_SIZE(cv1812h_pins),
|
||||
.npd = ARRAY_SIZE(cv1812h_power_domain_desc),
|
||||
.npds = ARRAY_SIZE(cv1812h_power_domain_desc),
|
||||
.pinsize = sizeof(struct cv1800_pin),
|
||||
};
|
||||
|
||||
static const struct of_device_id cv1812h_pinctrl_ids[] = {
|
||||
@@ -758,7 +767,7 @@ static const struct of_device_id cv1812h_pinctrl_ids[] = {
|
||||
MODULE_DEVICE_TABLE(of, cv1812h_pinctrl_ids);
|
||||
|
||||
static struct platform_driver cv1812h_pinctrl_driver = {
|
||||
.probe = cv1800_pinctrl_probe,
|
||||
.probe = sophgo_pinctrl_probe,
|
||||
.driver = {
|
||||
.name = "cv1812h-pinctrl",
|
||||
.suppress_bind_attrs = true,
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
@@ -24,35 +22,15 @@
|
||||
|
||||
#include <dt-bindings/pinctrl/pinctrl-cv18xx.h>
|
||||
|
||||
#include "../core.h"
|
||||
#include "../pinctrl-utils.h"
|
||||
#include "../pinconf.h"
|
||||
#include "../pinmux.h"
|
||||
#include "pinctrl-cv18xx.h"
|
||||
|
||||
struct cv1800_pinctrl {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pctl_dev;
|
||||
const struct cv1800_pinctrl_data *data;
|
||||
struct pinctrl_desc pdesc;
|
||||
struct cv1800_priv {
|
||||
u32 *power_cfg;
|
||||
|
||||
struct mutex mutex;
|
||||
raw_spinlock_t lock;
|
||||
|
||||
void __iomem *regs[2];
|
||||
};
|
||||
|
||||
struct cv1800_pin_mux_config {
|
||||
struct cv1800_pin *pin;
|
||||
u32 config;
|
||||
};
|
||||
|
||||
static unsigned int cv1800_dt_get_pin(u32 value)
|
||||
{
|
||||
return value & GENMASK(15, 0);
|
||||
}
|
||||
|
||||
static unsigned int cv1800_dt_get_pin_mux(u32 value)
|
||||
{
|
||||
return (value >> 16) & GENMASK(7, 0);
|
||||
@@ -66,40 +44,28 @@ static unsigned int cv1800_dt_get_pin_mux2(u32 value)
|
||||
#define cv1800_pinctrl_get_component_addr(pctrl, _comp) \
|
||||
((pctrl)->regs[(_comp)->area] + (_comp)->offset)
|
||||
|
||||
static int cv1800_cmp_pin(const void *key, const void *pivot)
|
||||
{
|
||||
const struct cv1800_pin *pin = pivot;
|
||||
int pin_id = (long)key;
|
||||
int pivid = pin->pin;
|
||||
|
||||
return pin_id - pivid;
|
||||
}
|
||||
|
||||
static int cv1800_set_power_cfg(struct cv1800_pinctrl *pctrl,
|
||||
static int cv1800_set_power_cfg(struct sophgo_pinctrl *pctrl,
|
||||
u8 domain, u32 cfg)
|
||||
{
|
||||
if (domain >= pctrl->data->npd)
|
||||
struct cv1800_priv *priv = pctrl->priv_ctrl;
|
||||
|
||||
if (domain >= pctrl->data->npds)
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (pctrl->power_cfg[domain] && pctrl->power_cfg[domain] != cfg)
|
||||
if (priv->power_cfg[domain] && priv->power_cfg[domain] != cfg)
|
||||
return -EINVAL;
|
||||
|
||||
pctrl->power_cfg[domain] = cfg;
|
||||
priv->power_cfg[domain] = cfg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cv1800_get_power_cfg(struct cv1800_pinctrl *pctrl,
|
||||
static int cv1800_get_power_cfg(struct sophgo_pinctrl *pctrl,
|
||||
u8 domain)
|
||||
{
|
||||
return pctrl->power_cfg[domain];
|
||||
}
|
||||
struct cv1800_priv *priv = pctrl->priv_ctrl;
|
||||
|
||||
static struct cv1800_pin *cv1800_get_pin(struct cv1800_pinctrl *pctrl,
|
||||
unsigned long pin)
|
||||
{
|
||||
return bsearch((void *)pin, pctrl->data->pindata, pctrl->data->npins,
|
||||
sizeof(struct cv1800_pin), cv1800_cmp_pin);
|
||||
return priv->power_cfg[domain];
|
||||
}
|
||||
|
||||
#define PIN_BGA_ID_OFFSET 8
|
||||
@@ -112,7 +78,7 @@ static const char *const io_type_desc[] = {
|
||||
"ETH"
|
||||
};
|
||||
|
||||
static const char *cv1800_get_power_cfg_desc(struct cv1800_pinctrl *pctrl,
|
||||
static const char *cv1800_get_power_cfg_desc(struct sophgo_pinctrl *pctrl,
|
||||
u8 domain)
|
||||
{
|
||||
return pctrl->data->pdnames[domain];
|
||||
@@ -121,53 +87,57 @@ static const char *cv1800_get_power_cfg_desc(struct cv1800_pinctrl *pctrl,
|
||||
static void cv1800_pctrl_dbg_show(struct pinctrl_dev *pctldev,
|
||||
struct seq_file *seq, unsigned int pin_id)
|
||||
{
|
||||
struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
|
||||
struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct cv1800_priv *priv = pctrl->priv_ctrl;
|
||||
const struct sophgo_pin *sp = sophgo_get_pin(pctrl, pin_id);
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
u32 pin_hwid = pin->pin.id;
|
||||
u32 value;
|
||||
void __iomem *reg;
|
||||
|
||||
if (pin->pin >> PIN_BGA_ID_OFFSET)
|
||||
if (pin_hwid >> PIN_BGA_ID_OFFSET)
|
||||
seq_printf(seq, "pos: %c%u ",
|
||||
'A' + (pin->pin >> PIN_BGA_ID_OFFSET) - 1,
|
||||
pin->pin & PIN_BGA_ID_MASK);
|
||||
'A' + (pin_hwid >> PIN_BGA_ID_OFFSET) - 1,
|
||||
pin_hwid & PIN_BGA_ID_MASK);
|
||||
else
|
||||
seq_printf(seq, "pos: %u ", pin->pin);
|
||||
seq_printf(seq, "pos: %u ", pin_hwid);
|
||||
|
||||
seq_printf(seq, "power-domain: %s ",
|
||||
cv1800_get_power_cfg_desc(pctrl, pin->power_domain));
|
||||
seq_printf(seq, "type: %s ", io_type_desc[type]);
|
||||
|
||||
reg = cv1800_pinctrl_get_component_addr(pctrl, &pin->mux);
|
||||
reg = cv1800_pinctrl_get_component_addr(priv, &pin->mux);
|
||||
value = readl(reg);
|
||||
seq_printf(seq, "mux: 0x%08x ", value);
|
||||
|
||||
if (pin->flags & CV1800_PIN_HAVE_MUX2) {
|
||||
reg = cv1800_pinctrl_get_component_addr(pctrl, &pin->mux2);
|
||||
if (pin->pin.flags & CV1800_PIN_HAVE_MUX2) {
|
||||
reg = cv1800_pinctrl_get_component_addr(priv, &pin->mux2);
|
||||
value = readl(reg);
|
||||
seq_printf(seq, "mux2: 0x%08x ", value);
|
||||
}
|
||||
|
||||
if (type == IO_TYPE_1V8_ONLY || type == IO_TYPE_1V8_OR_3V3) {
|
||||
reg = cv1800_pinctrl_get_component_addr(pctrl, &pin->conf);
|
||||
reg = cv1800_pinctrl_get_component_addr(priv, &pin->conf);
|
||||
value = readl(reg);
|
||||
seq_printf(seq, "conf: 0x%08x ", value);
|
||||
}
|
||||
}
|
||||
|
||||
static int cv1800_verify_pinmux_config(const struct cv1800_pin_mux_config *config)
|
||||
static int cv1800_verify_pinmux_config(const struct sophgo_pin_mux_config *config)
|
||||
{
|
||||
struct cv1800_pin *pin = sophgo_to_cv1800_pin(config->pin);
|
||||
unsigned int mux = cv1800_dt_get_pin_mux(config->config);
|
||||
unsigned int mux2 = cv1800_dt_get_pin_mux2(config->config);
|
||||
|
||||
if (mux > config->pin->mux.max)
|
||||
if (mux > pin->mux.max)
|
||||
return -EINVAL;
|
||||
|
||||
if (config->pin->flags & CV1800_PIN_HAVE_MUX2) {
|
||||
if (mux != config->pin->mux2.pfunc)
|
||||
if (pin->pin.flags & CV1800_PIN_HAVE_MUX2) {
|
||||
if (mux != pin->mux2.pfunc)
|
||||
return -EINVAL;
|
||||
|
||||
if (mux2 > config->pin->mux2.max)
|
||||
if (mux2 > pin->mux2.max)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (mux2 != PIN_MUX_INVALD)
|
||||
@@ -177,9 +147,10 @@ static int cv1800_verify_pinmux_config(const struct cv1800_pin_mux_config *confi
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cv1800_verify_pin_group(const struct cv1800_pin_mux_config *mux,
|
||||
unsigned long npins)
|
||||
static int cv1800_verify_pin_group(const struct sophgo_pin_mux_config *mux,
|
||||
unsigned int npins)
|
||||
{
|
||||
struct cv1800_pin *pin;
|
||||
enum cv1800_pin_io_type type;
|
||||
u8 power_domain;
|
||||
int i;
|
||||
@@ -187,232 +158,78 @@ static int cv1800_verify_pin_group(const struct cv1800_pin_mux_config *mux,
|
||||
if (npins == 1)
|
||||
return 0;
|
||||
|
||||
type = cv1800_pin_io_type(mux[0].pin);
|
||||
power_domain = mux[0].pin->power_domain;
|
||||
pin = sophgo_to_cv1800_pin(mux[0].pin);
|
||||
type = cv1800_pin_io_type(pin);
|
||||
power_domain = pin->power_domain;
|
||||
|
||||
for (i = 0; i < npins; i++) {
|
||||
if (type != cv1800_pin_io_type(mux[i].pin) ||
|
||||
power_domain != mux[i].pin->power_domain)
|
||||
pin = sophgo_to_cv1800_pin(mux[i].pin);
|
||||
|
||||
if (type != cv1800_pin_io_type(pin) ||
|
||||
power_domain != pin->power_domain)
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cv1800_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **maps,
|
||||
unsigned int *num_maps)
|
||||
static int cv1800_dt_node_to_map_post(struct device_node *cur,
|
||||
struct sophgo_pinctrl *pctrl,
|
||||
struct sophgo_pin_mux_config *pinmuxs,
|
||||
unsigned int npins)
|
||||
{
|
||||
struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct device *dev = pctrl->dev;
|
||||
struct device_node *child;
|
||||
struct pinctrl_map *map;
|
||||
const char **grpnames;
|
||||
const char *grpname;
|
||||
int ngroups = 0;
|
||||
int nmaps = 0;
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(pinmuxs[0].pin);
|
||||
u32 power;
|
||||
int ret;
|
||||
|
||||
for_each_available_child_of_node(np, child)
|
||||
ngroups += 1;
|
||||
ret = of_property_read_u32(cur, "power-source", &power);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
grpnames = devm_kcalloc(dev, ngroups, sizeof(*grpnames), GFP_KERNEL);
|
||||
if (!grpnames)
|
||||
return -ENOMEM;
|
||||
if (!(power == PIN_POWER_STATE_3V3 || power == PIN_POWER_STATE_1V8))
|
||||
return -ENOTSUPP;
|
||||
|
||||
map = kcalloc(ngroups * 2, sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
ngroups = 0;
|
||||
mutex_lock(&pctrl->mutex);
|
||||
for_each_available_child_of_node(np, child) {
|
||||
int npins = of_property_count_u32_elems(child, "pinmux");
|
||||
unsigned int *pins;
|
||||
struct cv1800_pin_mux_config *pinmuxs;
|
||||
u32 config, power;
|
||||
int i;
|
||||
|
||||
if (npins < 1) {
|
||||
dev_err(dev, "invalid pinctrl group %pOFn.%pOFn\n",
|
||||
np, child);
|
||||
ret = -EINVAL;
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
grpname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn",
|
||||
np, child);
|
||||
if (!grpname) {
|
||||
ret = -ENOMEM;
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
grpnames[ngroups++] = grpname;
|
||||
|
||||
pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
|
||||
if (!pins) {
|
||||
ret = -ENOMEM;
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
pinmuxs = devm_kcalloc(dev, npins, sizeof(*pinmuxs), GFP_KERNEL);
|
||||
if (!pinmuxs) {
|
||||
ret = -ENOMEM;
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
for (i = 0; i < npins; i++) {
|
||||
ret = of_property_read_u32_index(child, "pinmux",
|
||||
i, &config);
|
||||
if (ret)
|
||||
goto dt_failed;
|
||||
|
||||
pins[i] = cv1800_dt_get_pin(config);
|
||||
pinmuxs[i].config = config;
|
||||
pinmuxs[i].pin = cv1800_get_pin(pctrl, pins[i]);
|
||||
|
||||
if (!pinmuxs[i].pin) {
|
||||
dev_err(dev, "failed to get pin %d\n", pins[i]);
|
||||
ret = -ENODEV;
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
ret = cv1800_verify_pinmux_config(&pinmuxs[i]);
|
||||
if (ret) {
|
||||
dev_err(dev, "group %s pin %d is invalid\n",
|
||||
grpname, i);
|
||||
goto dt_failed;
|
||||
}
|
||||
}
|
||||
|
||||
ret = cv1800_verify_pin_group(pinmuxs, npins);
|
||||
if (ret) {
|
||||
dev_err(dev, "group %s is invalid\n", grpname);
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(child, "power-source", &power);
|
||||
if (ret)
|
||||
goto dt_failed;
|
||||
|
||||
if (!(power == PIN_POWER_STATE_3V3 || power == PIN_POWER_STATE_1V8)) {
|
||||
dev_err(dev, "group %s have unsupported power: %u\n",
|
||||
grpname, power);
|
||||
ret = -ENOTSUPP;
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
ret = cv1800_set_power_cfg(pctrl, pinmuxs[0].pin->power_domain,
|
||||
power);
|
||||
if (ret)
|
||||
goto dt_failed;
|
||||
|
||||
map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
map[nmaps].data.mux.function = np->name;
|
||||
map[nmaps].data.mux.group = grpname;
|
||||
nmaps += 1;
|
||||
|
||||
ret = pinconf_generic_parse_dt_config(child, pctldev,
|
||||
&map[nmaps].data.configs.configs,
|
||||
&map[nmaps].data.configs.num_configs);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to parse pin config of group %s: %d\n",
|
||||
grpname, ret);
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
ret = pinctrl_generic_add_group(pctldev, grpname,
|
||||
pins, npins, pinmuxs);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to add group %s: %d\n", grpname, ret);
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
/* don't create a map if there are no pinconf settings */
|
||||
if (map[nmaps].data.configs.num_configs == 0)
|
||||
continue;
|
||||
|
||||
map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
|
||||
map[nmaps].data.configs.group_or_pin = grpname;
|
||||
nmaps += 1;
|
||||
}
|
||||
|
||||
ret = pinmux_generic_add_function(pctldev, np->name,
|
||||
grpnames, ngroups, NULL);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "error adding function %s: %d\n", np->name, ret);
|
||||
goto function_failed;
|
||||
}
|
||||
|
||||
*maps = map;
|
||||
*num_maps = nmaps;
|
||||
mutex_unlock(&pctrl->mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
dt_failed:
|
||||
of_node_put(child);
|
||||
function_failed:
|
||||
pinctrl_utils_free_map(pctldev, map, nmaps);
|
||||
mutex_unlock(&pctrl->mutex);
|
||||
return ret;
|
||||
return cv1800_set_power_cfg(pctrl, pin->power_domain, power);
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops cv1800_pctrl_ops = {
|
||||
const struct pinctrl_ops cv1800_pctrl_ops = {
|
||||
.get_groups_count = pinctrl_generic_get_group_count,
|
||||
.get_group_name = pinctrl_generic_get_group_name,
|
||||
.get_group_pins = pinctrl_generic_get_group_pins,
|
||||
.pin_dbg_show = cv1800_pctrl_dbg_show,
|
||||
.dt_node_to_map = cv1800_pctrl_dt_node_to_map,
|
||||
.dt_node_to_map = sophgo_pctrl_dt_node_to_map,
|
||||
.dt_free_map = pinctrl_utils_free_map,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(cv1800_pctrl_ops);
|
||||
|
||||
static int cv1800_pmx_set_mux(struct pinctrl_dev *pctldev,
|
||||
unsigned int fsel, unsigned int gsel)
|
||||
static void cv1800_set_pinmux_config(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *sp, u32 config)
|
||||
{
|
||||
struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct group_desc *group;
|
||||
const struct cv1800_pin_mux_config *configs;
|
||||
unsigned int i;
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
struct cv1800_priv *priv = pctrl->priv_ctrl;
|
||||
void __iomem *reg_mux;
|
||||
void __iomem *reg_mux2;
|
||||
u32 mux;
|
||||
u32 mux2;
|
||||
|
||||
group = pinctrl_generic_get_group(pctldev, gsel);
|
||||
if (!group)
|
||||
return -EINVAL;
|
||||
reg_mux = cv1800_pinctrl_get_component_addr(priv, &pin->mux);
|
||||
reg_mux2 = cv1800_pinctrl_get_component_addr(priv, &pin->mux2);
|
||||
mux = cv1800_dt_get_pin_mux(config);
|
||||
mux2 = cv1800_dt_get_pin_mux2(config);
|
||||
|
||||
configs = group->data;
|
||||
|
||||
for (i = 0; i < group->grp.npins; i++) {
|
||||
const struct cv1800_pin *pin = configs[i].pin;
|
||||
u32 value = configs[i].config;
|
||||
void __iomem *reg_mux;
|
||||
void __iomem *reg_mux2;
|
||||
unsigned long flags;
|
||||
u32 mux;
|
||||
u32 mux2;
|
||||
|
||||
reg_mux = cv1800_pinctrl_get_component_addr(pctrl, &pin->mux);
|
||||
reg_mux2 = cv1800_pinctrl_get_component_addr(pctrl, &pin->mux2);
|
||||
mux = cv1800_dt_get_pin_mux(value);
|
||||
mux2 = cv1800_dt_get_pin_mux2(value);
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
writel_relaxed(mux, reg_mux);
|
||||
if (mux2 != PIN_MUX_INVALD)
|
||||
writel_relaxed(mux2, reg_mux2);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
writel_relaxed(mux, reg_mux);
|
||||
if (mux2 != PIN_MUX_INVALD)
|
||||
writel_relaxed(mux2, reg_mux2);
|
||||
}
|
||||
|
||||
static const struct pinmux_ops cv1800_pmx_ops = {
|
||||
const struct pinmux_ops cv1800_pmx_ops = {
|
||||
.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 = cv1800_pmx_set_mux,
|
||||
.set_mux = sophgo_pmx_set_mux,
|
||||
.strict = true,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(cv1800_pmx_ops);
|
||||
|
||||
#define PIN_IO_PULLUP BIT(2)
|
||||
#define PIN_IO_PULLDOWN BIT(3)
|
||||
@@ -421,94 +238,14 @@ static const struct pinmux_ops cv1800_pmx_ops = {
|
||||
#define PIN_IO_BUS_HOLD BIT(10)
|
||||
#define PIN_IO_OUT_FAST_SLEW BIT(11)
|
||||
|
||||
static u32 cv1800_pull_down_typical_resistor(struct cv1800_pinctrl *pctrl,
|
||||
struct cv1800_pin *pin)
|
||||
{
|
||||
return pctrl->data->vddio_ops->get_pull_down(pin, pctrl->power_cfg);
|
||||
}
|
||||
|
||||
static u32 cv1800_pull_up_typical_resistor(struct cv1800_pinctrl *pctrl,
|
||||
struct cv1800_pin *pin)
|
||||
{
|
||||
return pctrl->data->vddio_ops->get_pull_up(pin, pctrl->power_cfg);
|
||||
}
|
||||
|
||||
static int cv1800_pinctrl_oc2reg(struct cv1800_pinctrl *pctrl,
|
||||
struct cv1800_pin *pin, u32 target)
|
||||
{
|
||||
const u32 *map;
|
||||
int i, len;
|
||||
|
||||
len = pctrl->data->vddio_ops->get_oc_map(pin, pctrl->power_cfg, &map);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (map[i] >= target)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cv1800_pinctrl_reg2oc(struct cv1800_pinctrl *pctrl,
|
||||
struct cv1800_pin *pin, u32 reg)
|
||||
{
|
||||
const u32 *map;
|
||||
int len;
|
||||
|
||||
len = pctrl->data->vddio_ops->get_oc_map(pin, pctrl->power_cfg, &map);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
if (reg >= len)
|
||||
return -EINVAL;
|
||||
|
||||
return map[reg];
|
||||
}
|
||||
|
||||
static int cv1800_pinctrl_schmitt2reg(struct cv1800_pinctrl *pctrl,
|
||||
struct cv1800_pin *pin, u32 target)
|
||||
{
|
||||
const u32 *map;
|
||||
int i, len;
|
||||
|
||||
len = pctrl->data->vddio_ops->get_schmitt_map(pin, pctrl->power_cfg,
|
||||
&map);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (map[i] == target)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int cv1800_pinctrl_reg2schmitt(struct cv1800_pinctrl *pctrl,
|
||||
struct cv1800_pin *pin, u32 reg)
|
||||
{
|
||||
const u32 *map;
|
||||
int len;
|
||||
|
||||
len = pctrl->data->vddio_ops->get_schmitt_map(pin, pctrl->power_cfg,
|
||||
&map);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
if (reg >= len)
|
||||
return -EINVAL;
|
||||
|
||||
return map[reg];
|
||||
}
|
||||
|
||||
static int cv1800_pconf_get(struct pinctrl_dev *pctldev,
|
||||
unsigned int pin_id, unsigned long *config)
|
||||
{
|
||||
struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct cv1800_priv *priv = pctrl->priv_ctrl;
|
||||
int param = pinconf_to_config_param(*config);
|
||||
struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
|
||||
const struct sophgo_pin *sp = sophgo_get_pin(pctrl, pin_id);
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
enum cv1800_pin_io_type type;
|
||||
u32 value;
|
||||
u32 arg;
|
||||
@@ -522,28 +259,28 @@ static int cv1800_pconf_get(struct pinctrl_dev *pctldev,
|
||||
if (type == IO_TYPE_ETH || type == IO_TYPE_AUDIO)
|
||||
return -ENOTSUPP;
|
||||
|
||||
value = readl(cv1800_pinctrl_get_component_addr(pctrl, &pin->conf));
|
||||
value = readl(cv1800_pinctrl_get_component_addr(priv, &pin->conf));
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
enabled = FIELD_GET(PIN_IO_PULLDOWN, value);
|
||||
arg = cv1800_pull_down_typical_resistor(pctrl, pin);
|
||||
arg = sophgo_pinctrl_typical_pull_down(pctrl, sp, priv->power_cfg);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
enabled = FIELD_GET(PIN_IO_PULLUP, value);
|
||||
arg = cv1800_pull_up_typical_resistor(pctrl, pin);
|
||||
arg = sophgo_pinctrl_typical_pull_up(pctrl, sp, priv->power_cfg);
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH_UA:
|
||||
enabled = true;
|
||||
arg = FIELD_GET(PIN_IO_DRIVE, value);
|
||||
ret = cv1800_pinctrl_reg2oc(pctrl, pin, arg);
|
||||
ret = sophgo_pinctrl_reg2oc(pctrl, sp, priv->power_cfg, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
arg = ret;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_SCHMITT_UV:
|
||||
arg = FIELD_GET(PIN_IO_SCHMITT, value);
|
||||
ret = cv1800_pinctrl_reg2schmitt(pctrl, pin, arg);
|
||||
ret = sophgo_pinctrl_reg2schmitt(pctrl, sp, priv->power_cfg, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
arg = ret;
|
||||
@@ -570,14 +307,16 @@ static int cv1800_pconf_get(struct pinctrl_dev *pctldev,
|
||||
return enabled ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
|
||||
struct cv1800_pin *pin,
|
||||
static int cv1800_pinconf_compute_config(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *sp,
|
||||
unsigned long *configs,
|
||||
unsigned int num_configs,
|
||||
u32 *value)
|
||||
u32 *value, u32 *mask)
|
||||
{
|
||||
struct cv1800_priv *priv = pctrl->priv_ctrl;
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
int i;
|
||||
u32 v = 0;
|
||||
u32 v = 0, m = 0;
|
||||
enum cv1800_pin_io_type type;
|
||||
int ret;
|
||||
|
||||
@@ -596,24 +335,30 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
v &= ~PIN_IO_PULLDOWN;
|
||||
v |= FIELD_PREP(PIN_IO_PULLDOWN, arg);
|
||||
m |= PIN_IO_PULLDOWN;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
v &= ~PIN_IO_PULLUP;
|
||||
v |= FIELD_PREP(PIN_IO_PULLUP, arg);
|
||||
m |= PIN_IO_PULLUP;
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH_UA:
|
||||
ret = cv1800_pinctrl_oc2reg(pctrl, pin, arg);
|
||||
ret = sophgo_pinctrl_oc2reg(pctrl, sp,
|
||||
priv->power_cfg, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
v &= ~PIN_IO_DRIVE;
|
||||
v |= FIELD_PREP(PIN_IO_DRIVE, ret);
|
||||
m |= PIN_IO_DRIVE;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_SCHMITT_UV:
|
||||
ret = cv1800_pinctrl_schmitt2reg(pctrl, pin, arg);
|
||||
ret = sophgo_pinctrl_schmitt2reg(pctrl, sp,
|
||||
priv->power_cfg, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
v &= ~PIN_IO_SCHMITT;
|
||||
v |= FIELD_PREP(PIN_IO_SCHMITT, ret);
|
||||
m |= PIN_IO_SCHMITT;
|
||||
break;
|
||||
case PIN_CONFIG_POWER_SOURCE:
|
||||
/* Ignore power source as it is always fixed */
|
||||
@@ -621,10 +366,12 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
|
||||
case PIN_CONFIG_SLEW_RATE:
|
||||
v &= ~PIN_IO_OUT_FAST_SLEW;
|
||||
v |= FIELD_PREP(PIN_IO_OUT_FAST_SLEW, arg);
|
||||
m |= PIN_IO_OUT_FAST_SLEW;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_BUS_HOLD:
|
||||
v &= ~PIN_IO_BUS_HOLD;
|
||||
v |= FIELD_PREP(PIN_IO_BUS_HOLD, arg);
|
||||
m |= PIN_IO_BUS_HOLD;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
@@ -632,134 +379,73 @@ static int cv1800_pinconf_compute_config(struct cv1800_pinctrl *pctrl,
|
||||
}
|
||||
|
||||
*value = v;
|
||||
*mask = m;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cv1800_pin_set_config(struct cv1800_pinctrl *pctrl,
|
||||
unsigned int pin_id,
|
||||
u32 value)
|
||||
static int cv1800_set_pinconf_config(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *sp,
|
||||
u32 value, u32 mask)
|
||||
{
|
||||
struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
|
||||
unsigned long flags;
|
||||
struct cv1800_priv *priv = pctrl->priv_ctrl;
|
||||
struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
void __iomem *addr;
|
||||
u32 reg;
|
||||
|
||||
if (!pin)
|
||||
return -EINVAL;
|
||||
addr = cv1800_pinctrl_get_component_addr(priv, &pin->conf);
|
||||
|
||||
addr = cv1800_pinctrl_get_component_addr(pctrl, &pin->conf);
|
||||
|
||||
raw_spin_lock_irqsave(&pctrl->lock, flags);
|
||||
writel(value, addr);
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
reg = readl(addr);
|
||||
reg &= ~mask;
|
||||
reg |= value;
|
||||
writel(reg, addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cv1800_pconf_set(struct pinctrl_dev *pctldev,
|
||||
unsigned int pin_id, unsigned long *configs,
|
||||
unsigned int num_configs)
|
||||
{
|
||||
struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct cv1800_pin *pin = cv1800_get_pin(pctrl, pin_id);
|
||||
u32 value;
|
||||
|
||||
if (!pin)
|
||||
return -ENODEV;
|
||||
|
||||
if (cv1800_pinconf_compute_config(pctrl, pin,
|
||||
configs, num_configs, &value))
|
||||
return -ENOTSUPP;
|
||||
|
||||
return cv1800_pin_set_config(pctrl, pin_id, value);
|
||||
}
|
||||
|
||||
static int cv1800_pconf_group_set(struct pinctrl_dev *pctldev,
|
||||
unsigned int gsel,
|
||||
unsigned long *configs,
|
||||
unsigned int num_configs)
|
||||
{
|
||||
struct cv1800_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct group_desc *group;
|
||||
const struct cv1800_pin_mux_config *pinmuxs;
|
||||
u32 value;
|
||||
int i;
|
||||
|
||||
group = pinctrl_generic_get_group(pctldev, gsel);
|
||||
if (!group)
|
||||
return -EINVAL;
|
||||
|
||||
pinmuxs = group->data;
|
||||
|
||||
if (cv1800_pinconf_compute_config(pctrl, pinmuxs[0].pin,
|
||||
configs, num_configs, &value))
|
||||
return -ENOTSUPP;
|
||||
|
||||
for (i = 0; i < group->grp.npins; i++)
|
||||
cv1800_pin_set_config(pctrl, group->grp.pins[i], value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinconf_ops cv1800_pconf_ops = {
|
||||
const struct pinconf_ops cv1800_pconf_ops = {
|
||||
.pin_config_get = cv1800_pconf_get,
|
||||
.pin_config_set = cv1800_pconf_set,
|
||||
.pin_config_group_set = cv1800_pconf_group_set,
|
||||
.pin_config_set = sophgo_pconf_set,
|
||||
.pin_config_group_set = sophgo_pconf_group_set,
|
||||
.is_generic = true,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(cv1800_pconf_ops);
|
||||
|
||||
int cv1800_pinctrl_probe(struct platform_device *pdev)
|
||||
static int cv1800_pinctrl_init(struct platform_device *pdev,
|
||||
struct sophgo_pinctrl *pctrl)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct cv1800_pinctrl *pctrl;
|
||||
const struct cv1800_pinctrl_data *pctrl_data;
|
||||
int ret;
|
||||
const struct sophgo_pinctrl_data *pctrl_data = pctrl->data;
|
||||
struct cv1800_priv *priv;
|
||||
|
||||
pctrl_data = device_get_match_data(dev);
|
||||
if (!pctrl_data)
|
||||
return -ENODEV;
|
||||
|
||||
if (pctrl_data->npins == 0 || pctrl_data->npd == 0)
|
||||
return dev_err_probe(dev, -EINVAL, "invalid pin data\n");
|
||||
|
||||
pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
|
||||
if (!pctrl)
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(struct cv1800_priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
pctrl->power_cfg = devm_kcalloc(dev, pctrl_data->npd,
|
||||
sizeof(u32), GFP_KERNEL);
|
||||
if (!pctrl->power_cfg)
|
||||
priv->power_cfg = devm_kcalloc(&pdev->dev, pctrl_data->npds,
|
||||
sizeof(u32), GFP_KERNEL);
|
||||
if (!priv->power_cfg)
|
||||
return -ENOMEM;
|
||||
|
||||
pctrl->regs[0] = devm_platform_ioremap_resource_byname(pdev, "sys");
|
||||
if (IS_ERR(pctrl->regs[0]))
|
||||
return PTR_ERR(pctrl->regs[0]);
|
||||
priv->regs[0] = devm_platform_ioremap_resource_byname(pdev, "sys");
|
||||
if (IS_ERR(priv->regs[0]))
|
||||
return PTR_ERR(priv->regs[0]);
|
||||
|
||||
pctrl->regs[1] = devm_platform_ioremap_resource_byname(pdev, "rtc");
|
||||
if (IS_ERR(pctrl->regs[1]))
|
||||
return PTR_ERR(pctrl->regs[1]);
|
||||
priv->regs[1] = devm_platform_ioremap_resource_byname(pdev, "rtc");
|
||||
if (IS_ERR(priv->regs[1]))
|
||||
return PTR_ERR(priv->regs[1]);
|
||||
|
||||
pctrl->pdesc.name = dev_name(dev);
|
||||
pctrl->pdesc.pins = pctrl_data->pins;
|
||||
pctrl->pdesc.npins = pctrl_data->npins;
|
||||
pctrl->pdesc.pctlops = &cv1800_pctrl_ops;
|
||||
pctrl->pdesc.pmxops = &cv1800_pmx_ops;
|
||||
pctrl->pdesc.confops = &cv1800_pconf_ops;
|
||||
pctrl->pdesc.owner = THIS_MODULE;
|
||||
pctrl->priv_ctrl = priv;
|
||||
|
||||
pctrl->data = pctrl_data;
|
||||
pctrl->dev = dev;
|
||||
raw_spin_lock_init(&pctrl->lock);
|
||||
mutex_init(&pctrl->mutex);
|
||||
|
||||
platform_set_drvdata(pdev, pctrl);
|
||||
|
||||
ret = devm_pinctrl_register_and_init(dev, &pctrl->pdesc,
|
||||
pctrl, &pctrl->pctl_dev);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"fail to register pinctrl driver\n");
|
||||
|
||||
return pinctrl_enable(pctrl->pctl_dev);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cv1800_pinctrl_probe);
|
||||
|
||||
const struct sophgo_cfg_ops cv1800_cfg_ops = {
|
||||
.pctrl_init = cv1800_pinctrl_init,
|
||||
.verify_pinmux_config = cv1800_verify_pinmux_config,
|
||||
.verify_pin_group = cv1800_verify_pin_group,
|
||||
.dt_node_to_map_post = cv1800_dt_node_to_map_post,
|
||||
.compute_pinconf_config = cv1800_pinconf_compute_config,
|
||||
.set_pinconf_config = cv1800_set_pinconf_config,
|
||||
.set_pinmux_config = cv1800_set_pinmux_config,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(cv1800_cfg_ops);
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
|
||||
#include "pinctrl-sophgo.h"
|
||||
|
||||
enum cv1800_pin_io_type {
|
||||
IO_TYPE_1V8_ONLY = 0,
|
||||
IO_TYPE_1V8_OR_3V3 = 1,
|
||||
@@ -49,58 +50,37 @@ struct cv1800_pinconf {
|
||||
#define CV1800_PIN_FLAG_IO_TYPE(type) \
|
||||
FIELD_PREP_CONST(CV1800_PIN_IO_TYPE, type)
|
||||
struct cv1800_pin {
|
||||
u16 pin;
|
||||
u16 flags;
|
||||
struct sophgo_pin pin;
|
||||
u8 power_domain;
|
||||
struct cv1800_pinmux mux;
|
||||
struct cv1800_pinmux2 mux2;
|
||||
struct cv1800_pinconf conf;
|
||||
};
|
||||
|
||||
#define sophgo_to_cv1800_pin(_pin) \
|
||||
container_of((_pin), struct cv1800_pin, pin)
|
||||
|
||||
#define PIN_POWER_STATE_1V8 1800
|
||||
#define PIN_POWER_STATE_3V3 3300
|
||||
|
||||
/**
|
||||
* struct cv1800_vddio_cfg_ops - pin vddio operations
|
||||
*
|
||||
* @get_pull_up: get resistor for pull up;
|
||||
* @get_pull_down: get resistor for pull down.
|
||||
* @get_oc_map: get mapping for typical low level output current value to
|
||||
* register value map.
|
||||
* @get_schmitt_map: get mapping for register value to typical schmitt
|
||||
* threshold.
|
||||
*/
|
||||
struct cv1800_vddio_cfg_ops {
|
||||
int (*get_pull_up)(struct cv1800_pin *pin, const u32 *psmap);
|
||||
int (*get_pull_down)(struct cv1800_pin *pin, const u32 *psmap);
|
||||
int (*get_oc_map)(struct cv1800_pin *pin, const u32 *psmap,
|
||||
const u32 **map);
|
||||
int (*get_schmitt_map)(struct cv1800_pin *pin, const u32 *psmap,
|
||||
const u32 **map);
|
||||
};
|
||||
|
||||
struct cv1800_pinctrl_data {
|
||||
const struct pinctrl_pin_desc *pins;
|
||||
const struct cv1800_pin *pindata;
|
||||
const char * const *pdnames;
|
||||
const struct cv1800_vddio_cfg_ops *vddio_ops;
|
||||
u16 npins;
|
||||
u16 npd;
|
||||
};
|
||||
|
||||
static inline enum cv1800_pin_io_type cv1800_pin_io_type(struct cv1800_pin *pin)
|
||||
static inline enum cv1800_pin_io_type cv1800_pin_io_type(const struct cv1800_pin *pin)
|
||||
{
|
||||
return FIELD_GET(CV1800_PIN_IO_TYPE, pin->flags);
|
||||
return FIELD_GET(CV1800_PIN_IO_TYPE, pin->pin.flags);
|
||||
};
|
||||
|
||||
int cv1800_pinctrl_probe(struct platform_device *pdev);
|
||||
extern const struct pinctrl_ops cv1800_pctrl_ops;
|
||||
extern const struct pinmux_ops cv1800_pmx_ops;
|
||||
extern const struct pinconf_ops cv1800_pconf_ops;
|
||||
extern const struct sophgo_cfg_ops cv1800_cfg_ops;
|
||||
|
||||
#define CV1800_FUNC_PIN(_id, _power_domain, _type, \
|
||||
_mux_area, _mux_offset, _mux_func_max) \
|
||||
{ \
|
||||
.pin = (_id), \
|
||||
.pin = { \
|
||||
.id = (_id), \
|
||||
.flags = CV1800_PIN_FLAG_IO_TYPE(_type), \
|
||||
}, \
|
||||
.power_domain = (_power_domain), \
|
||||
.flags = CV1800_PIN_FLAG_IO_TYPE(_type), \
|
||||
.mux = { \
|
||||
.area = (_mux_area), \
|
||||
.offset = (_mux_offset), \
|
||||
@@ -112,9 +92,11 @@ int cv1800_pinctrl_probe(struct platform_device *pdev);
|
||||
_mux_area, _mux_offset, _mux_func_max, \
|
||||
_conf_area, _conf_offset) \
|
||||
{ \
|
||||
.pin = (_id), \
|
||||
.pin = { \
|
||||
.id = (_id), \
|
||||
.flags = CV1800_PIN_FLAG_IO_TYPE(_type), \
|
||||
}, \
|
||||
.power_domain = (_power_domain), \
|
||||
.flags = CV1800_PIN_FLAG_IO_TYPE(_type), \
|
||||
.mux = { \
|
||||
.area = (_mux_area), \
|
||||
.offset = (_mux_offset), \
|
||||
@@ -132,10 +114,12 @@ int cv1800_pinctrl_probe(struct platform_device *pdev);
|
||||
_mux2_func_max, \
|
||||
_conf_area, _conf_offset) \
|
||||
{ \
|
||||
.pin = (_id), \
|
||||
.pin = { \
|
||||
.id = (_id), \
|
||||
.flags = CV1800_PIN_FLAG_IO_TYPE(_type) | \
|
||||
CV1800_PIN_HAVE_MUX2, \
|
||||
}, \
|
||||
.power_domain = (_power_domain), \
|
||||
.flags = CV1800_PIN_FLAG_IO_TYPE(_type) | \
|
||||
CV1800_PIN_HAVE_MUX2, \
|
||||
.mux = { \
|
||||
.area = (_mux_area), \
|
||||
.offset = (_mux_offset), \
|
||||
|
||||
@@ -40,8 +40,9 @@ static const char *const sg2000_power_domain_desc[] = {
|
||||
[VDDIO_VIVO] = "VDDIO_VIVO",
|
||||
};
|
||||
|
||||
static int sg2000_get_pull_up(struct cv1800_pin *pin, const u32 *psmap)
|
||||
static int sg2000_get_pull_up(const struct sophgo_pin *sp, const u32 *psmap)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
|
||||
@@ -60,8 +61,9 @@ static int sg2000_get_pull_up(struct cv1800_pin *pin, const u32 *psmap)
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int sg2000_get_pull_down(struct cv1800_pin *pin, const u32 *psmap)
|
||||
static int sg2000_get_pull_down(const struct sophgo_pin *sp, const u32 *psmap)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
|
||||
@@ -114,9 +116,10 @@ static const u32 sg2000_eth_oc_map[] = {
|
||||
17800
|
||||
};
|
||||
|
||||
static int sg2000_get_oc_map(struct cv1800_pin *pin, const u32 *psmap,
|
||||
static int sg2000_get_oc_map(const struct sophgo_pin *sp, const u32 *psmap,
|
||||
const u32 **map)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
|
||||
@@ -159,9 +162,10 @@ static const u32 sg2000_18od33_3v3_schmitt_map[] = {
|
||||
1100000
|
||||
};
|
||||
|
||||
static int sg2000_get_schmitt_map(struct cv1800_pin *pin, const u32 *psmap,
|
||||
static int sg2000_get_schmitt_map(const struct sophgo_pin *sp, const u32 *psmap,
|
||||
const u32 **map)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
|
||||
@@ -183,11 +187,11 @@ static int sg2000_get_schmitt_map(struct cv1800_pin *pin, const u32 *psmap,
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static const struct cv1800_vddio_cfg_ops sg2000_vddio_cfg_ops = {
|
||||
static const struct sophgo_vddio_cfg_ops sg2000_vddio_cfg_ops = {
|
||||
.get_pull_up = sg2000_get_pull_up,
|
||||
.get_pull_down = sg2000_get_pull_down,
|
||||
.get_oc_map = sg2000_get_oc_map,
|
||||
.get_schmitt_map = sg2000_get_schmitt_map,
|
||||
.get_schmitt_map = sg2000_get_schmitt_map,
|
||||
};
|
||||
|
||||
static const struct pinctrl_pin_desc sg2000_pins[] = {
|
||||
@@ -742,13 +746,18 @@ static const struct cv1800_pin sg2000_pin_data[ARRAY_SIZE(sg2000_pins)] = {
|
||||
CV1800_PINCONF_AREA_RTC, 0x028),
|
||||
};
|
||||
|
||||
static const struct cv1800_pinctrl_data sg2000_pindata = {
|
||||
static const struct sophgo_pinctrl_data sg2000_pindata = {
|
||||
.pins = sg2000_pins,
|
||||
.pindata = sg2000_pin_data,
|
||||
.pdnames = sg2000_power_domain_desc,
|
||||
.vddio_ops = &sg2000_vddio_cfg_ops,
|
||||
.cfg_ops = &cv1800_cfg_ops,
|
||||
.pctl_ops = &cv1800_pctrl_ops,
|
||||
.pmx_ops = &cv1800_pmx_ops,
|
||||
.pconf_ops = &cv1800_pconf_ops,
|
||||
.npins = ARRAY_SIZE(sg2000_pins),
|
||||
.npd = ARRAY_SIZE(sg2000_power_domain_desc),
|
||||
.npds = ARRAY_SIZE(sg2000_power_domain_desc),
|
||||
.pinsize = sizeof(struct cv1800_pin),
|
||||
};
|
||||
|
||||
static const struct of_device_id sg2000_pinctrl_ids[] = {
|
||||
@@ -758,7 +767,7 @@ static const struct of_device_id sg2000_pinctrl_ids[] = {
|
||||
MODULE_DEVICE_TABLE(of, sg2000_pinctrl_ids);
|
||||
|
||||
static struct platform_driver sg2000_pinctrl_driver = {
|
||||
.probe = cv1800_pinctrl_probe,
|
||||
.probe = sophgo_pinctrl_probe,
|
||||
.driver = {
|
||||
.name = "sg2000-pinctrl",
|
||||
.suppress_bind_attrs = true,
|
||||
|
||||
@@ -34,8 +34,9 @@ static const char *const sg2002_power_domain_desc[] = {
|
||||
[VDDIO_SD1] = "VDDIO_SD1",
|
||||
};
|
||||
|
||||
static int sg2002_get_pull_up(struct cv1800_pin *pin, const u32 *psmap)
|
||||
static int sg2002_get_pull_up(const struct sophgo_pin *sp, const u32 *psmap)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
|
||||
@@ -54,8 +55,9 @@ static int sg2002_get_pull_up(struct cv1800_pin *pin, const u32 *psmap)
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static int sg2002_get_pull_down(struct cv1800_pin *pin, const u32 *psmap)
|
||||
static int sg2002_get_pull_down(const struct sophgo_pin *sp, const u32 *psmap)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
|
||||
@@ -108,9 +110,10 @@ static const u32 sg2002_eth_oc_map[] = {
|
||||
17800
|
||||
};
|
||||
|
||||
static int sg2002_get_oc_map(struct cv1800_pin *pin, const u32 *psmap,
|
||||
static int sg2002_get_oc_map(const struct sophgo_pin *sp, const u32 *psmap,
|
||||
const u32 **map)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
|
||||
@@ -153,9 +156,10 @@ static const u32 sg2002_18od33_3v3_schmitt_map[] = {
|
||||
1100000
|
||||
};
|
||||
|
||||
static int sg2002_get_schmitt_map(struct cv1800_pin *pin, const u32 *psmap,
|
||||
static int sg2002_get_schmitt_map(const struct sophgo_pin *sp, const u32 *psmap,
|
||||
const u32 **map)
|
||||
{
|
||||
const struct cv1800_pin *pin = sophgo_to_cv1800_pin(sp);
|
||||
enum cv1800_pin_io_type type = cv1800_pin_io_type(pin);
|
||||
u32 pstate = psmap[pin->power_domain];
|
||||
|
||||
@@ -177,11 +181,11 @@ static int sg2002_get_schmitt_map(struct cv1800_pin *pin, const u32 *psmap,
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
static const struct cv1800_vddio_cfg_ops sg2002_vddio_cfg_ops = {
|
||||
static const struct sophgo_vddio_cfg_ops sg2002_vddio_cfg_ops = {
|
||||
.get_pull_up = sg2002_get_pull_up,
|
||||
.get_pull_down = sg2002_get_pull_down,
|
||||
.get_oc_map = sg2002_get_oc_map,
|
||||
.get_schmitt_map = sg2002_get_schmitt_map,
|
||||
.get_schmitt_map = sg2002_get_schmitt_map,
|
||||
};
|
||||
|
||||
static const struct pinctrl_pin_desc sg2002_pins[] = {
|
||||
@@ -513,13 +517,18 @@ static const struct cv1800_pin sg2002_pin_data[ARRAY_SIZE(sg2002_pins)] = {
|
||||
CV1800_PINCONF_AREA_SYS, 0xc84),
|
||||
};
|
||||
|
||||
static const struct cv1800_pinctrl_data sg2002_pindata = {
|
||||
static const struct sophgo_pinctrl_data sg2002_pindata = {
|
||||
.pins = sg2002_pins,
|
||||
.pindata = sg2002_pin_data,
|
||||
.pdnames = sg2002_power_domain_desc,
|
||||
.vddio_ops = &sg2002_vddio_cfg_ops,
|
||||
.cfg_ops = &cv1800_cfg_ops,
|
||||
.pctl_ops = &cv1800_pctrl_ops,
|
||||
.pmx_ops = &cv1800_pmx_ops,
|
||||
.pconf_ops = &cv1800_pconf_ops,
|
||||
.npins = ARRAY_SIZE(sg2002_pins),
|
||||
.npd = ARRAY_SIZE(sg2002_power_domain_desc),
|
||||
.npds = ARRAY_SIZE(sg2002_power_domain_desc),
|
||||
.pinsize = sizeof(struct cv1800_pin),
|
||||
};
|
||||
|
||||
static const struct of_device_id sg2002_pinctrl_ids[] = {
|
||||
@@ -529,7 +538,7 @@ static const struct of_device_id sg2002_pinctrl_ids[] = {
|
||||
MODULE_DEVICE_TABLE(of, sg2002_pinctrl_ids);
|
||||
|
||||
static struct platform_driver sg2002_pinctrl_driver = {
|
||||
.probe = cv1800_pinctrl_probe,
|
||||
.probe = sophgo_pinctrl_probe,
|
||||
.driver = {
|
||||
.name = "sg2002-pinctrl",
|
||||
.suppress_bind_attrs = true,
|
||||
|
||||
296
drivers/pinctrl/sophgo/pinctrl-sg2042-ops.c
Normal file
296
drivers/pinctrl/sophgo/pinctrl-sg2042-ops.c
Normal file
@@ -0,0 +1,296 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Sophgo sg2042 SoCs pinctrl driver.
|
||||
*
|
||||
* Copyright (C) 2024 Inochi Amaoto <inochiama@outlook.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
|
||||
#include "../pinctrl-utils.h"
|
||||
#include "../pinmux.h"
|
||||
|
||||
#include "pinctrl-sg2042.h"
|
||||
|
||||
#define PIN_IO_PULL_ONE_ENABLE BIT(0)
|
||||
#define PIN_IO_PULL_DIR_UP (BIT(1) | PIN_IO_PULL_ONE_ENABLE)
|
||||
#define PIN_IO_PULL_DIR_DOWN (0 | PIN_IO_PULL_ONE_ENABLE)
|
||||
#define PIN_IO_PULL_ONE_MASK GENMASK(1, 0)
|
||||
|
||||
#define PIN_IO_PULL_UP BIT(2)
|
||||
#define PIN_IO_PULL_UP_DONW BIT(3)
|
||||
#define PIN_IO_PULL_UP_MASK GENMASK(3, 2)
|
||||
|
||||
#define PIN_IO_MUX GENMASK(5, 4)
|
||||
#define PIN_IO_DRIVE GENMASK(9, 6)
|
||||
#define PIN_IO_SCHMITT_ENABLE BIT(10)
|
||||
#define PIN_IO_OUTPUT_ENABLE BIT(11)
|
||||
|
||||
struct sg2042_priv {
|
||||
void __iomem *regs;
|
||||
};
|
||||
|
||||
static u8 sg2042_dt_get_pin_mux(u32 value)
|
||||
{
|
||||
return value >> 16;
|
||||
}
|
||||
|
||||
static inline u32 sg2042_get_pin_reg(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *sp)
|
||||
{
|
||||
struct sg2042_priv *priv = pctrl->priv_ctrl;
|
||||
const struct sg2042_pin *pin = sophgo_to_sg2042_pin(sp);
|
||||
void __iomem *reg = priv->regs + pin->offset;
|
||||
|
||||
if (sp->flags & PIN_FLAG_WRITE_HIGH)
|
||||
return readl(reg) >> 16;
|
||||
else
|
||||
return readl(reg) & 0xffff;
|
||||
}
|
||||
|
||||
static int sg2042_set_pin_reg(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *sp,
|
||||
u32 value, u32 mask)
|
||||
{
|
||||
struct sg2042_priv *priv = pctrl->priv_ctrl;
|
||||
const struct sg2042_pin *pin = sophgo_to_sg2042_pin(sp);
|
||||
void __iomem *reg = priv->regs + pin->offset;
|
||||
u32 v = readl(reg);
|
||||
|
||||
if (sp->flags & PIN_FLAG_WRITE_HIGH) {
|
||||
v &= ~(mask << 16);
|
||||
v |= value << 16;
|
||||
} else {
|
||||
v &= ~mask;
|
||||
v |= value;
|
||||
}
|
||||
|
||||
writel(v, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sg2042_pctrl_dbg_show(struct pinctrl_dev *pctldev,
|
||||
struct seq_file *seq, unsigned int pin_id)
|
||||
{
|
||||
struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct sophgo_pin *sp = sophgo_get_pin(pctrl, pin_id);
|
||||
u32 value, mux;
|
||||
|
||||
value = sg2042_get_pin_reg(pctrl, sp);
|
||||
mux = FIELD_GET(PIN_IO_MUX, value);
|
||||
seq_printf(seq, "mux:%u reg:0x%04x ", mux, value);
|
||||
}
|
||||
|
||||
const struct pinctrl_ops sg2042_pctrl_ops = {
|
||||
.get_groups_count = pinctrl_generic_get_group_count,
|
||||
.get_group_name = pinctrl_generic_get_group_name,
|
||||
.get_group_pins = pinctrl_generic_get_group_pins,
|
||||
.pin_dbg_show = sg2042_pctrl_dbg_show,
|
||||
.dt_node_to_map = sophgo_pctrl_dt_node_to_map,
|
||||
.dt_free_map = pinctrl_utils_free_map,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(sg2042_pctrl_ops);
|
||||
|
||||
static void sg2042_set_pinmux_config(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *sp, u32 config)
|
||||
{
|
||||
u32 mux = sg2042_dt_get_pin_mux(config);
|
||||
|
||||
if (!(sp->flags & PIN_FLAG_NO_PINMUX))
|
||||
sg2042_set_pin_reg(pctrl, sp, mux, PIN_IO_MUX);
|
||||
}
|
||||
|
||||
const struct pinmux_ops sg2042_pmx_ops = {
|
||||
.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 = sophgo_pmx_set_mux,
|
||||
.strict = true,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(sg2042_pmx_ops);
|
||||
|
||||
static int sg2042_pconf_get(struct pinctrl_dev *pctldev,
|
||||
unsigned int pin_id, unsigned long *config)
|
||||
{
|
||||
struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
int param = pinconf_to_config_param(*config);
|
||||
const struct sophgo_pin *sp = sophgo_get_pin(pctrl, pin_id);
|
||||
u32 value;
|
||||
u32 arg;
|
||||
bool enabled;
|
||||
int ret;
|
||||
|
||||
if (!sp)
|
||||
return -EINVAL;
|
||||
|
||||
value = sg2042_get_pin_reg(pctrl, sp);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
if (sp->flags & PIN_FLAG_ONLY_ONE_PULL)
|
||||
arg = FIELD_GET(PIN_IO_PULL_ONE_ENABLE, value);
|
||||
else
|
||||
arg = FIELD_GET(PIN_IO_PULL_UP_MASK, value);
|
||||
enabled = arg == 0;
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
if (sp->flags & PIN_FLAG_ONLY_ONE_PULL) {
|
||||
arg = FIELD_GET(PIN_IO_PULL_ONE_MASK, value);
|
||||
enabled = arg == PIN_IO_PULL_DIR_DOWN;
|
||||
} else {
|
||||
enabled = FIELD_GET(PIN_IO_PULL_UP_DONW, value) != 0;
|
||||
}
|
||||
arg = sophgo_pinctrl_typical_pull_down(pctrl, sp, NULL);
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
if (sp->flags & PIN_FLAG_ONLY_ONE_PULL) {
|
||||
arg = FIELD_GET(PIN_IO_PULL_ONE_MASK, value);
|
||||
enabled = arg == PIN_IO_PULL_DIR_UP;
|
||||
} else {
|
||||
enabled = FIELD_GET(PIN_IO_PULL_UP, value) != 0;
|
||||
}
|
||||
arg = sophgo_pinctrl_typical_pull_up(pctrl, sp, NULL);
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH_UA:
|
||||
enabled = FIELD_GET(PIN_IO_OUTPUT_ENABLE, value) != 0;
|
||||
arg = FIELD_GET(PIN_IO_DRIVE, value);
|
||||
ret = sophgo_pinctrl_reg2oc(pctrl, sp, NULL, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
arg = ret;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
arg = FIELD_GET(PIN_IO_SCHMITT_ENABLE, value);
|
||||
enabled = arg != 0;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
*config = pinconf_to_config_packed(param, arg);
|
||||
|
||||
return enabled ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
static int sg2042_pinconf_compute_config(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *sp,
|
||||
unsigned long *configs,
|
||||
unsigned int num_configs,
|
||||
u32 *value, u32 *mask)
|
||||
{
|
||||
int i;
|
||||
u16 v = 0, m = 0;
|
||||
int ret;
|
||||
|
||||
if (!sp)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
int param = pinconf_to_config_param(configs[i]);
|
||||
u32 arg = pinconf_to_config_argument(configs[i]);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_BIAS_DISABLE:
|
||||
if (sp->flags & PIN_FLAG_ONLY_ONE_PULL) {
|
||||
v &= ~PIN_IO_PULL_ONE_ENABLE;
|
||||
m |= PIN_IO_PULL_ONE_ENABLE;
|
||||
} else {
|
||||
v &= ~PIN_IO_PULL_UP_MASK;
|
||||
m |= PIN_IO_PULL_UP_MASK;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_DOWN:
|
||||
if (sp->flags & PIN_FLAG_ONLY_ONE_PULL) {
|
||||
v &= ~PIN_IO_PULL_ONE_MASK;
|
||||
v |= PIN_IO_PULL_DIR_DOWN;
|
||||
m |= PIN_IO_PULL_ONE_MASK;
|
||||
} else {
|
||||
v |= PIN_IO_PULL_UP_DONW;
|
||||
m |= PIN_IO_PULL_UP_DONW;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_BIAS_PULL_UP:
|
||||
if (sp->flags & PIN_FLAG_ONLY_ONE_PULL) {
|
||||
v &= ~PIN_IO_PULL_ONE_MASK;
|
||||
v |= PIN_IO_PULL_DIR_UP;
|
||||
m |= PIN_IO_PULL_ONE_MASK;
|
||||
} else {
|
||||
v |= PIN_IO_PULL_UP;
|
||||
m |= PIN_IO_PULL_UP;
|
||||
}
|
||||
break;
|
||||
case PIN_CONFIG_DRIVE_STRENGTH_UA:
|
||||
v &= ~(PIN_IO_DRIVE | PIN_IO_OUTPUT_ENABLE);
|
||||
if (arg != 0) {
|
||||
ret = sophgo_pinctrl_oc2reg(pctrl, sp, NULL, arg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!(sp->flags & PIN_FLAG_NO_OEX_EN))
|
||||
v |= PIN_IO_OUTPUT_ENABLE;
|
||||
v |= FIELD_PREP(PIN_IO_DRIVE, ret);
|
||||
}
|
||||
m |= PIN_IO_DRIVE | PIN_IO_OUTPUT_ENABLE;
|
||||
break;
|
||||
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
|
||||
v |= PIN_IO_SCHMITT_ENABLE;
|
||||
m |= PIN_IO_SCHMITT_ENABLE;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
*value = v;
|
||||
*mask = m;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct pinconf_ops sg2042_pconf_ops = {
|
||||
.pin_config_get = sg2042_pconf_get,
|
||||
.pin_config_set = sophgo_pconf_set,
|
||||
.pin_config_group_set = sophgo_pconf_group_set,
|
||||
.is_generic = true,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(sg2042_pconf_ops);
|
||||
|
||||
static int sophgo_pinctrl_init(struct platform_device *pdev,
|
||||
struct sophgo_pinctrl *pctrl)
|
||||
{
|
||||
struct sg2042_priv *priv;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->regs = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(priv->regs))
|
||||
return PTR_ERR(priv->regs);
|
||||
|
||||
pctrl->priv_ctrl = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct sophgo_cfg_ops sg2042_cfg_ops = {
|
||||
.pctrl_init = sophgo_pinctrl_init,
|
||||
.compute_pinconf_config = sg2042_pinconf_compute_config,
|
||||
.set_pinconf_config = sg2042_set_pin_reg,
|
||||
.set_pinmux_config = sg2042_set_pinmux_config,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(sg2042_cfg_ops);
|
||||
655
drivers/pinctrl/sophgo/pinctrl-sg2042.c
Normal file
655
drivers/pinctrl/sophgo/pinctrl-sg2042.c
Normal file
@@ -0,0 +1,655 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Sophgo SG2042 SoC pinctrl driver.
|
||||
*
|
||||
* Copyright (C) 2024 Inochi Amaoto <inochiama@outlook.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
|
||||
#include <dt-bindings/pinctrl/pinctrl-sg2042.h>
|
||||
|
||||
#include "pinctrl-sg2042.h"
|
||||
|
||||
static int sg2042_get_pull_up(const struct sophgo_pin *sp, const u32 *psmap)
|
||||
{
|
||||
return 35000;
|
||||
}
|
||||
|
||||
static int sg2042_get_pull_down(const struct sophgo_pin *sp, const u32 *psmap)
|
||||
{
|
||||
return 28000;
|
||||
}
|
||||
|
||||
static const u32 sg2042_oc_map[] = {
|
||||
5400, 8100, 10700, 13400,
|
||||
16100, 18800, 21400, 24100,
|
||||
26800, 29400, 32100, 34800,
|
||||
37400, 40100, 42800, 45400
|
||||
};
|
||||
|
||||
static int sg2042_get_oc_map(const struct sophgo_pin *sp, const u32 *psmap,
|
||||
const u32 **map)
|
||||
{
|
||||
*map = sg2042_oc_map;
|
||||
return ARRAY_SIZE(sg2042_oc_map);
|
||||
}
|
||||
|
||||
static const struct sophgo_vddio_cfg_ops sg2042_vddio_cfg_ops = {
|
||||
.get_pull_up = sg2042_get_pull_up,
|
||||
.get_pull_down = sg2042_get_pull_down,
|
||||
.get_oc_map = sg2042_get_oc_map,
|
||||
};
|
||||
|
||||
static const struct pinctrl_pin_desc sg2042_pins[] = {
|
||||
PINCTRL_PIN(PIN_LPC_LCLK, "lpc_lclk"),
|
||||
PINCTRL_PIN(PIN_LPC_LFRAME, "lpc_lframe"),
|
||||
PINCTRL_PIN(PIN_LPC_LAD0, "lpc_lad0"),
|
||||
PINCTRL_PIN(PIN_LPC_LAD1, "lpc_lad1"),
|
||||
PINCTRL_PIN(PIN_LPC_LAD2, "lpc_lad2"),
|
||||
PINCTRL_PIN(PIN_LPC_LAD3, "lpc_lad3"),
|
||||
PINCTRL_PIN(PIN_LPC_LDRQ0, "lpc_ldrq0"),
|
||||
PINCTRL_PIN(PIN_LPC_LDRQ1, "lpc_ldrq1"),
|
||||
PINCTRL_PIN(PIN_LPC_SERIRQ, "lpc_serirq"),
|
||||
PINCTRL_PIN(PIN_LPC_CLKRUN, "lpc_clkrun"),
|
||||
PINCTRL_PIN(PIN_LPC_LPME, "lpc_lpme"),
|
||||
PINCTRL_PIN(PIN_LPC_LPCPD, "lpc_lpcpd"),
|
||||
PINCTRL_PIN(PIN_LPC_LSMI, "lpc_lsmi"),
|
||||
PINCTRL_PIN(PIN_PCIE0_L0_RESET, "pcie0_l0_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE0_L1_RESET, "pcie0_l1_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE0_L0_WAKEUP, "pcie0_l0_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE0_L1_WAKEUP, "pcie0_l1_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE0_L0_CLKREQ_IN, "pcie0_l0_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_PCIE0_L1_CLKREQ_IN, "pcie0_l1_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_PCIE1_L0_RESET, "pcie1_l0_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE1_L1_RESET, "pcie1_l1_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE1_L0_WAKEUP, "pcie1_l0_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE1_L1_WAKEUP, "pcie1_l1_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE1_L0_CLKREQ_IN, "pcie1_l0_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_PCIE1_L1_CLKREQ_IN, "pcie1_l1_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_SPIF0_CLK_SEL1, "spif0_clk_sel1"),
|
||||
PINCTRL_PIN(PIN_SPIF0_CLK_SEL0, "spif0_clk_sel0"),
|
||||
PINCTRL_PIN(PIN_SPIF0_WP, "spif0_wp"),
|
||||
PINCTRL_PIN(PIN_SPIF0_HOLD, "spif0_hold"),
|
||||
PINCTRL_PIN(PIN_SPIF0_SDI, "spif0_sdi"),
|
||||
PINCTRL_PIN(PIN_SPIF0_CS, "spif0_cs"),
|
||||
PINCTRL_PIN(PIN_SPIF0_SCK, "spif0_sck"),
|
||||
PINCTRL_PIN(PIN_SPIF0_SDO, "spif0_sdo"),
|
||||
PINCTRL_PIN(PIN_SPIF1_CLK_SEL1, "spif1_clk_sel1"),
|
||||
PINCTRL_PIN(PIN_SPIF1_CLK_SEL0, "spif1_clk_sel0"),
|
||||
PINCTRL_PIN(PIN_SPIF1_WP, "spif1_wp"),
|
||||
PINCTRL_PIN(PIN_SPIF1_HOLD, "spif1_hold"),
|
||||
PINCTRL_PIN(PIN_SPIF1_SDI, "spif1_sdi"),
|
||||
PINCTRL_PIN(PIN_SPIF1_CS, "spif1_cs"),
|
||||
PINCTRL_PIN(PIN_SPIF1_SCK, "spif1_sck"),
|
||||
PINCTRL_PIN(PIN_SPIF1_SDO, "spif1_sdo"),
|
||||
PINCTRL_PIN(PIN_EMMC_WP, "emmc_wp"),
|
||||
PINCTRL_PIN(PIN_EMMC_CD, "emmc_cd"),
|
||||
PINCTRL_PIN(PIN_EMMC_RST, "emmc_rst"),
|
||||
PINCTRL_PIN(PIN_EMMC_PWR_EN, "emmc_pwr_en"),
|
||||
PINCTRL_PIN(PIN_SDIO_CD, "sdio_cd"),
|
||||
PINCTRL_PIN(PIN_SDIO_WP, "sdio_wp"),
|
||||
PINCTRL_PIN(PIN_SDIO_RST, "sdio_rst"),
|
||||
PINCTRL_PIN(PIN_SDIO_PWR_EN, "sdio_pwr_en"),
|
||||
PINCTRL_PIN(PIN_RGMII0_TXD0, "rgmii0_txd0"),
|
||||
PINCTRL_PIN(PIN_RGMII0_TXD1, "rgmii0_txd1"),
|
||||
PINCTRL_PIN(PIN_RGMII0_TXD2, "rgmii0_txd2"),
|
||||
PINCTRL_PIN(PIN_RGMII0_TXD3, "rgmii0_txd3"),
|
||||
PINCTRL_PIN(PIN_RGMII0_TXCTRL, "rgmii0_txctrl"),
|
||||
PINCTRL_PIN(PIN_RGMII0_RXD0, "rgmii0_rxd0"),
|
||||
PINCTRL_PIN(PIN_RGMII0_RXD1, "rgmii0_rxd1"),
|
||||
PINCTRL_PIN(PIN_RGMII0_RXD2, "rgmii0_rxd2"),
|
||||
PINCTRL_PIN(PIN_RGMII0_RXD3, "rgmii0_rxd3"),
|
||||
PINCTRL_PIN(PIN_RGMII0_RXCTRL, "rgmii0_rxctrl"),
|
||||
PINCTRL_PIN(PIN_RGMII0_TXC, "rgmii0_txc"),
|
||||
PINCTRL_PIN(PIN_RGMII0_RXC, "rgmii0_rxc"),
|
||||
PINCTRL_PIN(PIN_RGMII0_REFCLKO, "rgmii0_refclko"),
|
||||
PINCTRL_PIN(PIN_RGMII0_IRQ, "rgmii0_irq"),
|
||||
PINCTRL_PIN(PIN_RGMII0_MDC, "rgmii0_mdc"),
|
||||
PINCTRL_PIN(PIN_RGMII0_MDIO, "rgmii0_mdio"),
|
||||
PINCTRL_PIN(PIN_PWM0, "pwm0"),
|
||||
PINCTRL_PIN(PIN_PWM1, "pwm1"),
|
||||
PINCTRL_PIN(PIN_PWM2, "pwm2"),
|
||||
PINCTRL_PIN(PIN_PWM3, "pwm3"),
|
||||
PINCTRL_PIN(PIN_FAN0, "fan0"),
|
||||
PINCTRL_PIN(PIN_FAN1, "fan1"),
|
||||
PINCTRL_PIN(PIN_FAN2, "fan2"),
|
||||
PINCTRL_PIN(PIN_FAN3, "fan3"),
|
||||
PINCTRL_PIN(PIN_IIC0_SDA, "iic0_sda"),
|
||||
PINCTRL_PIN(PIN_IIC0_SCL, "iic0_scl"),
|
||||
PINCTRL_PIN(PIN_IIC1_SDA, "iic1_sda"),
|
||||
PINCTRL_PIN(PIN_IIC1_SCL, "iic1_scl"),
|
||||
PINCTRL_PIN(PIN_IIC2_SDA, "iic2_sda"),
|
||||
PINCTRL_PIN(PIN_IIC2_SCL, "iic2_scl"),
|
||||
PINCTRL_PIN(PIN_IIC3_SDA, "iic3_sda"),
|
||||
PINCTRL_PIN(PIN_IIC3_SCL, "iic3_scl"),
|
||||
PINCTRL_PIN(PIN_UART0_TX, "uart0_tx"),
|
||||
PINCTRL_PIN(PIN_UART0_RX, "uart0_rx"),
|
||||
PINCTRL_PIN(PIN_UART0_RTS, "uart0_rts"),
|
||||
PINCTRL_PIN(PIN_UART0_CTS, "uart0_cts"),
|
||||
PINCTRL_PIN(PIN_UART1_TX, "uart1_tx"),
|
||||
PINCTRL_PIN(PIN_UART1_RX, "uart1_rx"),
|
||||
PINCTRL_PIN(PIN_UART1_RTS, "uart1_rts"),
|
||||
PINCTRL_PIN(PIN_UART1_CTS, "uart1_cts"),
|
||||
PINCTRL_PIN(PIN_UART2_TX, "uart2_tx"),
|
||||
PINCTRL_PIN(PIN_UART2_RX, "uart2_rx"),
|
||||
PINCTRL_PIN(PIN_UART2_RTS, "uart2_rts"),
|
||||
PINCTRL_PIN(PIN_UART2_CTS, "uart2_cts"),
|
||||
PINCTRL_PIN(PIN_UART3_TX, "uart3_tx"),
|
||||
PINCTRL_PIN(PIN_UART3_RX, "uart3_rx"),
|
||||
PINCTRL_PIN(PIN_UART3_RTS, "uart3_rts"),
|
||||
PINCTRL_PIN(PIN_UART3_CTS, "uart3_cts"),
|
||||
PINCTRL_PIN(PIN_SPI0_CS0, "spi0_cs0"),
|
||||
PINCTRL_PIN(PIN_SPI0_CS1, "spi0_cs1"),
|
||||
PINCTRL_PIN(PIN_SPI0_SDI, "spi0_sdi"),
|
||||
PINCTRL_PIN(PIN_SPI0_SDO, "spi0_sdo"),
|
||||
PINCTRL_PIN(PIN_SPI0_SCK, "spi0_sck"),
|
||||
PINCTRL_PIN(PIN_SPI1_CS0, "spi1_cs0"),
|
||||
PINCTRL_PIN(PIN_SPI1_CS1, "spi1_cs1"),
|
||||
PINCTRL_PIN(PIN_SPI1_SDI, "spi1_sdi"),
|
||||
PINCTRL_PIN(PIN_SPI1_SDO, "spi1_sdo"),
|
||||
PINCTRL_PIN(PIN_SPI1_SCK, "spi1_sck"),
|
||||
PINCTRL_PIN(PIN_JTAG0_TDO, "jtag0_tdo"),
|
||||
PINCTRL_PIN(PIN_JTAG0_TCK, "jtag0_tck"),
|
||||
PINCTRL_PIN(PIN_JTAG0_TDI, "jtag0_tdi"),
|
||||
PINCTRL_PIN(PIN_JTAG0_TMS, "jtag0_tms"),
|
||||
PINCTRL_PIN(PIN_JTAG0_TRST, "jtag0_trst"),
|
||||
PINCTRL_PIN(PIN_JTAG0_SRST, "jtag0_srst"),
|
||||
PINCTRL_PIN(PIN_JTAG1_TDO, "jtag1_tdo"),
|
||||
PINCTRL_PIN(PIN_JTAG1_TCK, "jtag1_tck"),
|
||||
PINCTRL_PIN(PIN_JTAG1_TDI, "jtag1_tdi"),
|
||||
PINCTRL_PIN(PIN_JTAG1_TMS, "jtag1_tms"),
|
||||
PINCTRL_PIN(PIN_JTAG1_TRST, "jtag1_trst"),
|
||||
PINCTRL_PIN(PIN_JTAG1_SRST, "jtag1_srst"),
|
||||
PINCTRL_PIN(PIN_JTAG2_TDO, "jtag2_tdo"),
|
||||
PINCTRL_PIN(PIN_JTAG2_TCK, "jtag2_tck"),
|
||||
PINCTRL_PIN(PIN_JTAG2_TDI, "jtag2_tdi"),
|
||||
PINCTRL_PIN(PIN_JTAG2_TMS, "jtag2_tms"),
|
||||
PINCTRL_PIN(PIN_JTAG2_TRST, "jtag2_trst"),
|
||||
PINCTRL_PIN(PIN_JTAG2_SRST, "jtag2_srst"),
|
||||
PINCTRL_PIN(PIN_GPIO0, "gpio0"),
|
||||
PINCTRL_PIN(PIN_GPIO1, "gpio1"),
|
||||
PINCTRL_PIN(PIN_GPIO2, "gpio2"),
|
||||
PINCTRL_PIN(PIN_GPIO3, "gpio3"),
|
||||
PINCTRL_PIN(PIN_GPIO4, "gpio4"),
|
||||
PINCTRL_PIN(PIN_GPIO5, "gpio5"),
|
||||
PINCTRL_PIN(PIN_GPIO6, "gpio6"),
|
||||
PINCTRL_PIN(PIN_GPIO7, "gpio7"),
|
||||
PINCTRL_PIN(PIN_GPIO8, "gpio8"),
|
||||
PINCTRL_PIN(PIN_GPIO9, "gpio9"),
|
||||
PINCTRL_PIN(PIN_GPIO10, "gpio10"),
|
||||
PINCTRL_PIN(PIN_GPIO11, "gpio11"),
|
||||
PINCTRL_PIN(PIN_GPIO12, "gpio12"),
|
||||
PINCTRL_PIN(PIN_GPIO13, "gpio13"),
|
||||
PINCTRL_PIN(PIN_GPIO14, "gpio14"),
|
||||
PINCTRL_PIN(PIN_GPIO15, "gpio15"),
|
||||
PINCTRL_PIN(PIN_GPIO16, "gpio16"),
|
||||
PINCTRL_PIN(PIN_GPIO17, "gpio17"),
|
||||
PINCTRL_PIN(PIN_GPIO18, "gpio18"),
|
||||
PINCTRL_PIN(PIN_GPIO19, "gpio19"),
|
||||
PINCTRL_PIN(PIN_GPIO20, "gpio20"),
|
||||
PINCTRL_PIN(PIN_GPIO21, "gpio21"),
|
||||
PINCTRL_PIN(PIN_GPIO22, "gpio22"),
|
||||
PINCTRL_PIN(PIN_GPIO23, "gpio23"),
|
||||
PINCTRL_PIN(PIN_GPIO24, "gpio24"),
|
||||
PINCTRL_PIN(PIN_GPIO25, "gpio25"),
|
||||
PINCTRL_PIN(PIN_GPIO26, "gpio26"),
|
||||
PINCTRL_PIN(PIN_GPIO27, "gpio27"),
|
||||
PINCTRL_PIN(PIN_GPIO28, "gpio28"),
|
||||
PINCTRL_PIN(PIN_GPIO29, "gpio29"),
|
||||
PINCTRL_PIN(PIN_GPIO30, "gpio30"),
|
||||
PINCTRL_PIN(PIN_GPIO31, "gpio31"),
|
||||
PINCTRL_PIN(PIN_MODE_SEL0, "mode_sel0"),
|
||||
PINCTRL_PIN(PIN_MODE_SEL1, "mode_sel1"),
|
||||
PINCTRL_PIN(PIN_MODE_SEL2, "mode_sel2"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL0, "boot_sel0"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL1, "boot_sel1"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL2, "boot_sel2"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL3, "boot_sel3"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL4, "boot_sel4"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL5, "boot_sel5"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL6, "boot_sel6"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL7, "boot_sel7"),
|
||||
PINCTRL_PIN(PIN_MULTI_SCKT, "multi_sckt"),
|
||||
PINCTRL_PIN(PIN_SCKT_ID0, "sckt_id0"),
|
||||
PINCTRL_PIN(PIN_SCKT_ID1, "sckt_id1"),
|
||||
PINCTRL_PIN(PIN_PLL_CLK_IN_MAIN, "pll_clk_in_main"),
|
||||
PINCTRL_PIN(PIN_PLL_CLK_IN_DDR_L, "pll_clk_in_ddr_l"),
|
||||
PINCTRL_PIN(PIN_PLL_CLK_IN_DDR_R, "pll_clk_in_ddr_r"),
|
||||
PINCTRL_PIN(PIN_XTAL_32K, "xtal_32k"),
|
||||
PINCTRL_PIN(PIN_SYS_RST, "sys_rst"),
|
||||
PINCTRL_PIN(PIN_PWR_BUTTON, "pwr_button"),
|
||||
PINCTRL_PIN(PIN_TEST_EN, "test_en"),
|
||||
PINCTRL_PIN(PIN_TEST_MODE_MBIST, "test_mode_mbist"),
|
||||
PINCTRL_PIN(PIN_TEST_MODE_SCAN, "test_mode_scan"),
|
||||
PINCTRL_PIN(PIN_TEST_MODE_BSD, "test_mode_bsd"),
|
||||
PINCTRL_PIN(PIN_BISR_BYP, "bisr_byp"),
|
||||
};
|
||||
|
||||
static const struct sg2042_pin sg2042_pin_data[ARRAY_SIZE(sg2042_pins)] = {
|
||||
SG2042_GENERAL_PIN(PIN_LPC_LCLK, 0x000,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_LPC_LFRAME, 0x000,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_LPC_LAD0, 0x004,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_LPC_LAD1, 0x004,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_LPC_LAD2, 0x008,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_LPC_LAD3, 0x008,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_LPC_LDRQ0, 0x00c,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_LPC_LDRQ1, 0x00c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_LPC_SERIRQ, 0x010,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_LPC_CLKRUN, 0x010,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_LPC_LPME, 0x014,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_LPC_LPCPD, 0x014,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_LPC_LSMI, 0x018,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE0_L0_RESET, 0x018,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE0_L1_RESET, 0x01c,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE0_L0_WAKEUP, 0x01c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE0_L1_WAKEUP, 0x020,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE0_L0_CLKREQ_IN, 0x020,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE0_L1_CLKREQ_IN, 0x024,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE1_L0_RESET, 0x024,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE1_L1_RESET, 0x028,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE1_L0_WAKEUP, 0x028,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE1_L1_WAKEUP, 0x02c,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE1_L0_CLKREQ_IN, 0x02c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE1_L1_CLKREQ_IN, 0x030,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_CLK_SEL1, 0x030,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_CLK_SEL0, 0x034,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_WP, 0x034,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_HOLD, 0x038,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_SDI, 0x038,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_CS, 0x03c,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_SCK, 0x03c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_SDO, 0x040,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_CLK_SEL1, 0x040,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_CLK_SEL0, 0x044,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_WP, 0x044,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_HOLD, 0x048,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_SDI, 0x048,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_CS, 0x04c,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_SCK, 0x04c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_SDO, 0x050,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_EMMC_WP, 0x050,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_EMMC_CD, 0x054,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_EMMC_RST, 0x054,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_EMMC_PWR_EN, 0x058,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SDIO_CD, 0x058,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SDIO_WP, 0x05c,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SDIO_RST, 0x05c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SDIO_PWR_EN, 0x060,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_TXD0, 0x060,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_TXD1, 0x064,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_TXD2, 0x064,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_TXD3, 0x068,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_TXCTRL, 0x068,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_RXD0, 0x06c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_RXD1, 0x06c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_RXD2, 0x070,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_RXD3, 0x070,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_RXCTRL, 0x074,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_TXC, 0x074,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_RXC, 0x078,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_REFCLKO, 0x078,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_IRQ, 0x07c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_MDC, 0x07c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_MDIO, 0x080,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PWM0, 0x080,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PWM1, 0x084,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PWM2, 0x084,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_PWM3, 0x088,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_FAN0, 0x088,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_FAN1, 0x08c,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_FAN2, 0x08c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_FAN3, 0x090,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_IIC0_SDA, 0x090,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_IIC0_SCL, 0x094,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_IIC1_SDA, 0x094,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_IIC1_SCL, 0x098,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_IIC2_SDA, 0x098,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_IIC2_SCL, 0x09c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_IIC3_SDA, 0x09c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_IIC3_SCL, 0x0a0,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_UART0_TX, 0x0a0,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART0_RX, 0x0a4,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART0_RTS, 0x0a4,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART0_CTS, 0x0a8,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART1_TX, 0x0a8,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART1_RX, 0x0ac,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART1_RTS, 0x0ac,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART1_CTS, 0x0b0,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART2_TX, 0x0b0,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART2_RX, 0x0b4,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART2_RTS, 0x0b4,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART2_CTS, 0x0b8,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART3_TX, 0x0b8,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART3_RX, 0x0bc,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART3_RTS, 0x0bc,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_UART3_CTS, 0x0c0,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPI0_CS0, 0x0c0,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPI0_CS1, 0x0c4,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPI0_SDI, 0x0c4,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPI0_SDO, 0x0c8,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPI0_SCK, 0x0c8,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPI1_CS0, 0x0cc,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPI1_CS1, 0x0cc,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPI1_SDI, 0x0d0,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPI1_SDO, 0x0d0,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_SPI1_SCK, 0x0d4,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG0_TDO, 0x0d4,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG0_TCK, 0x0d8,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG0_TDI, 0x0d8,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG0_TMS, 0x0dc,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG0_TRST, 0x0dc,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG0_SRST, 0x0e0,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG1_TDO, 0x0e0,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG1_TCK, 0x0e4,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG1_TDI, 0x0e4,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG1_TMS, 0x0e8,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG1_TRST, 0x0e8,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG1_SRST, 0x0ec,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG2_TDO, 0x0ec,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG2_TCK, 0x0f0,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG2_TDI, 0x0f0,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG2_TMS, 0x0f4,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG2_TRST, 0x0f4,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG2_SRST, 0x0f8,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO0, 0x0f8,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO1, 0x0fc,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO2, 0x0fc,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO3, 0x100,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO4, 0x100,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO5, 0x104,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO6, 0x104,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO7, 0x108,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO8, 0x108,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO9, 0x10c,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO10, 0x10c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO11, 0x110,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO12, 0x110,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO13, 0x114,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO14, 0x114,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO15, 0x118,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO16, 0x118,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO17, 0x11c,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO18, 0x11c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO19, 0x120,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO20, 0x120,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO21, 0x124,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO22, 0x124,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO23, 0x128,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO24, 0x128,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO25, 0x12c,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO26, 0x12c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO27, 0x130,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO28, 0x130,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO29, 0x134,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO30, 0x134,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO31, 0x138,
|
||||
PIN_FLAG_ONLY_ONE_PULL),
|
||||
SG2042_GENERAL_PIN(PIN_MODE_SEL0, 0x138,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL |
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_MODE_SEL1, 0x13c,
|
||||
PIN_FLAG_ONLY_ONE_PULL | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_MODE_SEL2, 0x13c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL |
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL0, 0x140,
|
||||
PIN_FLAG_ONLY_ONE_PULL | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL1, 0x140,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL |
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL2, 0x144,
|
||||
PIN_FLAG_ONLY_ONE_PULL | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL3, 0x144,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL |
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL4, 0x148,
|
||||
PIN_FLAG_ONLY_ONE_PULL | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL5, 0x148,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL |
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL6, 0x14c,
|
||||
PIN_FLAG_ONLY_ONE_PULL | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL7, 0x14c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL |
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_MULTI_SCKT, 0x150,
|
||||
PIN_FLAG_ONLY_ONE_PULL | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_SCKT_ID0, 0x150,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL |
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_SCKT_ID1, 0x154,
|
||||
PIN_FLAG_ONLY_ONE_PULL | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_PLL_CLK_IN_MAIN, 0x154,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL |
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_PLL_CLK_IN_DDR_L, 0x158,
|
||||
PIN_FLAG_ONLY_ONE_PULL | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_PLL_CLK_IN_DDR_R, 0x158,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL |
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_XTAL_32K, 0x15c,
|
||||
PIN_FLAG_ONLY_ONE_PULL | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_SYS_RST, 0x15c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL |
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_PWR_BUTTON, 0x160,
|
||||
PIN_FLAG_ONLY_ONE_PULL | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_TEST_EN, 0x160,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL |
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_TEST_MODE_MBIST, 0x164,
|
||||
PIN_FLAG_ONLY_ONE_PULL | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_TEST_MODE_SCAN, 0x164,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL |
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_TEST_MODE_BSD, 0x168,
|
||||
PIN_FLAG_ONLY_ONE_PULL | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BISR_BYP, 0x168,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_ONLY_ONE_PULL |
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
};
|
||||
|
||||
static const struct sophgo_pinctrl_data sg2042_pindata = {
|
||||
.pins = sg2042_pins,
|
||||
.pindata = sg2042_pin_data,
|
||||
.vddio_ops = &sg2042_vddio_cfg_ops,
|
||||
.cfg_ops = &sg2042_cfg_ops,
|
||||
.pctl_ops = &sg2042_pctrl_ops,
|
||||
.pmx_ops = &sg2042_pmx_ops,
|
||||
.pconf_ops = &sg2042_pconf_ops,
|
||||
.npins = ARRAY_SIZE(sg2042_pins),
|
||||
.pinsize = sizeof(struct sg2042_pin),
|
||||
};
|
||||
|
||||
static const struct of_device_id sg2042_pinctrl_ids[] = {
|
||||
{ .compatible = "sophgo,sg2042-pinctrl", .data = &sg2042_pindata },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sg2042_pinctrl_ids);
|
||||
|
||||
static struct platform_driver sg2042_pinctrl_driver = {
|
||||
.probe = sophgo_pinctrl_probe,
|
||||
.driver = {
|
||||
.name = "sg2042-pinctrl",
|
||||
.suppress_bind_attrs = true,
|
||||
.of_match_table = sg2042_pinctrl_ids,
|
||||
},
|
||||
};
|
||||
module_platform_driver(sg2042_pinctrl_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Pinctrl driver for the SG2002 series SoC");
|
||||
MODULE_LICENSE("GPL");
|
||||
49
drivers/pinctrl/sophgo/pinctrl-sg2042.h
Normal file
49
drivers/pinctrl/sophgo/pinctrl-sg2042.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2024 Inochi Amaoto <inochiama@outlook.com>
|
||||
*/
|
||||
|
||||
#ifndef _PINCTRL_SOPHGO_SG2042_H
|
||||
#define _PINCTRL_SOPHGO_SG2042_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
|
||||
#include "pinctrl-sophgo.h"
|
||||
|
||||
#define PIN_FLAG_DEFAULT 0
|
||||
#define PIN_FLAG_WRITE_HIGH BIT(0)
|
||||
#define PIN_FLAG_ONLY_ONE_PULL BIT(1)
|
||||
#define PIN_FLAG_NO_PINMUX BIT(2)
|
||||
#define PIN_FLAG_NO_OEX_EN BIT(3)
|
||||
#define PIN_FLAG_IS_ETH BIT(4)
|
||||
|
||||
struct sg2042_pin {
|
||||
struct sophgo_pin pin;
|
||||
u16 offset;
|
||||
};
|
||||
|
||||
#define sophgo_to_sg2042_pin(_pin) \
|
||||
container_of((_pin), struct sg2042_pin, pin)
|
||||
|
||||
extern const struct pinctrl_ops sg2042_pctrl_ops;
|
||||
extern const struct pinmux_ops sg2042_pmx_ops;
|
||||
extern const struct pinconf_ops sg2042_pconf_ops;
|
||||
extern const struct sophgo_cfg_ops sg2042_cfg_ops;
|
||||
|
||||
#define SG2042_GENERAL_PIN(_id, _offset, _flag) \
|
||||
{ \
|
||||
.pin = { \
|
||||
.id = (_id), \
|
||||
.flags = (_flag), \
|
||||
}, \
|
||||
.offset = (_offset), \
|
||||
}
|
||||
|
||||
#endif
|
||||
718
drivers/pinctrl/sophgo/pinctrl-sg2044.c
Normal file
718
drivers/pinctrl/sophgo/pinctrl-sg2044.c
Normal file
@@ -0,0 +1,718 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Sophgo SG2042 SoC pinctrl driver.
|
||||
*
|
||||
* Copyright (C) 2024 Inochi Amaoto <inochiama@outlook.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
|
||||
#include <dt-bindings/pinctrl/pinctrl-sg2044.h>
|
||||
|
||||
#include "pinctrl-sg2042.h"
|
||||
|
||||
static int sg2044_get_pull_up(const struct sophgo_pin *sp, const u32 *psmap)
|
||||
{
|
||||
return 19500;
|
||||
}
|
||||
|
||||
static int sg2044_get_pull_down(const struct sophgo_pin *sp, const u32 *psmap)
|
||||
{
|
||||
return 23200;
|
||||
}
|
||||
|
||||
static const u32 sg2044_oc_map[] = {
|
||||
3200, 6400, 9600, 12700,
|
||||
15900, 19100, 22200, 25300,
|
||||
29500, 32700, 35900, 39000,
|
||||
42000, 45200, 48300, 51400
|
||||
};
|
||||
|
||||
static int sg2044_get_oc_map(const struct sophgo_pin *sp, const u32 *psmap,
|
||||
const u32 **map)
|
||||
{
|
||||
*map = sg2044_oc_map;
|
||||
return ARRAY_SIZE(sg2044_oc_map);
|
||||
}
|
||||
|
||||
static const struct sophgo_vddio_cfg_ops sg2044_vddio_cfg_ops = {
|
||||
.get_pull_up = sg2044_get_pull_up,
|
||||
.get_pull_down = sg2044_get_pull_down,
|
||||
.get_oc_map = sg2044_get_oc_map,
|
||||
};
|
||||
|
||||
static const struct pinctrl_pin_desc sg2044_pins[] = {
|
||||
PINCTRL_PIN(PIN_IIC0_SMBSUS_IN, "iic0_smbsus_in"),
|
||||
PINCTRL_PIN(PIN_IIC0_SMBSUS_OUT, "iic0_smbsus_out"),
|
||||
PINCTRL_PIN(PIN_IIC0_SMBALERT, "iic0_smbalert"),
|
||||
PINCTRL_PIN(PIN_IIC1_SMBSUS_IN, "iic1_smbsus_in"),
|
||||
PINCTRL_PIN(PIN_IIC1_SMBSUS_OUT, "iic1_smbsus_out"),
|
||||
PINCTRL_PIN(PIN_IIC1_SMBALERT, "iic1_smbalert"),
|
||||
PINCTRL_PIN(PIN_IIC2_SMBSUS_IN, "iic2_smbsus_in"),
|
||||
PINCTRL_PIN(PIN_IIC2_SMBSUS_OUT, "iic2_smbsus_out"),
|
||||
PINCTRL_PIN(PIN_IIC2_SMBALERT, "iic2_smbalert"),
|
||||
PINCTRL_PIN(PIN_IIC3_SMBSUS_IN, "iic3_smbsus_in"),
|
||||
PINCTRL_PIN(PIN_IIC3_SMBSUS_OUT, "iic3_smbsus_out"),
|
||||
PINCTRL_PIN(PIN_IIC3_SMBALERT, "iic3_smbalert"),
|
||||
PINCTRL_PIN(PIN_PCIE0_L0_RESET, "pcie0_l0_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE0_L1_RESET, "pcie0_l1_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE0_L0_WAKEUP, "pcie0_l0_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE0_L1_WAKEUP, "pcie0_l1_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE0_L0_CLKREQ_IN, "pcie0_l0_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_PCIE0_L1_CLKREQ_IN, "pcie0_l1_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_PCIE1_L0_RESET, "pcie1_l0_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE1_L1_RESET, "pcie1_l1_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE1_L0_WAKEUP, "pcie1_l0_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE1_L1_WAKEUP, "pcie1_l1_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE1_L0_CLKREQ_IN, "pcie1_l0_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_PCIE1_L1_CLKREQ_IN, "pcie1_l1_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_PCIE2_L0_RESET, "pcie2_l0_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE2_L1_RESET, "pcie2_l1_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE2_L0_WAKEUP, "pcie2_l0_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE2_L1_WAKEUP, "pcie2_l1_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE2_L0_CLKREQ_IN, "pcie2_l0_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_PCIE2_L1_CLKREQ_IN, "pcie2_l1_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_PCIE3_L0_RESET, "pcie3_l0_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE3_L1_RESET, "pcie3_l1_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE3_L0_WAKEUP, "pcie3_l0_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE3_L1_WAKEUP, "pcie3_l1_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE3_L0_CLKREQ_IN, "pcie3_l0_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_PCIE3_L1_CLKREQ_IN, "pcie3_l1_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_PCIE4_L0_RESET, "pcie4_l0_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE4_L1_RESET, "pcie4_l1_reset"),
|
||||
PINCTRL_PIN(PIN_PCIE4_L0_WAKEUP, "pcie4_l0_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE4_L1_WAKEUP, "pcie4_l1_wakeup"),
|
||||
PINCTRL_PIN(PIN_PCIE4_L0_CLKREQ_IN, "pcie4_l0_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_PCIE4_L1_CLKREQ_IN, "pcie4_l1_clkreq_in"),
|
||||
PINCTRL_PIN(PIN_SPIF0_CLK_SEL1, "spif0_clk_sel1"),
|
||||
PINCTRL_PIN(PIN_SPIF0_CLK_SEL0, "spif0_clk_sel0"),
|
||||
PINCTRL_PIN(PIN_SPIF0_WP, "spif0_wp"),
|
||||
PINCTRL_PIN(PIN_SPIF0_HOLD, "spif0_hold"),
|
||||
PINCTRL_PIN(PIN_SPIF0_SDI, "spif0_sdi"),
|
||||
PINCTRL_PIN(PIN_SPIF0_CS, "spif0_cs"),
|
||||
PINCTRL_PIN(PIN_SPIF0_SCK, "spif0_sck"),
|
||||
PINCTRL_PIN(PIN_SPIF0_SDO, "spif0_sdo"),
|
||||
PINCTRL_PIN(PIN_SPIF1_CLK_SEL1, "spif1_clk_sel1"),
|
||||
PINCTRL_PIN(PIN_SPIF1_CLK_SEL0, "spif1_clk_sel0"),
|
||||
PINCTRL_PIN(PIN_SPIF1_WP, "spif1_wp"),
|
||||
PINCTRL_PIN(PIN_SPIF1_HOLD, "spif1_hold"),
|
||||
PINCTRL_PIN(PIN_SPIF1_SDI, "spif1_sdi"),
|
||||
PINCTRL_PIN(PIN_SPIF1_CS, "spif1_cs"),
|
||||
PINCTRL_PIN(PIN_SPIF1_SCK, "spif1_sck"),
|
||||
PINCTRL_PIN(PIN_SPIF1_SDO, "spif1_sdo"),
|
||||
PINCTRL_PIN(PIN_EMMC_WP, "emmc_wp"),
|
||||
PINCTRL_PIN(PIN_EMMC_CD, "emmc_cd"),
|
||||
PINCTRL_PIN(PIN_EMMC_RST, "emmc_rst"),
|
||||
PINCTRL_PIN(PIN_EMMC_PWR_EN, "emmc_pwr_en"),
|
||||
PINCTRL_PIN(PIN_SDIO_CD, "sdio_cd"),
|
||||
PINCTRL_PIN(PIN_SDIO_WP, "sdio_wp"),
|
||||
PINCTRL_PIN(PIN_SDIO_RST, "sdio_rst"),
|
||||
PINCTRL_PIN(PIN_SDIO_PWR_EN, "sdio_pwr_en"),
|
||||
PINCTRL_PIN(PIN_RGMII0_TXD0, "rgmii0_txd0"),
|
||||
PINCTRL_PIN(PIN_RGMII0_TXD1, "rgmii0_txd1"),
|
||||
PINCTRL_PIN(PIN_RGMII0_TXD2, "rgmii0_txd2"),
|
||||
PINCTRL_PIN(PIN_RGMII0_TXD3, "rgmii0_txd3"),
|
||||
PINCTRL_PIN(PIN_RGMII0_TXCTRL, "rgmii0_txctrl"),
|
||||
PINCTRL_PIN(PIN_RGMII0_RXD0, "rgmii0_rxd0"),
|
||||
PINCTRL_PIN(PIN_RGMII0_RXD1, "rgmii0_rxd1"),
|
||||
PINCTRL_PIN(PIN_RGMII0_RXD2, "rgmii0_rxd2"),
|
||||
PINCTRL_PIN(PIN_RGMII0_RXD3, "rgmii0_rxd3"),
|
||||
PINCTRL_PIN(PIN_RGMII0_RXCTRL, "rgmii0_rxctrl"),
|
||||
PINCTRL_PIN(PIN_RGMII0_TXC, "rgmii0_txc"),
|
||||
PINCTRL_PIN(PIN_RGMII0_RXC, "rgmii0_rxc"),
|
||||
PINCTRL_PIN(PIN_RGMII0_REFCLKO, "rgmii0_refclko"),
|
||||
PINCTRL_PIN(PIN_RGMII0_IRQ, "rgmii0_irq"),
|
||||
PINCTRL_PIN(PIN_RGMII0_MDC, "rgmii0_mdc"),
|
||||
PINCTRL_PIN(PIN_RGMII0_MDIO, "rgmii0_mdio"),
|
||||
PINCTRL_PIN(PIN_PWM0, "pwm0"),
|
||||
PINCTRL_PIN(PIN_PWM1, "pwm1"),
|
||||
PINCTRL_PIN(PIN_PWM2, "pwm2"),
|
||||
PINCTRL_PIN(PIN_PWM3, "pwm3"),
|
||||
PINCTRL_PIN(PIN_FAN0, "fan0"),
|
||||
PINCTRL_PIN(PIN_FAN1, "fan1"),
|
||||
PINCTRL_PIN(PIN_FAN2, "fan2"),
|
||||
PINCTRL_PIN(PIN_FAN3, "fan3"),
|
||||
PINCTRL_PIN(PIN_IIC0_SDA, "iic0_sda"),
|
||||
PINCTRL_PIN(PIN_IIC0_SCL, "iic0_scl"),
|
||||
PINCTRL_PIN(PIN_IIC1_SDA, "iic1_sda"),
|
||||
PINCTRL_PIN(PIN_IIC1_SCL, "iic1_scl"),
|
||||
PINCTRL_PIN(PIN_IIC2_SDA, "iic2_sda"),
|
||||
PINCTRL_PIN(PIN_IIC2_SCL, "iic2_scl"),
|
||||
PINCTRL_PIN(PIN_IIC3_SDA, "iic3_sda"),
|
||||
PINCTRL_PIN(PIN_IIC3_SCL, "iic3_scl"),
|
||||
PINCTRL_PIN(PIN_UART0_TX, "uart0_tx"),
|
||||
PINCTRL_PIN(PIN_UART0_RX, "uart0_rx"),
|
||||
PINCTRL_PIN(PIN_UART0_RTS, "uart0_rts"),
|
||||
PINCTRL_PIN(PIN_UART0_CTS, "uart0_cts"),
|
||||
PINCTRL_PIN(PIN_UART1_TX, "uart1_tx"),
|
||||
PINCTRL_PIN(PIN_UART1_RX, "uart1_rx"),
|
||||
PINCTRL_PIN(PIN_UART1_RTS, "uart1_rts"),
|
||||
PINCTRL_PIN(PIN_UART1_CTS, "uart1_cts"),
|
||||
PINCTRL_PIN(PIN_UART2_TX, "uart2_tx"),
|
||||
PINCTRL_PIN(PIN_UART2_RX, "uart2_rx"),
|
||||
PINCTRL_PIN(PIN_UART2_RTS, "uart2_rts"),
|
||||
PINCTRL_PIN(PIN_UART2_CTS, "uart2_cts"),
|
||||
PINCTRL_PIN(PIN_UART3_TX, "uart3_tx"),
|
||||
PINCTRL_PIN(PIN_UART3_RX, "uart3_rx"),
|
||||
PINCTRL_PIN(PIN_UART3_RTS, "uart3_rts"),
|
||||
PINCTRL_PIN(PIN_UART3_CTS, "uart3_cts"),
|
||||
PINCTRL_PIN(PIN_SPI0_CS0, "spi0_cs0"),
|
||||
PINCTRL_PIN(PIN_SPI0_CS1, "spi0_cs1"),
|
||||
PINCTRL_PIN(PIN_SPI0_SDI, "spi0_sdi"),
|
||||
PINCTRL_PIN(PIN_SPI0_SDO, "spi0_sdo"),
|
||||
PINCTRL_PIN(PIN_SPI0_SCK, "spi0_sck"),
|
||||
PINCTRL_PIN(PIN_SPI1_CS0, "spi1_cs0"),
|
||||
PINCTRL_PIN(PIN_SPI1_CS1, "spi1_cs1"),
|
||||
PINCTRL_PIN(PIN_SPI1_SDI, "spi1_sdi"),
|
||||
PINCTRL_PIN(PIN_SPI1_SDO, "spi1_sdo"),
|
||||
PINCTRL_PIN(PIN_SPI1_SCK, "spi1_sck"),
|
||||
PINCTRL_PIN(PIN_JTAG0_TDO, "jtag0_tdo"),
|
||||
PINCTRL_PIN(PIN_JTAG0_TCK, "jtag0_tck"),
|
||||
PINCTRL_PIN(PIN_JTAG0_TDI, "jtag0_tdi"),
|
||||
PINCTRL_PIN(PIN_JTAG0_TMS, "jtag0_tms"),
|
||||
PINCTRL_PIN(PIN_JTAG0_TRST, "jtag0_trst"),
|
||||
PINCTRL_PIN(PIN_JTAG0_SRST, "jtag0_srst"),
|
||||
PINCTRL_PIN(PIN_JTAG1_TDO, "jtag1_tdo"),
|
||||
PINCTRL_PIN(PIN_JTAG1_TCK, "jtag1_tck"),
|
||||
PINCTRL_PIN(PIN_JTAG1_TDI, "jtag1_tdi"),
|
||||
PINCTRL_PIN(PIN_JTAG1_TMS, "jtag1_tms"),
|
||||
PINCTRL_PIN(PIN_JTAG1_TRST, "jtag1_trst"),
|
||||
PINCTRL_PIN(PIN_JTAG1_SRST, "jtag1_srst"),
|
||||
PINCTRL_PIN(PIN_JTAG2_TDO, "jtag2_tdo"),
|
||||
PINCTRL_PIN(PIN_JTAG2_TCK, "jtag2_tck"),
|
||||
PINCTRL_PIN(PIN_JTAG2_TDI, "jtag2_tdi"),
|
||||
PINCTRL_PIN(PIN_JTAG2_TMS, "jtag2_tms"),
|
||||
PINCTRL_PIN(PIN_JTAG2_TRST, "jtag2_trst"),
|
||||
PINCTRL_PIN(PIN_JTAG2_SRST, "jtag2_srst"),
|
||||
PINCTRL_PIN(PIN_JTAG3_TDO, "jtag3_tdo"),
|
||||
PINCTRL_PIN(PIN_JTAG3_TCK, "jtag3_tck"),
|
||||
PINCTRL_PIN(PIN_JTAG3_TDI, "jtag3_tdi"),
|
||||
PINCTRL_PIN(PIN_JTAG3_TMS, "jtag3_tms"),
|
||||
PINCTRL_PIN(PIN_JTAG3_TRST, "jtag3_trst"),
|
||||
PINCTRL_PIN(PIN_JTAG3_SRST, "jtag3_srst"),
|
||||
PINCTRL_PIN(PIN_GPIO0, "gpio0"),
|
||||
PINCTRL_PIN(PIN_GPIO1, "gpio1"),
|
||||
PINCTRL_PIN(PIN_GPIO2, "gpio2"),
|
||||
PINCTRL_PIN(PIN_GPIO3, "gpio3"),
|
||||
PINCTRL_PIN(PIN_GPIO4, "gpio4"),
|
||||
PINCTRL_PIN(PIN_GPIO5, "gpio5"),
|
||||
PINCTRL_PIN(PIN_GPIO6, "gpio6"),
|
||||
PINCTRL_PIN(PIN_GPIO7, "gpio7"),
|
||||
PINCTRL_PIN(PIN_GPIO8, "gpio8"),
|
||||
PINCTRL_PIN(PIN_GPIO9, "gpio9"),
|
||||
PINCTRL_PIN(PIN_GPIO10, "gpio10"),
|
||||
PINCTRL_PIN(PIN_GPIO11, "gpio11"),
|
||||
PINCTRL_PIN(PIN_GPIO12, "gpio12"),
|
||||
PINCTRL_PIN(PIN_GPIO13, "gpio13"),
|
||||
PINCTRL_PIN(PIN_GPIO14, "gpio14"),
|
||||
PINCTRL_PIN(PIN_GPIO15, "gpio15"),
|
||||
PINCTRL_PIN(PIN_GPIO16, "gpio16"),
|
||||
PINCTRL_PIN(PIN_GPIO17, "gpio17"),
|
||||
PINCTRL_PIN(PIN_GPIO18, "gpio18"),
|
||||
PINCTRL_PIN(PIN_GPIO19, "gpio19"),
|
||||
PINCTRL_PIN(PIN_GPIO20, "gpio20"),
|
||||
PINCTRL_PIN(PIN_GPIO21, "gpio21"),
|
||||
PINCTRL_PIN(PIN_GPIO22, "gpio22"),
|
||||
PINCTRL_PIN(PIN_GPIO23, "gpio23"),
|
||||
PINCTRL_PIN(PIN_GPIO24, "gpio24"),
|
||||
PINCTRL_PIN(PIN_GPIO25, "gpio25"),
|
||||
PINCTRL_PIN(PIN_GPIO26, "gpio26"),
|
||||
PINCTRL_PIN(PIN_GPIO27, "gpio27"),
|
||||
PINCTRL_PIN(PIN_GPIO28, "gpio28"),
|
||||
PINCTRL_PIN(PIN_GPIO29, "gpio29"),
|
||||
PINCTRL_PIN(PIN_GPIO30, "gpio30"),
|
||||
PINCTRL_PIN(PIN_GPIO31, "gpio31"),
|
||||
PINCTRL_PIN(PIN_MODE_SEL0, "mode_sel0"),
|
||||
PINCTRL_PIN(PIN_MODE_SEL1, "mode_sel1"),
|
||||
PINCTRL_PIN(PIN_MODE_SEL2, "mode_sel2"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL0, "boot_sel0"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL1, "boot_sel1"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL2, "boot_sel2"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL3, "boot_sel3"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL4, "boot_sel4"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL5, "boot_sel5"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL6, "boot_sel6"),
|
||||
PINCTRL_PIN(PIN_BOOT_SEL7, "boot_sel7"),
|
||||
PINCTRL_PIN(PIN_MULTI_SCKT, "multi_sckt"),
|
||||
PINCTRL_PIN(PIN_SCKT_ID0, "sckt_id0"),
|
||||
PINCTRL_PIN(PIN_SCKT_ID1, "sckt_id1"),
|
||||
PINCTRL_PIN(PIN_PLL_CLK_IN_MAIN, "pll_clk_in_main"),
|
||||
PINCTRL_PIN(PIN_PLL_CLK_IN_DDR_0, "pll_clk_in_ddr_0"),
|
||||
PINCTRL_PIN(PIN_PLL_CLK_IN_DDR_1, "pll_clk_in_ddr_1"),
|
||||
PINCTRL_PIN(PIN_PLL_CLK_IN_DDR_2, "pll_clk_in_ddr_2"),
|
||||
PINCTRL_PIN(PIN_PLL_CLK_IN_DDR_3, "pll_clk_in_ddr_3"),
|
||||
PINCTRL_PIN(PIN_XTAL_32K, "xtal_32k"),
|
||||
PINCTRL_PIN(PIN_SYS_RST, "sys_rst"),
|
||||
PINCTRL_PIN(PIN_PWR_BUTTON, "pwr_button"),
|
||||
PINCTRL_PIN(PIN_TEST_EN, "test_en"),
|
||||
PINCTRL_PIN(PIN_TEST_MODE_MBIST, "test_mode_mbist"),
|
||||
PINCTRL_PIN(PIN_TEST_MODE_SCAN, "test_mode_scan"),
|
||||
PINCTRL_PIN(PIN_TEST_MODE_BSD, "test_mode_bsd"),
|
||||
PINCTRL_PIN(PIN_BISR_BYP, "bisr_byp"),
|
||||
};
|
||||
|
||||
static const struct sg2042_pin sg2044_pin_data[ARRAY_SIZE(sg2044_pins)] = {
|
||||
SG2042_GENERAL_PIN(PIN_IIC0_SMBSUS_IN, 0x000,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_IIC0_SMBSUS_OUT, 0x000,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_IIC0_SMBALERT, 0x004,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_IIC1_SMBSUS_IN, 0x004,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_IIC1_SMBSUS_OUT, 0x008,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_IIC1_SMBALERT, 0x008,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_IIC2_SMBSUS_IN, 0x00c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_IIC2_SMBSUS_OUT, 0x00c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_IIC2_SMBALERT, 0x010,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_IIC3_SMBSUS_IN, 0x010,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_IIC3_SMBSUS_OUT, 0x014,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_IIC3_SMBALERT, 0x014,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE0_L0_RESET, 0x018,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE0_L1_RESET, 0x018,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE0_L0_WAKEUP, 0x01c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE0_L1_WAKEUP, 0x01c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE0_L0_CLKREQ_IN, 0x020,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE0_L1_CLKREQ_IN, 0x020,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE1_L0_RESET, 0x024,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE1_L1_RESET, 0x024,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE1_L0_WAKEUP, 0x028,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE1_L1_WAKEUP, 0x028,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE1_L0_CLKREQ_IN, 0x02c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE1_L1_CLKREQ_IN, 0x02c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE2_L0_RESET, 0x030,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE2_L1_RESET, 0x030,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE2_L0_WAKEUP, 0x034,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE2_L1_WAKEUP, 0x034,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE2_L0_CLKREQ_IN, 0x038,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE2_L1_CLKREQ_IN, 0x038,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE3_L0_RESET, 0x03c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE3_L1_RESET, 0x03c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE3_L0_WAKEUP, 0x040,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE3_L1_WAKEUP, 0x040,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE3_L0_CLKREQ_IN, 0x044,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE3_L1_CLKREQ_IN, 0x044,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE4_L0_RESET, 0x048,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE4_L1_RESET, 0x048,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE4_L0_WAKEUP, 0x04c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE4_L1_WAKEUP, 0x04c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE4_L0_CLKREQ_IN, 0x050,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PCIE4_L1_CLKREQ_IN, 0x050,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_CLK_SEL1, 0x054,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_CLK_SEL0, 0x054,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_WP, 0x058,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_HOLD, 0x058,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_SDI, 0x05c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_CS, 0x05c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_SCK, 0x060,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF0_SDO, 0x060,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_CLK_SEL1, 0x064,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_CLK_SEL0, 0x064,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_WP, 0x068,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_HOLD, 0x068,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_SDI, 0x06c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_CS, 0x06c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_SCK, 0x070,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SPIF1_SDO, 0x070,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_EMMC_WP, 0x074,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_EMMC_CD, 0x074,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_EMMC_RST, 0x078,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_EMMC_PWR_EN, 0x078,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SDIO_CD, 0x07c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SDIO_WP, 0x07c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SDIO_RST, 0x080,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SDIO_PWR_EN, 0x080,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_TXD0, 0x084,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_TXD1, 0x084,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_TXD2, 0x088,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_TXD3, 0x088,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_TXCTRL, 0x08c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_RXD0, 0x08c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_RXD1, 0x090,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_RXD2, 0x090,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_RXD3, 0x094,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_RXCTRL, 0x094,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_TXC, 0x098,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_RXC, 0x098,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_REFCLKO, 0x09c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_IRQ, 0x09c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_MDC, 0x0a0,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_RGMII0_MDIO, 0x0a0,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PWM0, 0x0a4,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PWM1, 0x0a4,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_PWM2, 0x0a8,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_PWM3, 0x0a8,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_FAN0, 0x0ac,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_FAN1, 0x0ac,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_FAN2, 0x0b0,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_FAN3, 0x0b0,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_IIC0_SDA, 0x0b4,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_IIC0_SCL, 0x0b4,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_IIC1_SDA, 0x0b8,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_IIC1_SCL, 0x0b8,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_IIC2_SDA, 0x0bc,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_IIC2_SCL, 0x0bc,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_IIC3_SDA, 0x0c0,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_IIC3_SCL, 0x0c0,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_UART0_TX, 0x0c4,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_UART0_RX, 0x0c4,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_UART0_RTS, 0x0c8,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_UART0_CTS, 0x0c8,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_UART1_TX, 0x0cc,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_UART1_RX, 0x0cc,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_UART1_RTS, 0x0d0,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_UART1_CTS, 0x0d0,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_UART2_TX, 0x0d4,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_UART2_RX, 0x0d4,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_UART2_RTS, 0x0d8,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_UART2_CTS, 0x0d8,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_UART3_TX, 0x0dc,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_UART3_RX, 0x0dc,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_UART3_RTS, 0x0e0,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_UART3_CTS, 0x0e0,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SPI0_CS0, 0x0e4,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SPI0_CS1, 0x0e4,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SPI0_SDI, 0x0e8,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SPI0_SDO, 0x0e8,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SPI0_SCK, 0x0ec,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SPI1_CS0, 0x0ec,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SPI1_CS1, 0x0f0,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SPI1_SDI, 0x0f0,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_SPI1_SDO, 0x0f4,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_SPI1_SCK, 0x0f4,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG0_TDO, 0x0f8,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG0_TCK, 0x0f8,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG0_TDI, 0x0fc,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG0_TMS, 0x0fc,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG0_TRST, 0x100,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG0_SRST, 0x100,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG1_TDO, 0x104,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG1_TCK, 0x104,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG1_TDI, 0x108,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG1_TMS, 0x108,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG1_TRST, 0x10c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG1_SRST, 0x10c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG2_TDO, 0x110,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG2_TCK, 0x110,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG2_TDI, 0x114,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG2_TMS, 0x114,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG2_TRST, 0x118,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG2_SRST, 0x118,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG3_TDO, 0x11c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG3_TCK, 0x11c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG3_TDI, 0x120,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG3_TMS, 0x120,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG3_TRST, 0x124,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_JTAG3_SRST, 0x124,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO0, 0x128,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO1, 0x128,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO2, 0x12c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO3, 0x12c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO4, 0x130,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO5, 0x130,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO6, 0x134,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO7, 0x134,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO8, 0x138,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO9, 0x138,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO10, 0x13c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO11, 0x13c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO12, 0x140,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO13, 0x140,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO14, 0x144,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO15, 0x144,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO16, 0x148,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO17, 0x148,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO18, 0x14c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO19, 0x14c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO20, 0x150,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO21, 0x150,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO22, 0x154,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO23, 0x154,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO24, 0x158,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO25, 0x158,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO26, 0x15c,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO27, 0x15c,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO28, 0x160,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO29, 0x160,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO30, 0x164,
|
||||
PIN_FLAG_DEFAULT),
|
||||
SG2042_GENERAL_PIN(PIN_GPIO31, 0x164,
|
||||
PIN_FLAG_WRITE_HIGH),
|
||||
SG2042_GENERAL_PIN(PIN_MODE_SEL0, 0x168,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_MODE_SEL1, 0x168,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_MODE_SEL2, 0x16c,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL0, 0x16c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL1, 0x170,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL2, 0x170,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL3, 0x174,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL4, 0x174,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL5, 0x178,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL6, 0x178,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BOOT_SEL7, 0x17c,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_MULTI_SCKT, 0x17c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_SCKT_ID0, 0x180,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_SCKT_ID1, 0x180,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_PLL_CLK_IN_MAIN, 0x184,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_PLL_CLK_IN_DDR_0, 0x184,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_PLL_CLK_IN_DDR_1, 0x188,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_PLL_CLK_IN_DDR_2, 0x188,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_PLL_CLK_IN_DDR_3, 0x18c,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_XTAL_32K, 0x18c,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_SYS_RST, 0x190,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_PWR_BUTTON, 0x190,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_TEST_EN, 0x194,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_TEST_MODE_MBIST, 0x194,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_TEST_MODE_SCAN, 0x198,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_TEST_MODE_BSD, 0x198,
|
||||
PIN_FLAG_WRITE_HIGH | PIN_FLAG_NO_PINMUX |
|
||||
PIN_FLAG_NO_OEX_EN),
|
||||
SG2042_GENERAL_PIN(PIN_BISR_BYP, 0x19c,
|
||||
PIN_FLAG_NO_PINMUX | PIN_FLAG_NO_OEX_EN),
|
||||
};
|
||||
|
||||
static const struct sophgo_pinctrl_data sg2044_pindata = {
|
||||
.pins = sg2044_pins,
|
||||
.pindata = sg2044_pin_data,
|
||||
.vddio_ops = &sg2044_vddio_cfg_ops,
|
||||
.cfg_ops = &sg2042_cfg_ops,
|
||||
.pctl_ops = &sg2042_pctrl_ops,
|
||||
.pmx_ops = &sg2042_pmx_ops,
|
||||
.pconf_ops = &sg2042_pconf_ops,
|
||||
.npins = ARRAY_SIZE(sg2044_pins),
|
||||
.pinsize = sizeof(struct sg2042_pin),
|
||||
};
|
||||
|
||||
static const struct of_device_id sg2044_pinctrl_ids[] = {
|
||||
{ .compatible = "sophgo,sg2044-pinctrl", .data = &sg2044_pindata },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sg2044_pinctrl_ids);
|
||||
|
||||
static struct platform_driver sg2044_pinctrl_driver = {
|
||||
.probe = sophgo_pinctrl_probe,
|
||||
.driver = {
|
||||
.name = "sg2044-pinctrl",
|
||||
.suppress_bind_attrs = true,
|
||||
.of_match_table = sg2044_pinctrl_ids,
|
||||
},
|
||||
};
|
||||
module_platform_driver(sg2044_pinctrl_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Pinctrl driver for the SG2002 series SoC");
|
||||
MODULE_LICENSE("GPL");
|
||||
451
drivers/pinctrl/sophgo/pinctrl-sophgo-common.c
Normal file
451
drivers/pinctrl/sophgo/pinctrl-sophgo-common.c
Normal file
@@ -0,0 +1,451 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Sophgo SoCs pinctrl common ops.
|
||||
*
|
||||
* Copyright (C) 2024 Inochi Amaoto <inochiama@outlook.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/bsearch.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "../pinctrl-utils.h"
|
||||
#include "../pinconf.h"
|
||||
#include "../pinmux.h"
|
||||
|
||||
#include "pinctrl-sophgo.h"
|
||||
|
||||
static u16 sophgo_dt_get_pin(u32 value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
static int sophgo_cmp_pin(const void *key, const void *pivot)
|
||||
{
|
||||
const struct sophgo_pin *pin = pivot;
|
||||
int pin_id = (long)key;
|
||||
int pivid = pin->id;
|
||||
|
||||
return pin_id - pivid;
|
||||
}
|
||||
|
||||
const struct sophgo_pin *sophgo_get_pin(struct sophgo_pinctrl *pctrl,
|
||||
unsigned long pin_id)
|
||||
{
|
||||
return bsearch((void *)pin_id, pctrl->data->pindata, pctrl->data->npins,
|
||||
pctrl->data->pinsize, sophgo_cmp_pin);
|
||||
}
|
||||
|
||||
static int sophgo_verify_pinmux_config(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin_mux_config *config)
|
||||
{
|
||||
if (pctrl->data->cfg_ops->verify_pinmux_config)
|
||||
return pctrl->data->cfg_ops->verify_pinmux_config(config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sophgo_verify_pin_group(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin_mux_config *config,
|
||||
unsigned int npins)
|
||||
{
|
||||
if (pctrl->data->cfg_ops->verify_pin_group)
|
||||
return pctrl->data->cfg_ops->verify_pin_group(config, npins);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sophgo_dt_node_to_map_post(struct device_node *cur,
|
||||
struct sophgo_pinctrl *pctrl,
|
||||
struct sophgo_pin_mux_config *config,
|
||||
unsigned int npins)
|
||||
{
|
||||
if (pctrl->data->cfg_ops->dt_node_to_map_post)
|
||||
return pctrl->data->cfg_ops->dt_node_to_map_post(cur, pctrl,
|
||||
config, npins);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sophgo_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *np,
|
||||
struct pinctrl_map **maps, unsigned int *num_maps)
|
||||
{
|
||||
struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct device *dev = pctrl->dev;
|
||||
struct device_node *child;
|
||||
struct pinctrl_map *map;
|
||||
const char **grpnames;
|
||||
const char *grpname;
|
||||
int ngroups = 0;
|
||||
int nmaps = 0;
|
||||
int ret;
|
||||
|
||||
for_each_available_child_of_node(np, child)
|
||||
ngroups += 1;
|
||||
|
||||
grpnames = devm_kcalloc(dev, ngroups, sizeof(*grpnames), GFP_KERNEL);
|
||||
if (!grpnames)
|
||||
return -ENOMEM;
|
||||
|
||||
map = kcalloc(ngroups * 2, sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
ngroups = 0;
|
||||
guard(mutex)(&pctrl->mutex);
|
||||
for_each_available_child_of_node(np, child) {
|
||||
int npins = of_property_count_u32_elems(child, "pinmux");
|
||||
unsigned int *pins;
|
||||
struct sophgo_pin_mux_config *pinmuxs;
|
||||
u32 config;
|
||||
int i;
|
||||
|
||||
if (npins < 1) {
|
||||
dev_err(dev, "invalid pinctrl group %pOFn.%pOFn\n",
|
||||
np, child);
|
||||
ret = -EINVAL;
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
grpname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn",
|
||||
np, child);
|
||||
if (!grpname) {
|
||||
ret = -ENOMEM;
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
grpnames[ngroups++] = grpname;
|
||||
|
||||
pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
|
||||
if (!pins) {
|
||||
ret = -ENOMEM;
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
pinmuxs = devm_kcalloc(dev, npins, sizeof(*pinmuxs), GFP_KERNEL);
|
||||
if (!pinmuxs) {
|
||||
ret = -ENOMEM;
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
for (i = 0; i < npins; i++) {
|
||||
ret = of_property_read_u32_index(child, "pinmux",
|
||||
i, &config);
|
||||
if (ret)
|
||||
goto dt_failed;
|
||||
|
||||
pins[i] = sophgo_dt_get_pin(config);
|
||||
pinmuxs[i].config = config;
|
||||
pinmuxs[i].pin = sophgo_get_pin(pctrl, pins[i]);
|
||||
|
||||
if (!pinmuxs[i].pin) {
|
||||
dev_err(dev, "failed to get pin %d\n", pins[i]);
|
||||
ret = -ENODEV;
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
ret = sophgo_verify_pinmux_config(pctrl, &pinmuxs[i]);
|
||||
if (ret) {
|
||||
dev_err(dev, "group %s pin %d is invalid\n",
|
||||
grpname, i);
|
||||
goto dt_failed;
|
||||
}
|
||||
}
|
||||
|
||||
ret = sophgo_verify_pin_group(pctrl, pinmuxs, npins);
|
||||
if (ret) {
|
||||
dev_err(dev, "group %s is invalid\n", grpname);
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
ret = sophgo_dt_node_to_map_post(child, pctrl, pinmuxs, npins);
|
||||
if (ret)
|
||||
goto dt_failed;
|
||||
|
||||
map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
map[nmaps].data.mux.function = np->name;
|
||||
map[nmaps].data.mux.group = grpname;
|
||||
nmaps += 1;
|
||||
|
||||
ret = pinconf_generic_parse_dt_config(child, pctldev,
|
||||
&map[nmaps].data.configs.configs,
|
||||
&map[nmaps].data.configs.num_configs);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to parse pin config of group %s: %d\n",
|
||||
grpname, ret);
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
ret = pinctrl_generic_add_group(pctldev, grpname,
|
||||
pins, npins, pinmuxs);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to add group %s: %d\n", grpname, ret);
|
||||
goto dt_failed;
|
||||
}
|
||||
|
||||
/* don't create a map if there are no pinconf settings */
|
||||
if (map[nmaps].data.configs.num_configs == 0)
|
||||
continue;
|
||||
|
||||
map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
|
||||
map[nmaps].data.configs.group_or_pin = grpname;
|
||||
nmaps += 1;
|
||||
}
|
||||
|
||||
ret = pinmux_generic_add_function(pctldev, np->name,
|
||||
grpnames, ngroups, NULL);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "error adding function %s: %d\n", np->name, ret);
|
||||
goto function_failed;
|
||||
}
|
||||
|
||||
*maps = map;
|
||||
*num_maps = nmaps;
|
||||
|
||||
return 0;
|
||||
|
||||
dt_failed:
|
||||
of_node_put(child);
|
||||
function_failed:
|
||||
pinctrl_utils_free_map(pctldev, map, nmaps);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sophgo_pmx_set_mux(struct pinctrl_dev *pctldev,
|
||||
unsigned int fsel, unsigned int gsel)
|
||||
{
|
||||
struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct group_desc *group;
|
||||
const struct sophgo_pin_mux_config *configs;
|
||||
unsigned int i;
|
||||
|
||||
group = pinctrl_generic_get_group(pctldev, gsel);
|
||||
if (!group)
|
||||
return -EINVAL;
|
||||
|
||||
configs = group->data;
|
||||
|
||||
for (i = 0; i < group->grp.npins; i++) {
|
||||
const struct sophgo_pin *pin = configs[i].pin;
|
||||
u32 value = configs[i].config;
|
||||
|
||||
guard(raw_spinlock_irqsave)(&pctrl->lock);
|
||||
|
||||
pctrl->data->cfg_ops->set_pinmux_config(pctrl, pin, value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sophgo_pin_set_config(struct sophgo_pinctrl *pctrl,
|
||||
unsigned int pin_id,
|
||||
u32 value, u32 mask)
|
||||
{
|
||||
const struct sophgo_pin *pin = sophgo_get_pin(pctrl, pin_id);
|
||||
|
||||
if (!pin)
|
||||
return -EINVAL;
|
||||
|
||||
guard(raw_spinlock_irqsave)(&pctrl->lock);
|
||||
|
||||
return pctrl->data->cfg_ops->set_pinconf_config(pctrl, pin, value, mask);
|
||||
}
|
||||
|
||||
int sophgo_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id,
|
||||
unsigned long *configs, unsigned int num_configs)
|
||||
{
|
||||
struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct sophgo_pin *pin = sophgo_get_pin(pctrl, pin_id);
|
||||
u32 value, mask;
|
||||
|
||||
if (!pin)
|
||||
return -ENODEV;
|
||||
|
||||
if (pctrl->data->cfg_ops->compute_pinconf_config(pctrl, pin,
|
||||
configs, num_configs,
|
||||
&value, &mask))
|
||||
return -ENOTSUPP;
|
||||
|
||||
return sophgo_pin_set_config(pctrl, pin_id, value, mask);
|
||||
}
|
||||
|
||||
int sophgo_pconf_group_set(struct pinctrl_dev *pctldev, unsigned int gsel,
|
||||
unsigned long *configs, unsigned int num_configs)
|
||||
{
|
||||
struct sophgo_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct group_desc *group;
|
||||
const struct sophgo_pin_mux_config *pinmuxs;
|
||||
u32 value, mask;
|
||||
int i;
|
||||
|
||||
group = pinctrl_generic_get_group(pctldev, gsel);
|
||||
if (!group)
|
||||
return -EINVAL;
|
||||
|
||||
pinmuxs = group->data;
|
||||
|
||||
if (pctrl->data->cfg_ops->compute_pinconf_config(pctrl, pinmuxs[0].pin,
|
||||
configs, num_configs,
|
||||
&value, &mask))
|
||||
return -ENOTSUPP;
|
||||
|
||||
for (i = 0; i < group->grp.npins; i++)
|
||||
sophgo_pin_set_config(pctrl, group->grp.pins[i], value, mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sophgo_pinctrl_typical_pull_down(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *pin,
|
||||
const u32 *power_cfg)
|
||||
{
|
||||
return pctrl->data->vddio_ops->get_pull_down(pin, power_cfg);
|
||||
}
|
||||
|
||||
u32 sophgo_pinctrl_typical_pull_up(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *pin,
|
||||
const u32 *power_cfg)
|
||||
{
|
||||
return pctrl->data->vddio_ops->get_pull_up(pin, power_cfg);
|
||||
}
|
||||
|
||||
int sophgo_pinctrl_oc2reg(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *pin,
|
||||
const u32 *power_cfg, u32 target)
|
||||
{
|
||||
const u32 *map;
|
||||
int i, len;
|
||||
|
||||
if (!pctrl->data->vddio_ops->get_oc_map)
|
||||
return -ENOTSUPP;
|
||||
|
||||
len = pctrl->data->vddio_ops->get_oc_map(pin, power_cfg, &map);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (map[i] >= target)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int sophgo_pinctrl_reg2oc(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *pin,
|
||||
const u32 *power_cfg, u32 reg)
|
||||
{
|
||||
const u32 *map;
|
||||
int len;
|
||||
|
||||
if (!pctrl->data->vddio_ops->get_oc_map)
|
||||
return -ENOTSUPP;
|
||||
|
||||
len = pctrl->data->vddio_ops->get_oc_map(pin, power_cfg, &map);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
if (reg >= len)
|
||||
return -EINVAL;
|
||||
|
||||
return map[reg];
|
||||
}
|
||||
|
||||
int sophgo_pinctrl_schmitt2reg(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *pin,
|
||||
const u32 *power_cfg, u32 target)
|
||||
{
|
||||
const u32 *map;
|
||||
int i, len;
|
||||
|
||||
if (!pctrl->data->vddio_ops->get_schmitt_map)
|
||||
return -ENOTSUPP;
|
||||
|
||||
len = pctrl->data->vddio_ops->get_schmitt_map(pin, power_cfg, &map);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (map[i] == target)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int sophgo_pinctrl_reg2schmitt(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *pin,
|
||||
const u32 *power_cfg, u32 reg)
|
||||
{
|
||||
const u32 *map;
|
||||
int len;
|
||||
|
||||
if (!pctrl->data->vddio_ops->get_schmitt_map)
|
||||
return -ENOTSUPP;
|
||||
|
||||
len = pctrl->data->vddio_ops->get_schmitt_map(pin, power_cfg, &map);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
if (reg >= len)
|
||||
return -EINVAL;
|
||||
|
||||
return map[reg];
|
||||
}
|
||||
|
||||
int sophgo_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct sophgo_pinctrl *pctrl;
|
||||
const struct sophgo_pinctrl_data *pctrl_data;
|
||||
int ret;
|
||||
|
||||
pctrl_data = device_get_match_data(dev);
|
||||
if (!pctrl_data)
|
||||
return -ENODEV;
|
||||
|
||||
if (pctrl_data->npins == 0)
|
||||
return dev_err_probe(dev, -EINVAL, "invalid pin data\n");
|
||||
|
||||
pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
|
||||
if (!pctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
pctrl->pdesc.name = dev_name(dev);
|
||||
pctrl->pdesc.pins = pctrl_data->pins;
|
||||
pctrl->pdesc.npins = pctrl_data->npins;
|
||||
pctrl->pdesc.pctlops = pctrl_data->pctl_ops;
|
||||
pctrl->pdesc.pmxops = pctrl_data->pmx_ops;
|
||||
pctrl->pdesc.confops = pctrl_data->pconf_ops;
|
||||
pctrl->pdesc.owner = THIS_MODULE;
|
||||
|
||||
pctrl->data = pctrl_data;
|
||||
pctrl->dev = dev;
|
||||
raw_spin_lock_init(&pctrl->lock);
|
||||
mutex_init(&pctrl->mutex);
|
||||
|
||||
ret = pctrl->data->cfg_ops->pctrl_init(pdev, pctrl);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, pctrl);
|
||||
|
||||
ret = devm_pinctrl_register_and_init(dev, &pctrl->pdesc,
|
||||
pctrl, &pctrl->pctrl_dev);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"fail to register pinctrl driver\n");
|
||||
|
||||
return pinctrl_enable(pctrl->pctrl_dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sophgo_pinctrl_probe);
|
||||
|
||||
MODULE_DESCRIPTION("Common pinctrl helper function for the Sophgo SoC");
|
||||
MODULE_LICENSE("GPL");
|
||||
136
drivers/pinctrl/sophgo/pinctrl-sophgo.h
Normal file
136
drivers/pinctrl/sophgo/pinctrl-sophgo.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2024 Inochi Amaoto <inochiama@outlook.com>
|
||||
*/
|
||||
|
||||
#ifndef _PINCTRL_SOPHGO_H
|
||||
#define _PINCTRL_SOPHGO_H
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "../core.h"
|
||||
|
||||
struct sophgo_pinctrl;
|
||||
|
||||
struct sophgo_pin {
|
||||
u16 id;
|
||||
u16 flags;
|
||||
};
|
||||
|
||||
struct sophgo_pin_mux_config {
|
||||
const struct sophgo_pin *pin;
|
||||
u32 config;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sophgo_cfg_ops - pin configuration operations
|
||||
*
|
||||
* @pctrl_init: soc specific init callback
|
||||
* @verify_pinmux_config: verify the pinmux config for a pin
|
||||
* @verify_pin_group: verify the whole pinmux group
|
||||
* @dt_node_to_map_post: post init for the pinmux config map
|
||||
* @compute_pinconf_config: compute pinconf config
|
||||
* @set_pinconf_config: set pinconf config (the caller holds lock)
|
||||
* @set_pinmux_config: set mux config (the caller holds lock)
|
||||
*/
|
||||
struct sophgo_cfg_ops {
|
||||
int (*pctrl_init)(struct platform_device *pdev,
|
||||
struct sophgo_pinctrl *pctrl);
|
||||
int (*verify_pinmux_config)(const struct sophgo_pin_mux_config *config);
|
||||
int (*verify_pin_group)(const struct sophgo_pin_mux_config *pinmuxs,
|
||||
unsigned int npins);
|
||||
int (*dt_node_to_map_post)(struct device_node *cur,
|
||||
struct sophgo_pinctrl *pctrl,
|
||||
struct sophgo_pin_mux_config *pinmuxs,
|
||||
unsigned int npins);
|
||||
int (*compute_pinconf_config)(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *sp,
|
||||
unsigned long *configs,
|
||||
unsigned int num_configs,
|
||||
u32 *value, u32 *mask);
|
||||
int (*set_pinconf_config)(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *sp,
|
||||
u32 value, u32 mask);
|
||||
void (*set_pinmux_config)(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *sp, u32 config);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sophgo_vddio_cfg_ops - pin vddio operations
|
||||
*
|
||||
* @get_pull_up: get resistor for pull up;
|
||||
* @get_pull_down: get resistor for pull down.
|
||||
* @get_oc_map: get mapping for typical low level output current value to
|
||||
* register value map.
|
||||
* @get_schmitt_map: get mapping for register value to typical schmitt
|
||||
* threshold.
|
||||
*/
|
||||
struct sophgo_vddio_cfg_ops {
|
||||
int (*get_pull_up)(const struct sophgo_pin *pin, const u32 *psmap);
|
||||
int (*get_pull_down)(const struct sophgo_pin *pin, const u32 *psmap);
|
||||
int (*get_oc_map)(const struct sophgo_pin *pin, const u32 *psmap,
|
||||
const u32 **map);
|
||||
int (*get_schmitt_map)(const struct sophgo_pin *pin, const u32 *psmap,
|
||||
const u32 **map);
|
||||
};
|
||||
|
||||
struct sophgo_pinctrl_data {
|
||||
const struct pinctrl_pin_desc *pins;
|
||||
const void *pindata;
|
||||
const char * const *pdnames;
|
||||
const struct sophgo_vddio_cfg_ops *vddio_ops;
|
||||
const struct sophgo_cfg_ops *cfg_ops;
|
||||
const struct pinctrl_ops *pctl_ops;
|
||||
const struct pinmux_ops *pmx_ops;
|
||||
const struct pinconf_ops *pconf_ops;
|
||||
u16 npins;
|
||||
u16 npds;
|
||||
u16 pinsize;
|
||||
};
|
||||
|
||||
struct sophgo_pinctrl {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pctrl_dev;
|
||||
const struct sophgo_pinctrl_data *data;
|
||||
struct pinctrl_desc pdesc;
|
||||
|
||||
struct mutex mutex;
|
||||
raw_spinlock_t lock;
|
||||
void *priv_ctrl;
|
||||
};
|
||||
|
||||
const struct sophgo_pin *sophgo_get_pin(struct sophgo_pinctrl *pctrl,
|
||||
unsigned long pin_id);
|
||||
int sophgo_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *np,
|
||||
struct pinctrl_map **maps, unsigned int *num_maps);
|
||||
int sophgo_pmx_set_mux(struct pinctrl_dev *pctldev,
|
||||
unsigned int fsel, unsigned int gsel);
|
||||
int sophgo_pconf_set(struct pinctrl_dev *pctldev, unsigned int pin_id,
|
||||
unsigned long *configs, unsigned int num_configs);
|
||||
int sophgo_pconf_group_set(struct pinctrl_dev *pctldev, unsigned int gsel,
|
||||
unsigned long *configs, unsigned int num_configs);
|
||||
u32 sophgo_pinctrl_typical_pull_down(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *pin,
|
||||
const u32 *power_cfg);
|
||||
u32 sophgo_pinctrl_typical_pull_up(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *pin,
|
||||
const u32 *power_cfg);
|
||||
int sophgo_pinctrl_oc2reg(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *pin,
|
||||
const u32 *power_cfg, u32 target);
|
||||
int sophgo_pinctrl_reg2oc(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *pin,
|
||||
const u32 *power_cfg, u32 reg);
|
||||
int sophgo_pinctrl_schmitt2reg(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *pin,
|
||||
const u32 *power_cfg, u32 target);
|
||||
int sophgo_pinctrl_reg2schmitt(struct sophgo_pinctrl *pctrl,
|
||||
const struct sophgo_pin *pin,
|
||||
const u32 *power_cfg, u32 reg);
|
||||
int sophgo_pinctrl_probe(struct platform_device *pdev);
|
||||
|
||||
#endif /* _PINCTRL_SOPHGO_H */
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
@@ -749,7 +750,10 @@ static int spacemit_pinctrl_probe(struct platform_device *pdev)
|
||||
pctrl->data = pctrl_data;
|
||||
pctrl->dev = dev;
|
||||
raw_spin_lock_init(&pctrl->lock);
|
||||
mutex_init(&pctrl->mutex);
|
||||
|
||||
ret = devm_mutex_init(dev, &pctrl->mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, pctrl);
|
||||
|
||||
|
||||
@@ -131,4 +131,14 @@ config PINCTRL_SUN50I_H616_R
|
||||
default ARM64 && ARCH_SUNXI
|
||||
select PINCTRL_SUNXI
|
||||
|
||||
config PINCTRL_SUN55I_A523
|
||||
bool "Support for the Allwinner A523 PIO"
|
||||
default ARM64 && ARCH_SUNXI
|
||||
select PINCTRL_SUNXI
|
||||
|
||||
config PINCTRL_SUN55I_A523_R
|
||||
bool "Support for the Allwinner A523 R-PIO"
|
||||
default ARM64 && ARCH_SUNXI
|
||||
select PINCTRL_SUNXI
|
||||
|
||||
endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Core
|
||||
obj-y += pinctrl-sunxi.o
|
||||
obj-y += pinctrl-sunxi-dt.o
|
||||
|
||||
# SoC Drivers
|
||||
obj-$(CONFIG_PINCTRL_SUNIV_F1C100S) += pinctrl-suniv-f1c100s.o
|
||||
@@ -26,5 +27,7 @@ obj-$(CONFIG_PINCTRL_SUN50I_H6) += pinctrl-sun50i-h6.o
|
||||
obj-$(CONFIG_PINCTRL_SUN50I_H6_R) += pinctrl-sun50i-h6-r.o
|
||||
obj-$(CONFIG_PINCTRL_SUN50I_H616) += pinctrl-sun50i-h616.o
|
||||
obj-$(CONFIG_PINCTRL_SUN50I_H616_R) += pinctrl-sun50i-h616-r.o
|
||||
obj-$(CONFIG_PINCTRL_SUN55I_A523) += pinctrl-sun55i-a523.o
|
||||
obj-$(CONFIG_PINCTRL_SUN55I_A523_R) += pinctrl-sun55i-a523-r.o
|
||||
obj-$(CONFIG_PINCTRL_SUN9I_A80) += pinctrl-sun9i-a80.o
|
||||
obj-$(CONFIG_PINCTRL_SUN9I_A80_R) += pinctrl-sun9i-a80-r.o
|
||||
|
||||
@@ -820,15 +820,13 @@ static const struct sunxi_pinctrl_desc d1_pinctrl_data = {
|
||||
|
||||
static int d1_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
|
||||
|
||||
return sunxi_pinctrl_init_with_variant(pdev, &d1_pinctrl_data, variant);
|
||||
return sunxi_pinctrl_init_with_flags(pdev, &d1_pinctrl_data,
|
||||
SUNXI_PINCTRL_NEW_REG_LAYOUT);
|
||||
}
|
||||
|
||||
static const struct of_device_id d1_pinctrl_match[] = {
|
||||
{
|
||||
.compatible = "allwinner,sun20i-d1-pinctrl",
|
||||
.data = (void *)PINCTRL_SUN20I_D1
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
#include "pinctrl-sunxi.h"
|
||||
|
||||
#define PINCTRL_SUN4I_A10 BIT(0)
|
||||
#define PINCTRL_SUN7I_A20 BIT(1)
|
||||
#define PINCTRL_SUN8I_R40 BIT(2)
|
||||
|
||||
static const struct sunxi_desc_pin sun4i_a10_pins[] = {
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
@@ -1295,8 +1299,8 @@ static int sun4i_a10_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
|
||||
|
||||
return sunxi_pinctrl_init_with_variant(pdev, &sun4i_a10_pinctrl_data,
|
||||
variant);
|
||||
return sunxi_pinctrl_init_with_flags(pdev, &sun4i_a10_pinctrl_data,
|
||||
variant);
|
||||
}
|
||||
|
||||
static const struct of_device_id sun4i_a10_pinctrl_match[] = {
|
||||
|
||||
54
drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c
Normal file
54
drivers/pinctrl/sunxi/pinctrl-sun55i-a523-r.c
Normal file
@@ -0,0 +1,54 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Allwinner A523 SoC r-pinctrl driver.
|
||||
*
|
||||
* Copyright (C) 2024 Arm Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-sunxi.h"
|
||||
|
||||
static const u8 a523_r_nr_bank_pins[SUNXI_PINCTRL_MAX_BANKS] =
|
||||
/* PL PM */
|
||||
{ 14, 6 };
|
||||
|
||||
static const unsigned int a523_r_irq_bank_map[] = { 0, 1 };
|
||||
|
||||
static const u8 a523_r_irq_bank_muxes[SUNXI_PINCTRL_MAX_BANKS] =
|
||||
/* PL PM */
|
||||
{ 14, 14 };
|
||||
|
||||
static struct sunxi_pinctrl_desc a523_r_pinctrl_data = {
|
||||
.irq_banks = ARRAY_SIZE(a523_r_irq_bank_map),
|
||||
.irq_bank_map = a523_r_irq_bank_map,
|
||||
.irq_read_needs_mux = true,
|
||||
.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
|
||||
.pin_base = PL_BASE,
|
||||
};
|
||||
|
||||
static int a523_r_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
return sunxi_pinctrl_dt_table_init(pdev, a523_r_nr_bank_pins,
|
||||
a523_r_irq_bank_muxes,
|
||||
&a523_r_pinctrl_data,
|
||||
SUNXI_PINCTRL_NEW_REG_LAYOUT);
|
||||
}
|
||||
|
||||
static const struct of_device_id a523_r_pinctrl_match[] = {
|
||||
{ .compatible = "allwinner,sun55i-a523-r-pinctrl", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver a523_r_pinctrl_driver = {
|
||||
.probe = a523_r_pinctrl_probe,
|
||||
.driver = {
|
||||
.name = "sun55i-a523-r-pinctrl",
|
||||
.of_match_table = a523_r_pinctrl_match,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(a523_r_pinctrl_driver);
|
||||
54
drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c
Normal file
54
drivers/pinctrl/sunxi/pinctrl-sun55i-a523.c
Normal file
@@ -0,0 +1,54 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Allwinner A523 SoC pinctrl driver.
|
||||
*
|
||||
* Copyright (C) 2023 Arm Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-sunxi.h"
|
||||
|
||||
static const u8 a523_nr_bank_pins[SUNXI_PINCTRL_MAX_BANKS] =
|
||||
/* PA PB PC PD PE PF PG PH PI PJ PK */
|
||||
{ 0, 15, 17, 24, 16, 7, 15, 20, 17, 28, 24 };
|
||||
|
||||
static const unsigned int a523_irq_bank_map[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
|
||||
static const u8 a523_irq_bank_muxes[SUNXI_PINCTRL_MAX_BANKS] =
|
||||
/* PA PB PC PD PE PF PG PH PI PJ PK */
|
||||
{ 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14};
|
||||
|
||||
static struct sunxi_pinctrl_desc a523_pinctrl_data = {
|
||||
.irq_banks = ARRAY_SIZE(a523_irq_bank_map),
|
||||
.irq_bank_map = a523_irq_bank_map,
|
||||
.irq_read_needs_mux = true,
|
||||
.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
|
||||
};
|
||||
|
||||
static int a523_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
return sunxi_pinctrl_dt_table_init(pdev, a523_nr_bank_pins,
|
||||
a523_irq_bank_muxes,
|
||||
&a523_pinctrl_data,
|
||||
SUNXI_PINCTRL_NEW_REG_LAYOUT |
|
||||
SUNXI_PINCTRL_ELEVEN_BANKS);
|
||||
}
|
||||
|
||||
static const struct of_device_id a523_pinctrl_match[] = {
|
||||
{ .compatible = "allwinner,sun55i-a523-pinctrl", },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver a523_pinctrl_driver = {
|
||||
.probe = a523_pinctrl_probe,
|
||||
.driver = {
|
||||
.name = "sun55i-a523-pinctrl",
|
||||
.of_match_table = a523_pinctrl_match,
|
||||
},
|
||||
};
|
||||
builtin_platform_driver(a523_pinctrl_driver);
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
#include "pinctrl-sunxi.h"
|
||||
|
||||
#define PINCTRL_SUN5I_A10S BIT(0)
|
||||
#define PINCTRL_SUN5I_A13 BIT(1)
|
||||
#define PINCTRL_SUN5I_GR8 BIT(2)
|
||||
|
||||
static const struct sunxi_desc_pin sun5i_pins[] = {
|
||||
SUNXI_PIN_VARIANT(SUNXI_PINCTRL_PIN(A, 0),
|
||||
PINCTRL_SUN5I_A10S,
|
||||
@@ -719,8 +723,8 @@ static int sun5i_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
|
||||
|
||||
return sunxi_pinctrl_init_with_variant(pdev, &sun5i_pinctrl_data,
|
||||
variant);
|
||||
return sunxi_pinctrl_init_with_flags(pdev, &sun5i_pinctrl_data,
|
||||
variant);
|
||||
}
|
||||
|
||||
static const struct of_device_id sun5i_pinctrl_match[] = {
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
#include "pinctrl-sunxi.h"
|
||||
|
||||
#define PINCTRL_SUN6I_A31 BIT(0)
|
||||
#define PINCTRL_SUN6I_A31S BIT(1)
|
||||
|
||||
static const struct sunxi_desc_pin sun6i_a31_pins[] = {
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
@@ -972,9 +975,8 @@ static int sun6i_a31_pinctrl_probe(struct platform_device *pdev)
|
||||
unsigned long variant =
|
||||
(unsigned long)of_device_get_match_data(&pdev->dev);
|
||||
|
||||
return sunxi_pinctrl_init_with_variant(pdev,
|
||||
&sun6i_a31_pinctrl_data,
|
||||
variant);
|
||||
return sunxi_pinctrl_init_with_flags(pdev, &sun6i_a31_pinctrl_data,
|
||||
variant);
|
||||
}
|
||||
|
||||
static const struct of_device_id sun6i_a31_pinctrl_match[] = {
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
|
||||
#include "pinctrl-sunxi.h"
|
||||
|
||||
#define PINCTRL_SUN8I_V3 BIT(0)
|
||||
#define PINCTRL_SUN8I_V3S BIT(1)
|
||||
|
||||
static const struct sunxi_desc_pin sun8i_v3s_pins[] = {
|
||||
/* Hole */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0),
|
||||
@@ -552,8 +555,8 @@ static int sun8i_v3s_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
unsigned long variant = (unsigned long)of_device_get_match_data(&pdev->dev);
|
||||
|
||||
return sunxi_pinctrl_init_with_variant(pdev, &sun8i_v3s_pinctrl_data,
|
||||
variant);
|
||||
return sunxi_pinctrl_init_with_flags(pdev, &sun8i_v3s_pinctrl_data,
|
||||
variant);
|
||||
}
|
||||
|
||||
static const struct of_device_id sun8i_v3s_pinctrl_match[] = {
|
||||
|
||||
374
drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c
Normal file
374
drivers/pinctrl/sunxi/pinctrl-sunxi-dt.c
Normal file
@@ -0,0 +1,374 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2017-2025 Arm Ltd.
|
||||
*
|
||||
* Generic DT driven Allwinner pinctrl driver routines.
|
||||
* Builds the pin tables from minimal driver information and pin groups
|
||||
* described in the DT. Then hands those tables of to the traditional
|
||||
* sunxi pinctrl driver.
|
||||
* sunxi_pinctrl_init() expects a table like shown below, previously spelled
|
||||
* out in a per-SoC .c file. This code generates this table, like so:
|
||||
*
|
||||
* SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1), // code iterates over every implemented
|
||||
* // pin, based on pins_per_bank[] array passed in
|
||||
*
|
||||
* SUNXI_FUNCTION(0x0, "gpio_in"), // always added, for every pin
|
||||
* SUNXI_FUNCTION(0x1, "gpio_out"), // always added, for every pin
|
||||
*
|
||||
* SUNXI_FUNCTION(0x2, "mmc0"), // based on pingroup found in DT:
|
||||
* // mmc0-pins {
|
||||
* // pins = "PF0", "PF1", ...
|
||||
* // function = "mmc0";
|
||||
* // allwinner,pinmux = <2>;
|
||||
*
|
||||
* SUNXI_FUNCTION_IRQ_BANK(0x6, 4, 1)), // derived by irq_bank_muxes[]
|
||||
* // array passed in
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "pinctrl-sunxi.h"
|
||||
|
||||
#define INVALID_MUX 0xff
|
||||
|
||||
/*
|
||||
* Return the "index"th element from the "allwinner,pinmux" property. If the
|
||||
* property does not hold enough entries, return the last one instead.
|
||||
* For almost every group the pinmux value is actually the same, so this
|
||||
* allows to just list one value in the property.
|
||||
*/
|
||||
static u8 sunxi_pinctrl_dt_read_pinmux(const struct device_node *node,
|
||||
int index)
|
||||
{
|
||||
int ret, num_elems;
|
||||
u32 value;
|
||||
|
||||
num_elems = of_property_count_u32_elems(node, "allwinner,pinmux");
|
||||
if (num_elems <= 0)
|
||||
return INVALID_MUX;
|
||||
|
||||
if (index >= num_elems)
|
||||
index = num_elems - 1;
|
||||
|
||||
ret = of_property_read_u32_index(node, "allwinner,pinmux", index,
|
||||
&value);
|
||||
if (ret)
|
||||
return INVALID_MUX;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a table with a sunxi_desc_pin structure for every pin needed.
|
||||
* Fills in the respective pin names ("PA0") and their pin numbers.
|
||||
* Returns the pins array. We cannot use the member in *desc yet, as this
|
||||
* is marked as const, and we will need to change the array still.
|
||||
*/
|
||||
static struct sunxi_desc_pin *init_pins_table(struct device *dev,
|
||||
const u8 *pins_per_bank,
|
||||
struct sunxi_pinctrl_desc *desc)
|
||||
{
|
||||
struct sunxi_desc_pin *pins, *cur_pin;
|
||||
int name_size = 0;
|
||||
int port_base = desc->pin_base / PINS_PER_BANK;
|
||||
char *pin_names, *cur_name;
|
||||
int i, j;
|
||||
|
||||
/*
|
||||
* Find the total number of pins.
|
||||
* Also work out how much memory we need to store all the pin names.
|
||||
*/
|
||||
for (i = 0; i < SUNXI_PINCTRL_MAX_BANKS; i++) {
|
||||
desc->npins += pins_per_bank[i];
|
||||
if (pins_per_bank[i] < 10) {
|
||||
/* 4 bytes for "PXy\0" */
|
||||
name_size += pins_per_bank[i] * 4;
|
||||
} else {
|
||||
/* 4 bytes for each "PXy\0" */
|
||||
name_size += 10 * 4;
|
||||
|
||||
/* 5 bytes for each "PXyy\0" */
|
||||
name_size += (pins_per_bank[i] - 10) * 5;
|
||||
}
|
||||
}
|
||||
|
||||
if (desc->npins == 0) {
|
||||
dev_err(dev, "no ports defined\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
pins = devm_kzalloc(dev, desc->npins * sizeof(*pins), GFP_KERNEL);
|
||||
if (!pins)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* Allocate memory to store the name for every pin. */
|
||||
pin_names = devm_kmalloc(dev, name_size, GFP_KERNEL);
|
||||
if (!pin_names)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* Fill the pins array with the name and the number for each pin. */
|
||||
cur_name = pin_names;
|
||||
cur_pin = pins;
|
||||
for (i = 0; i < SUNXI_PINCTRL_MAX_BANKS; i++) {
|
||||
for (j = 0; j < pins_per_bank[i]; j++, cur_pin++) {
|
||||
int nchars = sprintf(cur_name, "P%c%d",
|
||||
port_base + 'A' + i, j);
|
||||
|
||||
cur_pin->pin.number = (port_base + i) * PINS_PER_BANK + j;
|
||||
cur_pin->pin.name = cur_name;
|
||||
cur_name += nchars + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return pins;
|
||||
}
|
||||
|
||||
/*
|
||||
* Work out the number of functions for each pin. This will visit every
|
||||
* child node of the pinctrl DT node to find all advertised functions.
|
||||
* Provide memory to hold the per-function information and assign it to
|
||||
* the pin table.
|
||||
* Fill in the GPIO in/out functions already (that every pin has), also add
|
||||
* an "irq" function at the end, for those pins in IRQ-capable ports.
|
||||
* We do not fill in the extra functions (those describe in DT nodes) yet.
|
||||
* We (ab)use the "variant" member in each pin to keep track of the number of
|
||||
* extra functions needed. At the end this will get reset to 2, so that we
|
||||
* can add extra function later, after the two GPIO functions.
|
||||
*/
|
||||
static int prepare_function_table(struct device *dev, struct device_node *pnode,
|
||||
struct sunxi_desc_pin *pins, int npins,
|
||||
const u8 *irq_bank_muxes)
|
||||
{
|
||||
struct device_node *node;
|
||||
struct property *prop;
|
||||
struct sunxi_desc_function *func;
|
||||
int num_funcs, irq_bank, last_bank, i;
|
||||
|
||||
/*
|
||||
* We need at least three functions per pin:
|
||||
* - one for GPIO in
|
||||
* - one for GPIO out
|
||||
* - one for the sentinel signalling the end of the list
|
||||
*/
|
||||
num_funcs = 3 * npins;
|
||||
|
||||
/*
|
||||
* Add a function for each pin in a bank supporting interrupts.
|
||||
* We temporarily (ab)use the variant field to store the number of
|
||||
* functions per pin. This will be cleaned back to 0 before we hand
|
||||
* over the whole structure to the generic sunxi pinctrl setup code.
|
||||
*/
|
||||
for (i = 0; i < npins; i++) {
|
||||
struct sunxi_desc_pin *pin = &pins[i];
|
||||
int bank = pin->pin.number / PINS_PER_BANK;
|
||||
|
||||
if (irq_bank_muxes[bank]) {
|
||||
pin->variant++;
|
||||
num_funcs++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Go over each pin group (every child of the pinctrl DT node) and
|
||||
* add the number of special functions each pins has. Also update the
|
||||
* total number of functions required.
|
||||
* We might slightly overshoot here in case of double definitions.
|
||||
*/
|
||||
for_each_child_of_node(pnode, node) {
|
||||
const char *name;
|
||||
|
||||
of_property_for_each_string(node, "pins", prop, name) {
|
||||
for (i = 0; i < npins; i++) {
|
||||
if (strcmp(pins[i].pin.name, name))
|
||||
continue;
|
||||
|
||||
pins[i].variant++;
|
||||
num_funcs++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the memory needed for the functions in one table.
|
||||
* We later use pointers into this table to mark each pin.
|
||||
*/
|
||||
func = devm_kzalloc(dev, num_funcs * sizeof(*func), GFP_KERNEL);
|
||||
if (!func)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Assign the function's memory and fill in GPIOs, IRQ and a sentinel.
|
||||
* The extra functions will be filled in later.
|
||||
*/
|
||||
irq_bank = 0;
|
||||
last_bank = 0;
|
||||
for (i = 0; i < npins; i++) {
|
||||
struct sunxi_desc_pin *pin = &pins[i];
|
||||
int bank = pin->pin.number / PINS_PER_BANK;
|
||||
int lastfunc = pin->variant + 1;
|
||||
int irq_mux = irq_bank_muxes[bank];
|
||||
|
||||
func[0].name = "gpio_in";
|
||||
func[0].muxval = 0;
|
||||
func[1].name = "gpio_out";
|
||||
func[1].muxval = 1;
|
||||
|
||||
if (irq_mux) {
|
||||
if (bank > last_bank)
|
||||
irq_bank++;
|
||||
func[lastfunc].muxval = irq_mux;
|
||||
func[lastfunc].irqbank = irq_bank;
|
||||
func[lastfunc].irqnum = pin->pin.number % PINS_PER_BANK;
|
||||
func[lastfunc].name = "irq";
|
||||
}
|
||||
|
||||
if (bank > last_bank)
|
||||
last_bank = bank;
|
||||
|
||||
pin->functions = func;
|
||||
|
||||
/* Skip over the other needed functions and the sentinel. */
|
||||
func += pin->variant + 3;
|
||||
|
||||
/*
|
||||
* Reset the value for filling in the remaining functions
|
||||
* behind the GPIOs later.
|
||||
*/
|
||||
pin->variant = 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over all pins in a single group and add the function name and its
|
||||
* mux value to the respective pin.
|
||||
* The "variant" member is again used to temporarily track the number of
|
||||
* already added functions.
|
||||
*/
|
||||
static void fill_pin_function(struct device *dev, struct device_node *node,
|
||||
struct sunxi_desc_pin *pins, int npins)
|
||||
{
|
||||
const char *name, *funcname;
|
||||
struct sunxi_desc_function *func;
|
||||
struct property *prop;
|
||||
int pin, i, index;
|
||||
u8 muxval;
|
||||
|
||||
if (of_property_read_string(node, "function", &funcname)) {
|
||||
dev_warn(dev, "missing \"function\" property\n");
|
||||
return;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
of_property_for_each_string(node, "pins", prop, name) {
|
||||
/* Find the index of this pin in our table. */
|
||||
for (pin = 0; pin < npins; pin++)
|
||||
if (!strcmp(pins[pin].pin.name, name))
|
||||
break;
|
||||
if (pin == npins) {
|
||||
dev_warn(dev, "%s: cannot find pin %s\n",
|
||||
of_node_full_name(node), name);
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Read the associated mux value. */
|
||||
muxval = sunxi_pinctrl_dt_read_pinmux(node, index);
|
||||
if (muxval == INVALID_MUX) {
|
||||
dev_warn(dev, "%s: invalid mux value for pin %s\n",
|
||||
of_node_full_name(node), name);
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for double definitions by comparing the to-be-added
|
||||
* function with already assigned ones.
|
||||
* Ignore identical pairs (function name and mux value the
|
||||
* same), but warn about conflicting assignments.
|
||||
*/
|
||||
for (i = 2; i < pins[pin].variant; i++) {
|
||||
func = &pins[pin].functions[i];
|
||||
|
||||
/* Skip over totally unrelated functions. */
|
||||
if (strcmp(func->name, funcname) &&
|
||||
func->muxval != muxval)
|
||||
continue;
|
||||
|
||||
/* Ignore (but skip below) any identical functions. */
|
||||
if (!strcmp(func->name, funcname) &&
|
||||
muxval == func->muxval)
|
||||
break;
|
||||
|
||||
dev_warn(dev,
|
||||
"pin %s: function %s redefined to mux %d\n",
|
||||
name, funcname, muxval);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip any pins with that function already assigned. */
|
||||
if (i < pins[pin].variant) {
|
||||
index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Assign function and muxval to the next free slot. */
|
||||
func = &pins[pin].functions[pins[pin].variant];
|
||||
func->muxval = muxval;
|
||||
func->name = funcname;
|
||||
|
||||
pins[pin].variant++;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the pinctrl table, by building it from driver provided
|
||||
* information: the number of pins per bank, the IRQ capable banks and their
|
||||
* IRQ mux value.
|
||||
* Then iterate over all pinctrl DT node children to enter the function name
|
||||
* and mux values for each mentioned pin.
|
||||
* At the end hand over this structure to the actual sunxi pinctrl driver.
|
||||
*/
|
||||
int sunxi_pinctrl_dt_table_init(struct platform_device *pdev,
|
||||
const u8 *pins_per_bank,
|
||||
const u8 *irq_bank_muxes,
|
||||
struct sunxi_pinctrl_desc *desc,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct device_node *pnode = pdev->dev.of_node, *node;
|
||||
struct sunxi_desc_pin *pins;
|
||||
int ret, i;
|
||||
|
||||
pins = init_pins_table(&pdev->dev, pins_per_bank, desc);
|
||||
if (IS_ERR(pins))
|
||||
return PTR_ERR(pins);
|
||||
|
||||
ret = prepare_function_table(&pdev->dev, pnode, pins, desc->npins,
|
||||
irq_bank_muxes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Now iterate over all groups and add the respective function name
|
||||
* and mux values to each pin listed within.
|
||||
*/
|
||||
for_each_child_of_node(pnode, node)
|
||||
fill_pin_function(&pdev->dev, node, pins, desc->npins);
|
||||
|
||||
/* Clear the temporary storage. */
|
||||
for (i = 0; i < desc->npins; i++)
|
||||
pins[i].variant = 0;
|
||||
|
||||
desc->pins = pins;
|
||||
|
||||
return sunxi_pinctrl_init_with_flags(pdev, desc, flags);
|
||||
}
|
||||
@@ -58,13 +58,29 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip;
|
||||
* The following functions calculate the register and the bit offset to access.
|
||||
* They take a pin number which is relative to the start of the current device.
|
||||
*/
|
||||
|
||||
/*
|
||||
* When using the extended register layout, Bank K does not fit into the
|
||||
* space used for the other banks. Instead it lives at offset 0x500.
|
||||
*/
|
||||
static u32 sunxi_bank_offset(const struct sunxi_pinctrl *pctl, u32 pin)
|
||||
{
|
||||
u32 offset = 0;
|
||||
|
||||
if (pin >= PK_BASE) {
|
||||
pin -= PK_BASE;
|
||||
offset = PIO_BANK_K_OFFSET;
|
||||
}
|
||||
|
||||
return offset + (pin / PINS_PER_BANK) * pctl->bank_mem_size;
|
||||
}
|
||||
|
||||
static void sunxi_mux_reg(const struct sunxi_pinctrl *pctl,
|
||||
u32 pin, u32 *reg, u32 *shift, u32 *mask)
|
||||
{
|
||||
u32 bank = pin / PINS_PER_BANK;
|
||||
u32 offset = pin % PINS_PER_BANK * MUX_FIELD_WIDTH;
|
||||
|
||||
*reg = bank * pctl->bank_mem_size + MUX_REGS_OFFSET +
|
||||
*reg = sunxi_bank_offset(pctl, pin) + MUX_REGS_OFFSET +
|
||||
offset / BITS_PER_TYPE(u32) * sizeof(u32);
|
||||
*shift = offset % BITS_PER_TYPE(u32);
|
||||
*mask = (BIT(MUX_FIELD_WIDTH) - 1) << *shift;
|
||||
@@ -73,10 +89,9 @@ static void sunxi_mux_reg(const struct sunxi_pinctrl *pctl,
|
||||
static void sunxi_data_reg(const struct sunxi_pinctrl *pctl,
|
||||
u32 pin, u32 *reg, u32 *shift, u32 *mask)
|
||||
{
|
||||
u32 bank = pin / PINS_PER_BANK;
|
||||
u32 offset = pin % PINS_PER_BANK * DATA_FIELD_WIDTH;
|
||||
|
||||
*reg = bank * pctl->bank_mem_size + DATA_REGS_OFFSET +
|
||||
*reg = sunxi_bank_offset(pctl, pin) + DATA_REGS_OFFSET +
|
||||
offset / BITS_PER_TYPE(u32) * sizeof(u32);
|
||||
*shift = offset % BITS_PER_TYPE(u32);
|
||||
*mask = (BIT(DATA_FIELD_WIDTH) - 1) << *shift;
|
||||
@@ -85,10 +100,9 @@ static void sunxi_data_reg(const struct sunxi_pinctrl *pctl,
|
||||
static void sunxi_dlevel_reg(const struct sunxi_pinctrl *pctl,
|
||||
u32 pin, u32 *reg, u32 *shift, u32 *mask)
|
||||
{
|
||||
u32 bank = pin / PINS_PER_BANK;
|
||||
u32 offset = pin % PINS_PER_BANK * pctl->dlevel_field_width;
|
||||
|
||||
*reg = bank * pctl->bank_mem_size + DLEVEL_REGS_OFFSET +
|
||||
*reg = sunxi_bank_offset(pctl, pin) + DLEVEL_REGS_OFFSET +
|
||||
offset / BITS_PER_TYPE(u32) * sizeof(u32);
|
||||
*shift = offset % BITS_PER_TYPE(u32);
|
||||
*mask = (BIT(pctl->dlevel_field_width) - 1) << *shift;
|
||||
@@ -97,10 +111,9 @@ static void sunxi_dlevel_reg(const struct sunxi_pinctrl *pctl,
|
||||
static void sunxi_pull_reg(const struct sunxi_pinctrl *pctl,
|
||||
u32 pin, u32 *reg, u32 *shift, u32 *mask)
|
||||
{
|
||||
u32 bank = pin / PINS_PER_BANK;
|
||||
u32 offset = pin % PINS_PER_BANK * PULL_FIELD_WIDTH;
|
||||
|
||||
*reg = bank * pctl->bank_mem_size + pctl->pull_regs_offset +
|
||||
*reg = sunxi_bank_offset(pctl, pin) + pctl->pull_regs_offset +
|
||||
offset / BITS_PER_TYPE(u32) * sizeof(u32);
|
||||
*shift = offset % BITS_PER_TYPE(u32);
|
||||
*mask = (BIT(PULL_FIELD_WIDTH) - 1) << *shift;
|
||||
@@ -723,9 +736,11 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
|
||||
val = uV > 1800000 && uV <= 2500000 ? BIT(bank) : 0;
|
||||
|
||||
raw_spin_lock_irqsave(&pctl->lock, flags);
|
||||
reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG);
|
||||
reg = readl(pctl->membase + pctl->pow_mod_sel_offset +
|
||||
PIO_POW_MOD_CTL_OFS);
|
||||
reg &= ~BIT(bank);
|
||||
writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG);
|
||||
writel(reg | val, pctl->membase + pctl->pow_mod_sel_offset +
|
||||
PIO_POW_MOD_CTL_OFS);
|
||||
raw_spin_unlock_irqrestore(&pctl->lock, flags);
|
||||
|
||||
fallthrough;
|
||||
@@ -733,9 +748,10 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl,
|
||||
val = uV <= 1800000 ? 1 : 0;
|
||||
|
||||
raw_spin_lock_irqsave(&pctl->lock, flags);
|
||||
reg = readl(pctl->membase + PIO_POW_MOD_SEL_REG);
|
||||
reg = readl(pctl->membase + pctl->pow_mod_sel_offset);
|
||||
reg &= ~(1 << bank);
|
||||
writel(reg | val << bank, pctl->membase + PIO_POW_MOD_SEL_REG);
|
||||
writel(reg | val << bank,
|
||||
pctl->membase + pctl->pow_mod_sel_offset);
|
||||
raw_spin_unlock_irqrestore(&pctl->lock, flags);
|
||||
return 0;
|
||||
default:
|
||||
@@ -1472,9 +1488,9 @@ static int sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl *pctl,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
|
||||
const struct sunxi_pinctrl_desc *desc,
|
||||
unsigned long variant)
|
||||
int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
|
||||
const struct sunxi_pinctrl_desc *desc,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct pinctrl_desc *pctrl_desc;
|
||||
@@ -1497,8 +1513,8 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
|
||||
|
||||
pctl->dev = &pdev->dev;
|
||||
pctl->desc = desc;
|
||||
pctl->variant = variant;
|
||||
if (pctl->variant >= PINCTRL_SUN20I_D1) {
|
||||
pctl->variant = flags & SUNXI_PINCTRL_VARIANT_MASK;
|
||||
if (flags & SUNXI_PINCTRL_NEW_REG_LAYOUT) {
|
||||
pctl->bank_mem_size = D1_BANK_MEM_SIZE;
|
||||
pctl->pull_regs_offset = D1_PULL_REGS_OFFSET;
|
||||
pctl->dlevel_field_width = D1_DLEVEL_FIELD_WIDTH;
|
||||
@@ -1507,6 +1523,10 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
|
||||
pctl->pull_regs_offset = PULL_REGS_OFFSET;
|
||||
pctl->dlevel_field_width = DLEVEL_FIELD_WIDTH;
|
||||
}
|
||||
if (flags & SUNXI_PINCTRL_ELEVEN_BANKS)
|
||||
pctl->pow_mod_sel_offset = PIO_11B_POW_MOD_SEL_REG;
|
||||
else
|
||||
pctl->pow_mod_sel_offset = PIO_POW_MOD_SEL_REG;
|
||||
|
||||
pctl->irq_array = devm_kcalloc(&pdev->dev,
|
||||
IRQ_PER_BANK * pctl->desc->irq_banks,
|
||||
|
||||
@@ -25,10 +25,15 @@
|
||||
#define PG_BASE 192
|
||||
#define PH_BASE 224
|
||||
#define PI_BASE 256
|
||||
#define PJ_BASE 288
|
||||
#define PK_BASE 320
|
||||
#define PL_BASE 352
|
||||
#define PM_BASE 384
|
||||
#define PN_BASE 416
|
||||
|
||||
/* maximum number of banks per controller (PA -> PK) */
|
||||
#define SUNXI_PINCTRL_MAX_BANKS 11
|
||||
|
||||
#define SUNXI_PINCTRL_PIN(bank, pin) \
|
||||
PINCTRL_PIN(P ## bank ## _BASE + (pin), "P" #bank #pin)
|
||||
|
||||
@@ -82,21 +87,16 @@
|
||||
#define SUN4I_FUNC_INPUT 0
|
||||
#define SUN4I_FUNC_IRQ 6
|
||||
|
||||
#define PINCTRL_SUN5I_A10S BIT(1)
|
||||
#define PINCTRL_SUN5I_A13 BIT(2)
|
||||
#define PINCTRL_SUN5I_GR8 BIT(3)
|
||||
#define PINCTRL_SUN6I_A31 BIT(4)
|
||||
#define PINCTRL_SUN6I_A31S BIT(5)
|
||||
#define PINCTRL_SUN4I_A10 BIT(6)
|
||||
#define PINCTRL_SUN7I_A20 BIT(7)
|
||||
#define PINCTRL_SUN8I_R40 BIT(8)
|
||||
#define PINCTRL_SUN8I_V3 BIT(9)
|
||||
#define PINCTRL_SUN8I_V3S BIT(10)
|
||||
/* Variants below here have an updated register layout. */
|
||||
#define PINCTRL_SUN20I_D1 BIT(11)
|
||||
#define SUNXI_PINCTRL_VARIANT_MASK GENMASK(7, 0)
|
||||
#define SUNXI_PINCTRL_NEW_REG_LAYOUT BIT(8)
|
||||
#define SUNXI_PINCTRL_PORTF_SWITCH BIT(9)
|
||||
#define SUNXI_PINCTRL_ELEVEN_BANKS BIT(10)
|
||||
|
||||
#define PIO_POW_MOD_SEL_REG 0x340
|
||||
#define PIO_POW_MOD_CTL_REG 0x344
|
||||
#define PIO_POW_MOD_SEL_REG 0x340
|
||||
#define PIO_11B_POW_MOD_SEL_REG 0x380
|
||||
#define PIO_POW_MOD_CTL_OFS 0x004
|
||||
|
||||
#define PIO_BANK_K_OFFSET 0x500
|
||||
|
||||
enum sunxi_desc_bias_voltage {
|
||||
BIAS_VOLTAGE_NONE,
|
||||
@@ -164,7 +164,7 @@ struct sunxi_pinctrl {
|
||||
struct gpio_chip *chip;
|
||||
const struct sunxi_pinctrl_desc *desc;
|
||||
struct device *dev;
|
||||
struct sunxi_pinctrl_regulator regulators[9];
|
||||
struct sunxi_pinctrl_regulator regulators[11];
|
||||
struct irq_domain *domain;
|
||||
struct sunxi_pinctrl_function *functions;
|
||||
unsigned nfunctions;
|
||||
@@ -178,6 +178,7 @@ struct sunxi_pinctrl {
|
||||
u32 bank_mem_size;
|
||||
u32 pull_regs_offset;
|
||||
u32 dlevel_field_width;
|
||||
u32 pow_mod_sel_offset;
|
||||
};
|
||||
|
||||
#define SUNXI_PIN(_pin, ...) \
|
||||
@@ -299,11 +300,17 @@ static inline u32 sunxi_grp_config_reg(u16 pin)
|
||||
return GRP_CFG_REG + bank * 0x4;
|
||||
}
|
||||
|
||||
int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
|
||||
const struct sunxi_pinctrl_desc *desc,
|
||||
unsigned long variant);
|
||||
int sunxi_pinctrl_init_with_flags(struct platform_device *pdev,
|
||||
const struct sunxi_pinctrl_desc *desc,
|
||||
unsigned long flags);
|
||||
|
||||
#define sunxi_pinctrl_init(_dev, _desc) \
|
||||
sunxi_pinctrl_init_with_variant(_dev, _desc, 0)
|
||||
sunxi_pinctrl_init_with_flags(_dev, _desc, 0)
|
||||
|
||||
int sunxi_pinctrl_dt_table_init(struct platform_device *pdev,
|
||||
const u8 *pins_per_bank,
|
||||
const u8 *irq_bank_muxes,
|
||||
struct sunxi_pinctrl_desc *desc,
|
||||
unsigned long flags);
|
||||
|
||||
#endif /* __PINCTRL_SUNXI_H */
|
||||
|
||||
@@ -96,6 +96,7 @@ static const struct cfg_param {
|
||||
{"nvidia,slew-rate-falling", TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING},
|
||||
{"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING},
|
||||
{"nvidia,drive-type", TEGRA_PINCONF_PARAM_DRIVE_TYPE},
|
||||
{"nvidia,gpio-mode", TEGRA_PINCONF_PARAM_GPIO_MODE},
|
||||
};
|
||||
|
||||
static int tegra_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
|
||||
@@ -270,13 +271,16 @@ static int tegra_pinctrl_set_mux(struct pinctrl_dev *pctldev,
|
||||
val = pmx_readl(pmx, g->mux_bank, g->mux_reg);
|
||||
val &= ~(0x3 << g->mux_bit);
|
||||
val |= i << g->mux_bit;
|
||||
/* Set the SFIO/GPIO selection to SFIO when under pinmux control*/
|
||||
if (pmx->soc->sfsel_in_mux)
|
||||
val |= (1 << g->sfsel_bit);
|
||||
pmx_writel(pmx, val, g->mux_bank, g->mux_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev *pctldev,
|
||||
unsigned int offset)
|
||||
static int tegra_pinctrl_get_group_index(struct pinctrl_dev *pctldev,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned int group, num_pins, j;
|
||||
@@ -289,12 +293,35 @@ static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev *
|
||||
continue;
|
||||
for (j = 0; j < num_pins; j++) {
|
||||
if (offset == pins[j])
|
||||
return &pmx->soc->groups[group];
|
||||
return group;
|
||||
}
|
||||
}
|
||||
|
||||
dev_err(pctldev->dev, "Pingroup not found for pin %u\n", offset);
|
||||
return NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct tegra_pingroup *tegra_pinctrl_get_group(struct pinctrl_dev *pctldev,
|
||||
unsigned int offset,
|
||||
int group_index)
|
||||
{
|
||||
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
if (group_index < 0 || group_index >= pmx->soc->ngroups)
|
||||
return NULL;
|
||||
|
||||
return &pmx->soc->groups[group_index];
|
||||
}
|
||||
|
||||
static struct tegra_pingroup_config *tegra_pinctrl_get_group_config(struct pinctrl_dev *pctldev,
|
||||
unsigned int offset,
|
||||
int group_index)
|
||||
{
|
||||
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
if (group_index < 0)
|
||||
return NULL;
|
||||
|
||||
return &pmx->pingroup_configs[group_index];
|
||||
}
|
||||
|
||||
static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
@@ -303,12 +330,15 @@ static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
{
|
||||
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct tegra_pingroup *group;
|
||||
struct tegra_pingroup_config *config;
|
||||
int group_index;
|
||||
u32 value;
|
||||
|
||||
if (!pmx->soc->sfsel_in_mux)
|
||||
return 0;
|
||||
|
||||
group = tegra_pinctrl_get_group(pctldev, offset);
|
||||
group_index = tegra_pinctrl_get_group_index(pctldev, offset);
|
||||
group = tegra_pinctrl_get_group(pctldev, offset, group_index);
|
||||
|
||||
if (!group)
|
||||
return -EINVAL;
|
||||
@@ -316,7 +346,11 @@ static int tegra_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
if (group->mux_reg < 0 || group->sfsel_bit < 0)
|
||||
return -EINVAL;
|
||||
|
||||
config = tegra_pinctrl_get_group_config(pctldev, offset, group_index);
|
||||
if (!config)
|
||||
return -EINVAL;
|
||||
value = pmx_readl(pmx, group->mux_bank, group->mux_reg);
|
||||
config->is_sfsel = (value & BIT(group->sfsel_bit)) != 0;
|
||||
value &= ~BIT(group->sfsel_bit);
|
||||
pmx_writel(pmx, value, group->mux_bank, group->mux_reg);
|
||||
|
||||
@@ -329,12 +363,15 @@ static void tegra_pinctrl_gpio_disable_free(struct pinctrl_dev *pctldev,
|
||||
{
|
||||
struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct tegra_pingroup *group;
|
||||
struct tegra_pingroup_config *config;
|
||||
int group_index;
|
||||
u32 value;
|
||||
|
||||
if (!pmx->soc->sfsel_in_mux)
|
||||
return;
|
||||
|
||||
group = tegra_pinctrl_get_group(pctldev, offset);
|
||||
group_index = tegra_pinctrl_get_group_index(pctldev, offset);
|
||||
group = tegra_pinctrl_get_group(pctldev, offset, group_index);
|
||||
|
||||
if (!group)
|
||||
return;
|
||||
@@ -342,8 +379,12 @@ static void tegra_pinctrl_gpio_disable_free(struct pinctrl_dev *pctldev,
|
||||
if (group->mux_reg < 0 || group->sfsel_bit < 0)
|
||||
return;
|
||||
|
||||
config = tegra_pinctrl_get_group_config(pctldev, offset, group_index);
|
||||
if (!config)
|
||||
return;
|
||||
value = pmx_readl(pmx, group->mux_bank, group->mux_reg);
|
||||
value |= BIT(group->sfsel_bit);
|
||||
if (config->is_sfsel)
|
||||
value |= BIT(group->sfsel_bit);
|
||||
pmx_writel(pmx, value, group->mux_bank, group->mux_reg);
|
||||
}
|
||||
|
||||
@@ -468,6 +509,16 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
|
||||
*bit = g->drvtype_bit;
|
||||
*width = 2;
|
||||
break;
|
||||
case TEGRA_PINCONF_PARAM_GPIO_MODE:
|
||||
if (pmx->soc->sfsel_in_mux) {
|
||||
*bank = g->mux_bank;
|
||||
*reg = g->mux_reg;
|
||||
*bit = g->sfsel_bit;
|
||||
*width = 1;
|
||||
} else {
|
||||
*reg = -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(pmx->dev, "Invalid config param %04x\n", param);
|
||||
return -ENOTSUPP;
|
||||
@@ -788,6 +839,12 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
|
||||
pmx->dev = &pdev->dev;
|
||||
pmx->soc = soc_data;
|
||||
|
||||
pmx->pingroup_configs = devm_kcalloc(&pdev->dev,
|
||||
pmx->soc->ngroups, sizeof(*pmx->pingroup_configs),
|
||||
GFP_KERNEL);
|
||||
if (!pmx->pingroup_configs)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Each mux group will appear in 4 functions' list of groups.
|
||||
* This over-allocates slightly, since not all groups are mux groups.
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
#ifndef __PINMUX_TEGRA_H__
|
||||
#define __PINMUX_TEGRA_H__
|
||||
|
||||
struct tegra_pingroup_config {
|
||||
bool is_sfsel;
|
||||
};
|
||||
|
||||
struct tegra_pmx {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pctl;
|
||||
@@ -21,6 +25,8 @@ struct tegra_pmx {
|
||||
int nbanks;
|
||||
void __iomem **regs;
|
||||
u32 *backup_regs;
|
||||
/* Array of size soc->ngroups */
|
||||
struct tegra_pingroup_config *pingroup_configs;
|
||||
};
|
||||
|
||||
enum tegra_pinconf_param {
|
||||
@@ -54,6 +60,8 @@ enum tegra_pinconf_param {
|
||||
TEGRA_PINCONF_PARAM_SLEW_RATE_RISING,
|
||||
/* argument: Integer, range is HW-dependant */
|
||||
TEGRA_PINCONF_PARAM_DRIVE_TYPE,
|
||||
/* argument: Boolean */
|
||||
TEGRA_PINCONF_PARAM_GPIO_MODE,
|
||||
};
|
||||
|
||||
enum tegra_pinconf_pull {
|
||||
@@ -176,16 +184,22 @@ struct tegra_pingroup {
|
||||
|
||||
/**
|
||||
* struct tegra_pinctrl_soc_data - Tegra pin controller driver configuration
|
||||
* @ngpios: The number of GPIO pins the pin controller HW affects.
|
||||
* @pins: An array describing all pins the pin controller affects.
|
||||
* All pins which are also GPIOs must be listed first within the
|
||||
* array, and be numbered identically to the GPIO controller's
|
||||
* numbering.
|
||||
* @npins: The numbmer of entries in @pins.
|
||||
* @functions: An array describing all mux functions the SoC supports.
|
||||
* @nfunctions: The numbmer of entries in @functions.
|
||||
* @groups: An array describing all pin groups the pin SoC supports.
|
||||
* @ngroups: The numbmer of entries in @groups.
|
||||
* @ngpios: The number of GPIO pins the pin controller HW affects.
|
||||
* @gpio_compatible: Device-tree GPIO compatible string.
|
||||
* @pins: An array describing all pins the pin controller affects.
|
||||
* All pins which are also GPIOs must be listed first within the
|
||||
* array, and be numbered identically to the GPIO controller's
|
||||
* numbering.
|
||||
* @npins: The number of entries in @pins.
|
||||
* @functions: An array describing all mux functions the SoC supports.
|
||||
* @nfunctions: The number of entries in @functions.
|
||||
* @groups: An array describing all pin groups the pin SoC supports.
|
||||
* @ngroups: The number of entries in @groups.
|
||||
* @hsm_in_mux: High-speed mode field. Only applicable to devices with one pin per group.
|
||||
* @schmitt_in_mux: Schmitt trigger field. Only applicable to devices with one pin per group.
|
||||
* @drvtype_in_mux: Drivetype field. Only applicable to devices with one pin per group.
|
||||
* @sfsel_in_mux: Special function selection field.
|
||||
* Only applicable to devices with one pin per group.
|
||||
*/
|
||||
struct tegra_pinctrl_soc_data {
|
||||
unsigned ngpios;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
* Author: Alan Cox <alan@linux.intel.com>
|
||||
*/
|
||||
|
||||
#define DEFAULT_SYMBOL_NAMESPACE "PWM_LPSS"
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
@@ -20,8 +22,6 @@
|
||||
#include <linux/pwm.h>
|
||||
#include <linux/time.h>
|
||||
|
||||
#define DEFAULT_SYMBOL_NAMESPACE "PWM_LPSS"
|
||||
|
||||
#include "pwm-lpss.h"
|
||||
|
||||
#define PWM 0x00000000
|
||||
|
||||
46
include/dt-bindings/pinctrl/amlogic,pinctrl.h
Normal file
46
include/dt-bindings/pinctrl/amlogic,pinctrl.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
|
||||
/*
|
||||
* Copyright (c) 2024 Amlogic, Inc. All rights reserved.
|
||||
* Author: Xianwei Zhao <xianwei.zhao@amlogic.com>
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_AMLOGIC_PINCTRL_H
|
||||
#define _DT_BINDINGS_AMLOGIC_PINCTRL_H
|
||||
/* Normal PIN bank */
|
||||
#define AMLOGIC_GPIO_A 0
|
||||
#define AMLOGIC_GPIO_B 1
|
||||
#define AMLOGIC_GPIO_C 2
|
||||
#define AMLOGIC_GPIO_D 3
|
||||
#define AMLOGIC_GPIO_E 4
|
||||
#define AMLOGIC_GPIO_F 5
|
||||
#define AMLOGIC_GPIO_G 6
|
||||
#define AMLOGIC_GPIO_H 7
|
||||
#define AMLOGIC_GPIO_I 8
|
||||
#define AMLOGIC_GPIO_J 9
|
||||
#define AMLOGIC_GPIO_K 10
|
||||
#define AMLOGIC_GPIO_L 11
|
||||
#define AMLOGIC_GPIO_M 12
|
||||
#define AMLOGIC_GPIO_N 13
|
||||
#define AMLOGIC_GPIO_O 14
|
||||
#define AMLOGIC_GPIO_P 15
|
||||
#define AMLOGIC_GPIO_Q 16
|
||||
#define AMLOGIC_GPIO_R 17
|
||||
#define AMLOGIC_GPIO_S 18
|
||||
#define AMLOGIC_GPIO_T 19
|
||||
#define AMLOGIC_GPIO_U 20
|
||||
#define AMLOGIC_GPIO_V 21
|
||||
#define AMLOGIC_GPIO_W 22
|
||||
#define AMLOGIC_GPIO_X 23
|
||||
#define AMLOGIC_GPIO_Y 24
|
||||
#define AMLOGIC_GPIO_Z 25
|
||||
|
||||
/* Special PIN bank */
|
||||
#define AMLOGIC_GPIO_DV 26
|
||||
#define AMLOGIC_GPIO_AO 27
|
||||
#define AMLOGIC_GPIO_CC 28
|
||||
#define AMLOGIC_GPIO_TEST_N 29
|
||||
#define AMLOGIC_GPIO_ANALOG 30
|
||||
|
||||
#define AML_PINMUX(bank, offset, mode) (((((bank) << 8) + (offset)) << 8) | (mode))
|
||||
|
||||
#endif /* _DT_BINDINGS_AMLOGIC_PINCTRL_H */
|
||||
196
include/dt-bindings/pinctrl/pinctrl-sg2042.h
Normal file
196
include/dt-bindings/pinctrl/pinctrl-sg2042.h
Normal file
@@ -0,0 +1,196 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024 Inochi Amaoto <inochiama@outlook.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_PINCTRL_SG2042_H
|
||||
#define _DT_BINDINGS_PINCTRL_SG2042_H
|
||||
|
||||
#define PINMUX(pin, mux) \
|
||||
(((pin) & 0xffff) | (((mux) & 0xff) << 16))
|
||||
|
||||
#define PIN_LPC_LCLK 0
|
||||
#define PIN_LPC_LFRAME 1
|
||||
#define PIN_LPC_LAD0 2
|
||||
#define PIN_LPC_LAD1 3
|
||||
#define PIN_LPC_LAD2 4
|
||||
#define PIN_LPC_LAD3 5
|
||||
#define PIN_LPC_LDRQ0 6
|
||||
#define PIN_LPC_LDRQ1 7
|
||||
#define PIN_LPC_SERIRQ 8
|
||||
#define PIN_LPC_CLKRUN 9
|
||||
#define PIN_LPC_LPME 10
|
||||
#define PIN_LPC_LPCPD 11
|
||||
#define PIN_LPC_LSMI 12
|
||||
#define PIN_PCIE0_L0_RESET 13
|
||||
#define PIN_PCIE0_L1_RESET 14
|
||||
#define PIN_PCIE0_L0_WAKEUP 15
|
||||
#define PIN_PCIE0_L1_WAKEUP 16
|
||||
#define PIN_PCIE0_L0_CLKREQ_IN 17
|
||||
#define PIN_PCIE0_L1_CLKREQ_IN 18
|
||||
#define PIN_PCIE1_L0_RESET 19
|
||||
#define PIN_PCIE1_L1_RESET 20
|
||||
#define PIN_PCIE1_L0_WAKEUP 21
|
||||
#define PIN_PCIE1_L1_WAKEUP 22
|
||||
#define PIN_PCIE1_L0_CLKREQ_IN 23
|
||||
#define PIN_PCIE1_L1_CLKREQ_IN 24
|
||||
#define PIN_SPIF0_CLK_SEL1 25
|
||||
#define PIN_SPIF0_CLK_SEL0 26
|
||||
#define PIN_SPIF0_WP 27
|
||||
#define PIN_SPIF0_HOLD 28
|
||||
#define PIN_SPIF0_SDI 29
|
||||
#define PIN_SPIF0_CS 30
|
||||
#define PIN_SPIF0_SCK 31
|
||||
#define PIN_SPIF0_SDO 32
|
||||
#define PIN_SPIF1_CLK_SEL1 33
|
||||
#define PIN_SPIF1_CLK_SEL0 34
|
||||
#define PIN_SPIF1_WP 35
|
||||
#define PIN_SPIF1_HOLD 36
|
||||
#define PIN_SPIF1_SDI 37
|
||||
#define PIN_SPIF1_CS 38
|
||||
#define PIN_SPIF1_SCK 39
|
||||
#define PIN_SPIF1_SDO 40
|
||||
#define PIN_EMMC_WP 41
|
||||
#define PIN_EMMC_CD 42
|
||||
#define PIN_EMMC_RST 43
|
||||
#define PIN_EMMC_PWR_EN 44
|
||||
#define PIN_SDIO_CD 45
|
||||
#define PIN_SDIO_WP 46
|
||||
#define PIN_SDIO_RST 47
|
||||
#define PIN_SDIO_PWR_EN 48
|
||||
#define PIN_RGMII0_TXD0 49
|
||||
#define PIN_RGMII0_TXD1 50
|
||||
#define PIN_RGMII0_TXD2 51
|
||||
#define PIN_RGMII0_TXD3 52
|
||||
#define PIN_RGMII0_TXCTRL 53
|
||||
#define PIN_RGMII0_RXD0 54
|
||||
#define PIN_RGMII0_RXD1 55
|
||||
#define PIN_RGMII0_RXD2 56
|
||||
#define PIN_RGMII0_RXD3 57
|
||||
#define PIN_RGMII0_RXCTRL 58
|
||||
#define PIN_RGMII0_TXC 59
|
||||
#define PIN_RGMII0_RXC 60
|
||||
#define PIN_RGMII0_REFCLKO 61
|
||||
#define PIN_RGMII0_IRQ 62
|
||||
#define PIN_RGMII0_MDC 63
|
||||
#define PIN_RGMII0_MDIO 64
|
||||
#define PIN_PWM0 65
|
||||
#define PIN_PWM1 66
|
||||
#define PIN_PWM2 67
|
||||
#define PIN_PWM3 68
|
||||
#define PIN_FAN0 69
|
||||
#define PIN_FAN1 70
|
||||
#define PIN_FAN2 71
|
||||
#define PIN_FAN3 72
|
||||
#define PIN_IIC0_SDA 73
|
||||
#define PIN_IIC0_SCL 74
|
||||
#define PIN_IIC1_SDA 75
|
||||
#define PIN_IIC1_SCL 76
|
||||
#define PIN_IIC2_SDA 77
|
||||
#define PIN_IIC2_SCL 78
|
||||
#define PIN_IIC3_SDA 79
|
||||
#define PIN_IIC3_SCL 80
|
||||
#define PIN_UART0_TX 81
|
||||
#define PIN_UART0_RX 82
|
||||
#define PIN_UART0_RTS 83
|
||||
#define PIN_UART0_CTS 84
|
||||
#define PIN_UART1_TX 85
|
||||
#define PIN_UART1_RX 86
|
||||
#define PIN_UART1_RTS 87
|
||||
#define PIN_UART1_CTS 88
|
||||
#define PIN_UART2_TX 89
|
||||
#define PIN_UART2_RX 90
|
||||
#define PIN_UART2_RTS 91
|
||||
#define PIN_UART2_CTS 92
|
||||
#define PIN_UART3_TX 93
|
||||
#define PIN_UART3_RX 94
|
||||
#define PIN_UART3_RTS 95
|
||||
#define PIN_UART3_CTS 96
|
||||
#define PIN_SPI0_CS0 97
|
||||
#define PIN_SPI0_CS1 98
|
||||
#define PIN_SPI0_SDI 99
|
||||
#define PIN_SPI0_SDO 100
|
||||
#define PIN_SPI0_SCK 101
|
||||
#define PIN_SPI1_CS0 102
|
||||
#define PIN_SPI1_CS1 103
|
||||
#define PIN_SPI1_SDI 104
|
||||
#define PIN_SPI1_SDO 105
|
||||
#define PIN_SPI1_SCK 106
|
||||
#define PIN_JTAG0_TDO 107
|
||||
#define PIN_JTAG0_TCK 108
|
||||
#define PIN_JTAG0_TDI 109
|
||||
#define PIN_JTAG0_TMS 110
|
||||
#define PIN_JTAG0_TRST 111
|
||||
#define PIN_JTAG0_SRST 112
|
||||
#define PIN_JTAG1_TDO 113
|
||||
#define PIN_JTAG1_TCK 114
|
||||
#define PIN_JTAG1_TDI 115
|
||||
#define PIN_JTAG1_TMS 116
|
||||
#define PIN_JTAG1_TRST 117
|
||||
#define PIN_JTAG1_SRST 118
|
||||
#define PIN_JTAG2_TDO 119
|
||||
#define PIN_JTAG2_TCK 120
|
||||
#define PIN_JTAG2_TDI 121
|
||||
#define PIN_JTAG2_TMS 122
|
||||
#define PIN_JTAG2_TRST 123
|
||||
#define PIN_JTAG2_SRST 124
|
||||
#define PIN_GPIO0 125
|
||||
#define PIN_GPIO1 126
|
||||
#define PIN_GPIO2 127
|
||||
#define PIN_GPIO3 128
|
||||
#define PIN_GPIO4 129
|
||||
#define PIN_GPIO5 130
|
||||
#define PIN_GPIO6 131
|
||||
#define PIN_GPIO7 132
|
||||
#define PIN_GPIO8 133
|
||||
#define PIN_GPIO9 134
|
||||
#define PIN_GPIO10 135
|
||||
#define PIN_GPIO11 136
|
||||
#define PIN_GPIO12 137
|
||||
#define PIN_GPIO13 138
|
||||
#define PIN_GPIO14 139
|
||||
#define PIN_GPIO15 140
|
||||
#define PIN_GPIO16 141
|
||||
#define PIN_GPIO17 142
|
||||
#define PIN_GPIO18 143
|
||||
#define PIN_GPIO19 144
|
||||
#define PIN_GPIO20 145
|
||||
#define PIN_GPIO21 146
|
||||
#define PIN_GPIO22 147
|
||||
#define PIN_GPIO23 148
|
||||
#define PIN_GPIO24 149
|
||||
#define PIN_GPIO25 150
|
||||
#define PIN_GPIO26 151
|
||||
#define PIN_GPIO27 152
|
||||
#define PIN_GPIO28 153
|
||||
#define PIN_GPIO29 154
|
||||
#define PIN_GPIO30 155
|
||||
#define PIN_GPIO31 156
|
||||
#define PIN_MODE_SEL0 157
|
||||
#define PIN_MODE_SEL1 158
|
||||
#define PIN_MODE_SEL2 159
|
||||
#define PIN_BOOT_SEL0 160
|
||||
#define PIN_BOOT_SEL1 161
|
||||
#define PIN_BOOT_SEL2 162
|
||||
#define PIN_BOOT_SEL3 163
|
||||
#define PIN_BOOT_SEL4 164
|
||||
#define PIN_BOOT_SEL5 165
|
||||
#define PIN_BOOT_SEL6 166
|
||||
#define PIN_BOOT_SEL7 167
|
||||
#define PIN_MULTI_SCKT 168
|
||||
#define PIN_SCKT_ID0 169
|
||||
#define PIN_SCKT_ID1 170
|
||||
#define PIN_PLL_CLK_IN_MAIN 171
|
||||
#define PIN_PLL_CLK_IN_DDR_L 172
|
||||
#define PIN_PLL_CLK_IN_DDR_R 173
|
||||
#define PIN_XTAL_32K 174
|
||||
#define PIN_SYS_RST 175
|
||||
#define PIN_PWR_BUTTON 176
|
||||
#define PIN_TEST_EN 177
|
||||
#define PIN_TEST_MODE_MBIST 178
|
||||
#define PIN_TEST_MODE_SCAN 179
|
||||
#define PIN_TEST_MODE_BSD 180
|
||||
#define PIN_BISR_BYP 181
|
||||
|
||||
#endif /* _DT_BINDINGS_PINCTRL_SG2042_H */
|
||||
221
include/dt-bindings/pinctrl/pinctrl-sg2044.h
Normal file
221
include/dt-bindings/pinctrl/pinctrl-sg2044.h
Normal file
@@ -0,0 +1,221 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
|
||||
/*
|
||||
* Copyright (C) 2024 Inochi Amaoto <inochiama@outlook.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_PINCTRL_SG2044_H
|
||||
#define _DT_BINDINGS_PINCTRL_SG2044_H
|
||||
|
||||
#define PINMUX(pin, mux) \
|
||||
(((pin) & 0xffff) | (((mux) & 0xff) << 16))
|
||||
|
||||
#define PIN_IIC0_SMBSUS_IN 0
|
||||
#define PIN_IIC0_SMBSUS_OUT 1
|
||||
#define PIN_IIC0_SMBALERT 2
|
||||
#define PIN_IIC1_SMBSUS_IN 3
|
||||
#define PIN_IIC1_SMBSUS_OUT 4
|
||||
#define PIN_IIC1_SMBALERT 5
|
||||
#define PIN_IIC2_SMBSUS_IN 6
|
||||
#define PIN_IIC2_SMBSUS_OUT 7
|
||||
#define PIN_IIC2_SMBALERT 8
|
||||
#define PIN_IIC3_SMBSUS_IN 9
|
||||
#define PIN_IIC3_SMBSUS_OUT 10
|
||||
#define PIN_IIC3_SMBALERT 11
|
||||
#define PIN_PCIE0_L0_RESET 12
|
||||
#define PIN_PCIE0_L1_RESET 13
|
||||
#define PIN_PCIE0_L0_WAKEUP 14
|
||||
#define PIN_PCIE0_L1_WAKEUP 15
|
||||
#define PIN_PCIE0_L0_CLKREQ_IN 16
|
||||
#define PIN_PCIE0_L1_CLKREQ_IN 17
|
||||
#define PIN_PCIE1_L0_RESET 18
|
||||
#define PIN_PCIE1_L1_RESET 19
|
||||
#define PIN_PCIE1_L0_WAKEUP 20
|
||||
#define PIN_PCIE1_L1_WAKEUP 21
|
||||
#define PIN_PCIE1_L0_CLKREQ_IN 22
|
||||
#define PIN_PCIE1_L1_CLKREQ_IN 23
|
||||
#define PIN_PCIE2_L0_RESET 24
|
||||
#define PIN_PCIE2_L1_RESET 25
|
||||
#define PIN_PCIE2_L0_WAKEUP 26
|
||||
#define PIN_PCIE2_L1_WAKEUP 27
|
||||
#define PIN_PCIE2_L0_CLKREQ_IN 28
|
||||
#define PIN_PCIE2_L1_CLKREQ_IN 29
|
||||
#define PIN_PCIE3_L0_RESET 30
|
||||
#define PIN_PCIE3_L1_RESET 31
|
||||
#define PIN_PCIE3_L0_WAKEUP 32
|
||||
#define PIN_PCIE3_L1_WAKEUP 33
|
||||
#define PIN_PCIE3_L0_CLKREQ_IN 34
|
||||
#define PIN_PCIE3_L1_CLKREQ_IN 35
|
||||
#define PIN_PCIE4_L0_RESET 36
|
||||
#define PIN_PCIE4_L1_RESET 37
|
||||
#define PIN_PCIE4_L0_WAKEUP 38
|
||||
#define PIN_PCIE4_L1_WAKEUP 39
|
||||
#define PIN_PCIE4_L0_CLKREQ_IN 40
|
||||
#define PIN_PCIE4_L1_CLKREQ_IN 41
|
||||
#define PIN_SPIF0_CLK_SEL1 42
|
||||
#define PIN_SPIF0_CLK_SEL0 43
|
||||
#define PIN_SPIF0_WP 44
|
||||
#define PIN_SPIF0_HOLD 45
|
||||
#define PIN_SPIF0_SDI 46
|
||||
#define PIN_SPIF0_CS 47
|
||||
#define PIN_SPIF0_SCK 48
|
||||
#define PIN_SPIF0_SDO 49
|
||||
#define PIN_SPIF1_CLK_SEL1 50
|
||||
#define PIN_SPIF1_CLK_SEL0 51
|
||||
#define PIN_SPIF1_WP 52
|
||||
#define PIN_SPIF1_HOLD 53
|
||||
#define PIN_SPIF1_SDI 54
|
||||
#define PIN_SPIF1_CS 55
|
||||
#define PIN_SPIF1_SCK 56
|
||||
#define PIN_SPIF1_SDO 57
|
||||
#define PIN_EMMC_WP 58
|
||||
#define PIN_EMMC_CD 59
|
||||
#define PIN_EMMC_RST 60
|
||||
#define PIN_EMMC_PWR_EN 61
|
||||
#define PIN_SDIO_CD 62
|
||||
#define PIN_SDIO_WP 63
|
||||
#define PIN_SDIO_RST 64
|
||||
#define PIN_SDIO_PWR_EN 65
|
||||
#define PIN_RGMII0_TXD0 66
|
||||
#define PIN_RGMII0_TXD1 67
|
||||
#define PIN_RGMII0_TXD2 68
|
||||
#define PIN_RGMII0_TXD3 69
|
||||
#define PIN_RGMII0_TXCTRL 70
|
||||
#define PIN_RGMII0_RXD0 71
|
||||
#define PIN_RGMII0_RXD1 72
|
||||
#define PIN_RGMII0_RXD2 73
|
||||
#define PIN_RGMII0_RXD3 74
|
||||
#define PIN_RGMII0_RXCTRL 75
|
||||
#define PIN_RGMII0_TXC 76
|
||||
#define PIN_RGMII0_RXC 77
|
||||
#define PIN_RGMII0_REFCLKO 78
|
||||
#define PIN_RGMII0_IRQ 79
|
||||
#define PIN_RGMII0_MDC 80
|
||||
#define PIN_RGMII0_MDIO 81
|
||||
#define PIN_PWM0 82
|
||||
#define PIN_PWM1 83
|
||||
#define PIN_PWM2 84
|
||||
#define PIN_PWM3 85
|
||||
#define PIN_FAN0 86
|
||||
#define PIN_FAN1 87
|
||||
#define PIN_FAN2 88
|
||||
#define PIN_FAN3 89
|
||||
#define PIN_IIC0_SDA 90
|
||||
#define PIN_IIC0_SCL 91
|
||||
#define PIN_IIC1_SDA 92
|
||||
#define PIN_IIC1_SCL 93
|
||||
#define PIN_IIC2_SDA 94
|
||||
#define PIN_IIC2_SCL 95
|
||||
#define PIN_IIC3_SDA 96
|
||||
#define PIN_IIC3_SCL 97
|
||||
#define PIN_UART0_TX 98
|
||||
#define PIN_UART0_RX 99
|
||||
#define PIN_UART0_RTS 100
|
||||
#define PIN_UART0_CTS 101
|
||||
#define PIN_UART1_TX 102
|
||||
#define PIN_UART1_RX 103
|
||||
#define PIN_UART1_RTS 104
|
||||
#define PIN_UART1_CTS 105
|
||||
#define PIN_UART2_TX 106
|
||||
#define PIN_UART2_RX 107
|
||||
#define PIN_UART2_RTS 108
|
||||
#define PIN_UART2_CTS 109
|
||||
#define PIN_UART3_TX 110
|
||||
#define PIN_UART3_RX 111
|
||||
#define PIN_UART3_RTS 112
|
||||
#define PIN_UART3_CTS 113
|
||||
#define PIN_SPI0_CS0 114
|
||||
#define PIN_SPI0_CS1 115
|
||||
#define PIN_SPI0_SDI 116
|
||||
#define PIN_SPI0_SDO 117
|
||||
#define PIN_SPI0_SCK 118
|
||||
#define PIN_SPI1_CS0 119
|
||||
#define PIN_SPI1_CS1 120
|
||||
#define PIN_SPI1_SDI 121
|
||||
#define PIN_SPI1_SDO 122
|
||||
#define PIN_SPI1_SCK 123
|
||||
#define PIN_JTAG0_TDO 124
|
||||
#define PIN_JTAG0_TCK 125
|
||||
#define PIN_JTAG0_TDI 126
|
||||
#define PIN_JTAG0_TMS 127
|
||||
#define PIN_JTAG0_TRST 128
|
||||
#define PIN_JTAG0_SRST 129
|
||||
#define PIN_JTAG1_TDO 130
|
||||
#define PIN_JTAG1_TCK 131
|
||||
#define PIN_JTAG1_TDI 132
|
||||
#define PIN_JTAG1_TMS 133
|
||||
#define PIN_JTAG1_TRST 134
|
||||
#define PIN_JTAG1_SRST 135
|
||||
#define PIN_JTAG2_TDO 136
|
||||
#define PIN_JTAG2_TCK 137
|
||||
#define PIN_JTAG2_TDI 138
|
||||
#define PIN_JTAG2_TMS 139
|
||||
#define PIN_JTAG2_TRST 140
|
||||
#define PIN_JTAG2_SRST 141
|
||||
#define PIN_JTAG3_TDO 142
|
||||
#define PIN_JTAG3_TCK 143
|
||||
#define PIN_JTAG3_TDI 144
|
||||
#define PIN_JTAG3_TMS 145
|
||||
#define PIN_JTAG3_TRST 146
|
||||
#define PIN_JTAG3_SRST 147
|
||||
#define PIN_GPIO0 148
|
||||
#define PIN_GPIO1 149
|
||||
#define PIN_GPIO2 150
|
||||
#define PIN_GPIO3 151
|
||||
#define PIN_GPIO4 152
|
||||
#define PIN_GPIO5 153
|
||||
#define PIN_GPIO6 154
|
||||
#define PIN_GPIO7 155
|
||||
#define PIN_GPIO8 156
|
||||
#define PIN_GPIO9 157
|
||||
#define PIN_GPIO10 158
|
||||
#define PIN_GPIO11 159
|
||||
#define PIN_GPIO12 160
|
||||
#define PIN_GPIO13 161
|
||||
#define PIN_GPIO14 162
|
||||
#define PIN_GPIO15 163
|
||||
#define PIN_GPIO16 164
|
||||
#define PIN_GPIO17 165
|
||||
#define PIN_GPIO18 166
|
||||
#define PIN_GPIO19 167
|
||||
#define PIN_GPIO20 168
|
||||
#define PIN_GPIO21 169
|
||||
#define PIN_GPIO22 170
|
||||
#define PIN_GPIO23 171
|
||||
#define PIN_GPIO24 172
|
||||
#define PIN_GPIO25 173
|
||||
#define PIN_GPIO26 174
|
||||
#define PIN_GPIO27 175
|
||||
#define PIN_GPIO28 176
|
||||
#define PIN_GPIO29 177
|
||||
#define PIN_GPIO30 178
|
||||
#define PIN_GPIO31 179
|
||||
#define PIN_MODE_SEL0 180
|
||||
#define PIN_MODE_SEL1 181
|
||||
#define PIN_MODE_SEL2 182
|
||||
#define PIN_BOOT_SEL0 183
|
||||
#define PIN_BOOT_SEL1 184
|
||||
#define PIN_BOOT_SEL2 185
|
||||
#define PIN_BOOT_SEL3 186
|
||||
#define PIN_BOOT_SEL4 187
|
||||
#define PIN_BOOT_SEL5 188
|
||||
#define PIN_BOOT_SEL6 189
|
||||
#define PIN_BOOT_SEL7 190
|
||||
#define PIN_MULTI_SCKT 191
|
||||
#define PIN_SCKT_ID0 192
|
||||
#define PIN_SCKT_ID1 193
|
||||
#define PIN_PLL_CLK_IN_MAIN 194
|
||||
#define PIN_PLL_CLK_IN_DDR_0 195
|
||||
#define PIN_PLL_CLK_IN_DDR_1 196
|
||||
#define PIN_PLL_CLK_IN_DDR_2 197
|
||||
#define PIN_PLL_CLK_IN_DDR_3 198
|
||||
#define PIN_XTAL_32K 199
|
||||
#define PIN_SYS_RST 200
|
||||
#define PIN_PWR_BUTTON 201
|
||||
#define PIN_TEST_EN 202
|
||||
#define PIN_TEST_MODE_MBIST 203
|
||||
#define PIN_TEST_MODE_SCAN 204
|
||||
#define PIN_TEST_MODE_BSD 205
|
||||
#define PIN_BISR_BYP 206
|
||||
|
||||
#endif /* _DT_BINDINGS_PINCTRL_SG2044_H */
|
||||
@@ -232,4 +232,8 @@ static inline int pinconf_generic_dt_node_to_map_all(struct pinctrl_dev *pctldev
|
||||
PIN_MAP_TYPE_INVALID);
|
||||
}
|
||||
|
||||
int pinconf_generic_dt_node_to_map_pinmux(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np,
|
||||
struct pinctrl_map **map,
|
||||
unsigned int *num_maps);
|
||||
#endif /* __LINUX_PINCTRL_PINCONF_GENERIC_H */
|
||||
|
||||
@@ -15,9 +15,36 @@ struct pwm_lpss_boardinfo {
|
||||
unsigned int npwm;
|
||||
unsigned long base_unit_bits;
|
||||
/*
|
||||
* Some versions of the IP may stuck in the state machine if enable
|
||||
* bit is not set, and hence update bit will show busy status till
|
||||
* the reset. For the rest it may be otherwise.
|
||||
* NOTE:
|
||||
* Intel Broxton, Apollo Lake, and Gemini Lake have different programming flow.
|
||||
*
|
||||
* Initial Enable or First Activation
|
||||
* 1. Program the base unit and on time divisor values.
|
||||
* 2. Set the software update bit.
|
||||
* 3. Poll in a loop on the PWMCTRL bit until software update bit is cleared.+
|
||||
* 4. Enable the PWM output by setting PWM Enable.
|
||||
* 5. Repeat the above steps for the next PWM Module.
|
||||
*
|
||||
* Dynamic update while PWM is Enabled
|
||||
* 1. Program the base unit and on-time divisor values.
|
||||
* 2. Set the software update bit.
|
||||
* 3. Repeat the above steps for the next PWM module.
|
||||
*
|
||||
* + After setting PWMCTRL register's SW update bit, hardware automatically
|
||||
* deasserts the SW update bit after a brief delay. It was observed that
|
||||
* setting of PWM enable is typically done via read-modify-write of the PWMCTRL
|
||||
* register. If there is no/little delay between setting software update bit
|
||||
* and setting enable bit via read-modify-write, it is possible that the read
|
||||
* could return with software enable as 1. In that case, the last write to set
|
||||
* enable to 1 could also set sw_update to 1. If this happens, sw_update gets
|
||||
* stuck and the driver code can hang as it explicitly waits for sw_update bit
|
||||
* to be 0 after setting the enable bit to 1. To avoid this race condition,
|
||||
* SW should poll on the software update bit to make sure that it is 0 before
|
||||
* doing the read-modify-write to set the enable bit to 1.
|
||||
*
|
||||
* Also, we noted that if sw_update bit was set in step #1 above then when it
|
||||
* is set again in step #2, sw_update bit never gets cleared and the flow hangs.
|
||||
* As such, we need to make sure that sw_update bit is 0 when doing step #1.
|
||||
*/
|
||||
bool bypass;
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user