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:
Linus Torvalds
2025-03-29 16:59:16 -07:00
98 changed files with 8764 additions and 1181 deletions

View File

@@ -24,6 +24,9 @@ properties:
'#gpio-cells':
const: 2
gpio-ranges:
maxItems: 1
interrupt-controller: true
'#interrupt-cells':

View File

@@ -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";
};
};

View File

@@ -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>;
};
};
};
};

View File

@@ -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.

View File

@@ -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;
};
};
};
...

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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>;
};
};
};
...

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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");

View File

@@ -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)

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)), \

View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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, &regval);
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");

View File

@@ -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>

View File

@@ -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;

View File

@@ -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");

View File

@@ -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", &reg);
if (ret < 0)
return ret;

View File

@@ -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,

View File

@@ -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

View 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);

View 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),
};

View File

@@ -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, &reg_val);
ret = cy8c95x0_regmap_read_bits(chip, CY8C95X0_INPUT, port, bit, &reg_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, &reg_val);
ret = cy8c95x0_regmap_read_bits(chip, CY8C95X0_DIRECTION, port, bit, &reg_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, &reg_val);
ret = cy8c95x0_regmap_read_bits(chip, reg, port, bit, &reg_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)) {

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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];

View File

@@ -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",

View File

@@ -196,6 +196,7 @@ enum rockchip_pinctrl_type {
RK3328,
RK3368,
RK3399,
RK3528,
RK3562,
RK3568,
RK3576,

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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))

View File

@@ -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");

View File

@@ -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)

View 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");

View File

@@ -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)) {

View File

@@ -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,
};

View File

@@ -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");

View File

@@ -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 = {

View File

@@ -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.

View File

@@ -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",

View File

@@ -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;

View File

@@ -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.

View File

@@ -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

View File

@@ -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,

View File

@@ -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,

View File

@@ -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);

View File

@@ -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), \

View File

@@ -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,

View File

@@ -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,

View 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);

View 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");

View 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

View 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");

View 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");

View 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 */

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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
},
{}
};

View File

@@ -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[] = {

View 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);

View 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);

View File

@@ -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[] = {

View File

@@ -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[] = {

View File

@@ -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[] = {

View 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);
}

View File

@@ -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,

View File

@@ -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 */

View File

@@ -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.

View File

@@ -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;

View File

@@ -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

View 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 */

View 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 */

View 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 */

View File

@@ -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 */

View File

@@ -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;
/*