mirror of
https://github.com/u-boot/u-boot.git
synced 2024-12-04 01:53:27 +08:00
- mvebu: Add Armada 38x pin muxing support (Pali) - a37xx: pinctrl: Fix requesting GPIOs and pinmux command (Pali) - mvebu: pinctrl: apply SDHCI PHY config for A7K (Kosta) - gpio: Add Turris Omnia MCU driver (Pali) - cmd: mvebu/bubt: Improvements for image verification (Pali) - mvebu: turris_omnia: Fix mpp26 pin name and comment (Marek)
This commit is contained in:
commit
12fc2c3898
@ -246,7 +246,7 @@
|
||||
};
|
||||
|
||||
nand@d0000 {
|
||||
compatible = "marvell,armada370-nand";
|
||||
compatible = "marvell,armada370-nand-controller";
|
||||
reg = <0xd0000 0x54>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
@ -541,7 +541,7 @@
|
||||
};
|
||||
|
||||
nand@d0000 {
|
||||
compatible = "marvell,armada370-nand";
|
||||
compatible = "marvell,armada370-nand-controller";
|
||||
reg = <0xd0000 0x54>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
@ -28,11 +28,8 @@
|
||||
i2c@5 {
|
||||
u-boot,dm-pre-reloc;
|
||||
|
||||
/* ATSHA204A at address 0x64 */
|
||||
crypto@64 {
|
||||
u-boot,dm-pre-reloc;
|
||||
compatible = "atmel,atsha204a";
|
||||
reg = <0x64>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -42,7 +39,7 @@
|
||||
&spi0 {
|
||||
u-boot,dm-pre-reloc;
|
||||
|
||||
spi-nor@0 {
|
||||
flash@0 {
|
||||
u-boot,dm-pre-reloc;
|
||||
|
||||
partitions {
|
||||
|
@ -1,43 +1,10 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
|
||||
/*
|
||||
* Device Tree file for the Turris Omnia
|
||||
*
|
||||
* Copyright (C) 2016 Uwe Kleine-König <uwe@kleine-koenig.org>
|
||||
* Copyright (C) 2016 Tomas Hlavacek <tmshlvkc@gmail.com>
|
||||
*
|
||||
* This file is dual-licensed: you can use it either under the terms
|
||||
* of the GPL or the X11 license, at your option. Note that this dual
|
||||
* licensing only applies to this file, and not this project as a
|
||||
* whole.
|
||||
*
|
||||
* a) This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without
|
||||
* any warranty of any kind, whether express or implied.
|
||||
*
|
||||
* Or, alternatively,
|
||||
*
|
||||
* b) Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Schematic available at https://www.turris.cz/doc/_media/rtrom01-schema.pdf
|
||||
*/
|
||||
|
||||
@ -45,6 +12,7 @@
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include "armada-385.dtsi"
|
||||
|
||||
/ {
|
||||
@ -70,7 +38,8 @@
|
||||
ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
|
||||
MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000
|
||||
MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000
|
||||
MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>;
|
||||
MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000
|
||||
MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>;
|
||||
|
||||
internal-regs {
|
||||
|
||||
@ -108,19 +77,48 @@
|
||||
pcie@1,0 {
|
||||
/* Port 0, Lane 0 */
|
||||
status = "okay";
|
||||
slot-power-limit-milliwatt = <10000>;
|
||||
};
|
||||
|
||||
pcie@2,0 {
|
||||
/* Port 1, Lane 0 */
|
||||
status = "okay";
|
||||
slot-power-limit-milliwatt = <10000>;
|
||||
};
|
||||
|
||||
pcie@3,0 {
|
||||
/* Port 2, Lane 0 */
|
||||
status = "okay";
|
||||
slot-power-limit-milliwatt = <10000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sfp: sfp {
|
||||
compatible = "sff,sfp";
|
||||
i2c-bus = <&sfp_i2c>;
|
||||
tx-fault-gpios = <&pcawan 0 GPIO_ACTIVE_HIGH>;
|
||||
tx-disable-gpios = <&pcawan 1 GPIO_ACTIVE_HIGH>;
|
||||
rate-select0-gpios = <&pcawan 2 GPIO_ACTIVE_HIGH>;
|
||||
los-gpios = <&pcawan 3 GPIO_ACTIVE_HIGH>;
|
||||
mod-def0-gpios = <&pcawan 4 GPIO_ACTIVE_LOW>;
|
||||
maximum-power-milliwatt = <3000>;
|
||||
|
||||
/*
|
||||
* For now this has to be enabled at boot time by U-Boot when
|
||||
* a SFP module is present. Read more in the comment in the
|
||||
* eth2 node below.
|
||||
*/
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
&bm {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&bm_bppi {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
/* Connected to 88E6176 switch, port 6 */
|
||||
@ -129,6 +127,9 @@
|
||||
pinctrl-0 = <&ge0_rgmii_pins>;
|
||||
status = "okay";
|
||||
phy-mode = "rgmii";
|
||||
buffer-manager = <&bm>;
|
||||
bm,pool-long = <0>;
|
||||
bm,pool-short = <3>;
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
@ -142,6 +143,9 @@
|
||||
pinctrl-0 = <&ge1_rgmii_pins>;
|
||||
status = "okay";
|
||||
phy-mode = "rgmii";
|
||||
buffer-manager = <&bm>;
|
||||
bm,pool-long = <1>;
|
||||
bm,pool-short = <3>;
|
||||
|
||||
fixed-link {
|
||||
speed = <1000>;
|
||||
@ -151,9 +155,23 @@
|
||||
|
||||
/* WAN port */
|
||||
ð2 {
|
||||
/*
|
||||
* eth2 is connected via a multiplexor to both the SFP cage and to
|
||||
* ethernet-phy@1. The multiplexor switches the signal to SFP cage when
|
||||
* a SFP module is present, as determined by the mode-def0 GPIO.
|
||||
*
|
||||
* Until kernel supports this configuration properly, in case SFP module
|
||||
* is present, U-Boot has to enable the sfp node above, remove phy
|
||||
* handle and add managed = "in-band-status" property.
|
||||
*/
|
||||
status = "okay";
|
||||
phy-mode = "sgmii";
|
||||
phy = <&phy1>;
|
||||
phy-handle = <&phy1>;
|
||||
phys = <&comphy5 2>;
|
||||
sfp = <&sfp>;
|
||||
buffer-manager = <&bm>;
|
||||
bm,pool-long = <2>;
|
||||
bm,pool-short = <3>;
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
@ -166,18 +184,128 @@
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x70>;
|
||||
status = "okay";
|
||||
|
||||
i2c@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
|
||||
/* STM32F0 command interface at address 0x2a */
|
||||
/* leds device (in STM32F0) at address 0x2b */
|
||||
/* MCU command i2c API */
|
||||
mcu: mcu@2a {
|
||||
compatible = "cznic,turris-omnia-mcu";
|
||||
reg = <0x2a>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <3>;
|
||||
};
|
||||
|
||||
led-controller@2b {
|
||||
compatible = "cznic,turris-omnia-leds";
|
||||
reg = <0x2b>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "okay";
|
||||
|
||||
/*
|
||||
* LEDs are controlled by MCU (STM32F0) at
|
||||
* address 0x2b.
|
||||
*
|
||||
* LED functions are not stable yet:
|
||||
* - there are 3 LEDs connected via MCU to PCIe
|
||||
* ports. One of these ports supports mSATA.
|
||||
* There is no mSATA nor PCIe function.
|
||||
* For now we use LED_FUNCTION_WLAN, since
|
||||
* in most cases users have wifi cards in
|
||||
* these slots
|
||||
* - there are 2 LEDs dedicated for user: A and
|
||||
* B. Again there is no such function defined.
|
||||
* For now we use LED_FUNCTION_INDICATOR
|
||||
*/
|
||||
|
||||
multi-led@0 {
|
||||
reg = <0x0>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
function-enumerator = <2>;
|
||||
};
|
||||
|
||||
multi-led@1 {
|
||||
reg = <0x1>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_INDICATOR;
|
||||
function-enumerator = <1>;
|
||||
};
|
||||
|
||||
multi-led@2 {
|
||||
reg = <0x2>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_WLAN;
|
||||
function-enumerator = <3>;
|
||||
};
|
||||
|
||||
multi-led@3 {
|
||||
reg = <0x3>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_WLAN;
|
||||
function-enumerator = <2>;
|
||||
};
|
||||
|
||||
multi-led@4 {
|
||||
reg = <0x4>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_WLAN;
|
||||
function-enumerator = <1>;
|
||||
};
|
||||
|
||||
multi-led@5 {
|
||||
reg = <0x5>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_WAN;
|
||||
};
|
||||
|
||||
multi-led@6 {
|
||||
reg = <0x6>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
function-enumerator = <4>;
|
||||
};
|
||||
|
||||
multi-led@7 {
|
||||
reg = <0x7>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
function-enumerator = <3>;
|
||||
};
|
||||
|
||||
multi-led@8 {
|
||||
reg = <0x8>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
function-enumerator = <2>;
|
||||
};
|
||||
|
||||
multi-led@9 {
|
||||
reg = <0x9>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
function-enumerator = <1>;
|
||||
};
|
||||
|
||||
multi-led@a {
|
||||
reg = <0xa>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_LAN;
|
||||
function-enumerator = <0>;
|
||||
};
|
||||
|
||||
multi-led@b {
|
||||
reg = <0xb>;
|
||||
color = <LED_COLOR_ID_RGB>;
|
||||
function = LED_FUNCTION_POWER;
|
||||
};
|
||||
};
|
||||
|
||||
eeprom@54 {
|
||||
compatible = "at,24c64";
|
||||
compatible = "atmel,24c64";
|
||||
reg = <0x54>;
|
||||
|
||||
/* The EEPROM contains data for bootloader.
|
||||
@ -216,7 +344,7 @@
|
||||
/* routed to PCIe2 connector (CN62A) */
|
||||
};
|
||||
|
||||
i2c@4 {
|
||||
sfp_i2c: i2c@4 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <4>;
|
||||
@ -229,7 +357,11 @@
|
||||
#size-cells = <0>;
|
||||
reg = <5>;
|
||||
|
||||
/* ATSHA204A at address 0x64 */
|
||||
/* ATSHA204A-MAHDA-T crypto module */
|
||||
crypto@64 {
|
||||
compatible = "atmel,atsha204a";
|
||||
reg = <0x64>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c@6 {
|
||||
@ -271,23 +403,29 @@
|
||||
pinctrl-0 = <&mdio_pins>;
|
||||
status = "okay";
|
||||
|
||||
phy1: phy@1 {
|
||||
status = "okay";
|
||||
compatible = "ethernet-phy-id0141.0DD1", "ethernet-phy-ieee802.3-c22";
|
||||
phy1: ethernet-phy@1 {
|
||||
compatible = "ethernet-phy-ieee802.3-c22";
|
||||
reg = <1>;
|
||||
marvell,reg-init = <3 18 0 0x4985>,
|
||||
<3 16 0xfff0 0x0001>;
|
||||
|
||||
/* irq is connected to &pcawan pin 7 */
|
||||
};
|
||||
|
||||
/* Switch MV88E6176 at address 0x10 */
|
||||
switch@10 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&swint_pins>;
|
||||
compatible = "marvell,mv88e6085";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
dsa,member = <0 0>;
|
||||
|
||||
dsa,member = <0 0>;
|
||||
reg = <0x10>;
|
||||
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <13 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
@ -340,12 +478,17 @@
|
||||
marvell,function = "gpio";
|
||||
};
|
||||
|
||||
swint_pins: swint-pins {
|
||||
marvell,pins = "mpp45";
|
||||
marvell,function = "gpio";
|
||||
};
|
||||
|
||||
spi0cs0_pins: spi0cs0-pins {
|
||||
marvell,pins = "mpp25";
|
||||
marvell,function = "spi0";
|
||||
};
|
||||
|
||||
spi0cs1_pins: spi0cs1-pins {
|
||||
spi0cs2_pins: spi0cs2-pins {
|
||||
marvell,pins = "mpp26";
|
||||
marvell,function = "spi0";
|
||||
};
|
||||
@ -356,7 +499,7 @@
|
||||
pinctrl-0 = <&spi0_pins &spi0cs0_pins>;
|
||||
status = "okay";
|
||||
|
||||
spi-nor@0 {
|
||||
flash@0 {
|
||||
compatible = "spansion,s25fl164k", "jedec,spi-nor";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
@ -380,7 +523,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
/* MISO, MOSI, SCLK and CS1 are routed to pin header CN11 */
|
||||
/* MISO, MOSI, SCLK and CS2 are routed to pin header CN11 */
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
|
@ -69,17 +69,26 @@
|
||||
reg = <0x0800 0 0 0 0>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
interrupt-names = "intx";
|
||||
interrupts-extended = <&gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#interrupt-cells = <1>;
|
||||
ranges = <0x82000000 0 0 0x82000000 0x1 0 1 0
|
||||
0x81000000 0 0 0x81000000 0x1 0 1 0>;
|
||||
bus-range = <0x00 0xff>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
interrupt-map = <0 0 0 1 &pcie1_intc 0>,
|
||||
<0 0 0 2 &pcie1_intc 1>,
|
||||
<0 0 0 3 &pcie1_intc 2>,
|
||||
<0 0 0 4 &pcie1_intc 3>;
|
||||
marvell,pcie-port = <0>;
|
||||
marvell,pcie-lane = <0>;
|
||||
clocks = <&gateclk 8>;
|
||||
resets = <&systemc 0 0>;
|
||||
status = "disabled";
|
||||
pcie1_intc: interrupt-controller {
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
/* x1 port */
|
||||
@ -89,17 +98,26 @@
|
||||
reg = <0x1000 0 0 0 0>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
interrupt-names = "intx";
|
||||
interrupts-extended = <&gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#interrupt-cells = <1>;
|
||||
ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
|
||||
0x81000000 0 0 0x81000000 0x2 0 1 0>;
|
||||
bus-range = <0x00 0xff>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &gic GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
interrupt-map = <0 0 0 1 &pcie2_intc 0>,
|
||||
<0 0 0 2 &pcie2_intc 1>,
|
||||
<0 0 0 3 &pcie2_intc 2>,
|
||||
<0 0 0 4 &pcie2_intc 3>;
|
||||
marvell,pcie-port = <1>;
|
||||
marvell,pcie-lane = <0>;
|
||||
clocks = <&gateclk 5>;
|
||||
resets = <&systemc 0 1>;
|
||||
status = "disabled";
|
||||
pcie2_intc: interrupt-controller {
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
/* x1 port */
|
||||
@ -109,17 +127,26 @@
|
||||
reg = <0x1800 0 0 0 0>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
interrupt-names = "intx";
|
||||
interrupts-extended = <&gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#interrupt-cells = <1>;
|
||||
ranges = <0x82000000 0 0 0x82000000 0x3 0 1 0
|
||||
0x81000000 0 0 0x81000000 0x3 0 1 0>;
|
||||
bus-range = <0x00 0xff>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
interrupt-map = <0 0 0 1 &pcie3_intc 0>,
|
||||
<0 0 0 2 &pcie3_intc 1>,
|
||||
<0 0 0 3 &pcie3_intc 2>,
|
||||
<0 0 0 4 &pcie3_intc 3>;
|
||||
marvell,pcie-port = <2>;
|
||||
marvell,pcie-lane = <0>;
|
||||
clocks = <&gateclk 6>;
|
||||
resets = <&systemc 0 2>;
|
||||
status = "disabled";
|
||||
pcie3_intc: interrupt-controller {
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
@ -132,17 +159,26 @@
|
||||
reg = <0x2000 0 0 0 0>;
|
||||
#address-cells = <3>;
|
||||
#size-cells = <2>;
|
||||
interrupt-names = "intx";
|
||||
interrupts-extended = <&gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#interrupt-cells = <1>;
|
||||
ranges = <0x82000000 0 0 0x82000000 0x4 0 1 0
|
||||
0x81000000 0 0 0x81000000 0x4 0 1 0>;
|
||||
bus-range = <0x00 0xff>;
|
||||
interrupt-map-mask = <0 0 0 0>;
|
||||
interrupt-map = <0 0 0 0 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
interrupt-map = <0 0 0 1 &pcie4_intc 0>,
|
||||
<0 0 0 2 &pcie4_intc 1>,
|
||||
<0 0 0 3 &pcie4_intc 2>,
|
||||
<0 0 0 4 &pcie4_intc 3>;
|
||||
marvell,pcie-port = <3>;
|
||||
marvell,pcie-lane = <0>;
|
||||
clocks = <&gateclk 7>;
|
||||
resets = <&systemc 0 3>;
|
||||
status = "disabled";
|
||||
pcie4_intc: interrupt-controller {
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -9,13 +9,15 @@
|
||||
* Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
*/
|
||||
|
||||
#include "skeleton.dtsi"
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
#define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
|
||||
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
model = "Marvell Armada 38x family SoC";
|
||||
compatible = "marvell,armada380";
|
||||
|
||||
@ -103,6 +105,11 @@
|
||||
#size-cells = <1>;
|
||||
ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
|
||||
|
||||
sdramc: sdramc@1400 {
|
||||
compatible = "marvell,armada-xp-sdram-controller";
|
||||
reg = <0x1400 0x500>;
|
||||
};
|
||||
|
||||
L2: cache-controller@8000 {
|
||||
compatible = "arm,pl310-cache";
|
||||
reg = <0x8000 0x1000>;
|
||||
@ -148,7 +155,6 @@
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
|
||||
timeout-ms = <1000>;
|
||||
clocks = <&coreclk 0>;
|
||||
status = "disabled";
|
||||
};
|
||||
@ -159,13 +165,12 @@
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
|
||||
timeout-ms = <1000>;
|
||||
clocks = <&coreclk 0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
uart0: serial@12000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
compatible = "marvell,armada-38x-uart", "ns16550a";
|
||||
reg = <0x12000 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
|
||||
@ -175,7 +180,7 @@
|
||||
};
|
||||
|
||||
uart1: serial@12100 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
compatible = "marvell,armada-38x-uart", "ns16550a";
|
||||
reg = <0x12100 0x100>;
|
||||
reg-shift = <2>;
|
||||
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
|
||||
@ -295,6 +300,7 @@
|
||||
reg-names = "gpio", "pwm";
|
||||
ngpios = <32>;
|
||||
gpio-controller;
|
||||
gpio-ranges = <&pinctrl 0 0 32>;
|
||||
#gpio-cells = <2>;
|
||||
#pwm-cells = <2>;
|
||||
interrupt-controller;
|
||||
@ -313,6 +319,7 @@
|
||||
reg-names = "gpio", "pwm";
|
||||
ngpios = <28>;
|
||||
gpio-controller;
|
||||
gpio-ranges = <&pinctrl 0 32 28>;
|
||||
#gpio-cells = <2>;
|
||||
#pwm-cells = <2>;
|
||||
interrupt-controller;
|
||||
@ -338,6 +345,44 @@
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
|
||||
comphy: phy@18300 {
|
||||
compatible = "marvell,armada-380-comphy";
|
||||
reg-names = "comphy", "conf";
|
||||
reg = <0x18300 0x100>, <0x18460 4>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
comphy0: phy@0 {
|
||||
reg = <0>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
|
||||
comphy1: phy@1 {
|
||||
reg = <1>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
|
||||
comphy2: phy@2 {
|
||||
reg = <2>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
|
||||
comphy3: phy@3 {
|
||||
reg = <3>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
|
||||
comphy4: phy@4 {
|
||||
reg = <4>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
|
||||
comphy5: phy@5 {
|
||||
reg = <5>;
|
||||
#phy-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
coreclk: mvebu-sar@18600 {
|
||||
compatible = "marvell,armada-380-core-clock";
|
||||
reg = <0x18600 0x04>;
|
||||
@ -379,6 +424,8 @@
|
||||
reg = <0x20300 0x34>, <0x20704 0x4>, <0x18260 0x4>;
|
||||
clocks = <&coreclk 2>, <&refclk>;
|
||||
clock-names = "nbclk", "fixed";
|
||||
interrupts-extended = <&gic GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<&gic GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
cpurst: cpurst@20800 {
|
||||
@ -555,7 +602,7 @@
|
||||
};
|
||||
|
||||
nand_controller: nand-controller@d0000 {
|
||||
compatible = "marvell,armada370-nand","marvell,mvebu-pxa3xx-nand";
|
||||
compatible = "marvell,armada370-nand-controller";
|
||||
reg = <0xd0000 0x54>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -5,7 +5,7 @@
|
||||
};
|
||||
|
||||
&nand_controller {
|
||||
compatible="marvell,mvebu-pxa3xx-nand";
|
||||
compatible="marvell,armada370-nand-controller";
|
||||
status = "okay";
|
||||
label = "pxa3xx_nand-0";
|
||||
nand-rb = <0>;
|
||||
|
@ -6,4 +6,5 @@ F: arch/arm/dts/armada-385-turris-omnia*.dts*
|
||||
F: board/CZ.NIC/turris_atsha_otp.*
|
||||
F: board/CZ.NIC/turris_omnia/
|
||||
F: configs/turris_omnia_defconfig
|
||||
F: drivers/gpio/turris_omnia_mcu.c
|
||||
F: include/configs/turris_omnia.h
|
||||
|
@ -4,6 +4,7 @@ depends on ARCH_MVEBU
|
||||
config CMD_MVEBU_BUBT
|
||||
bool "bubt"
|
||||
select SHA256 if ARMADA_3700
|
||||
select SHA512 if ARMADA_3700
|
||||
help
|
||||
bubt - Burn a u-boot image to flash
|
||||
For details about bubt command please see the documentation
|
||||
|
102
cmd/mvebu/bubt.c
102
cmd/mvebu/bubt.c
@ -26,6 +26,7 @@
|
||||
#endif
|
||||
#include <u-boot/sha1.h>
|
||||
#include <u-boot/sha256.h>
|
||||
#include <u-boot/sha512.h>
|
||||
|
||||
#if defined(CONFIG_ARMADA_8K)
|
||||
#define MAIN_HDR_MAGIC 0xB105B002
|
||||
@ -56,6 +57,21 @@ struct mvebu_image_header {
|
||||
#define IMAGE_VERSION_3_6_0 0x030600
|
||||
#define IMAGE_VERSION_3_5_0 0x030500
|
||||
|
||||
struct tim_boot_flash_sign {
|
||||
unsigned int id;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct tim_boot_flash_sign tim_boot_flash_signs[] = {
|
||||
{ 0x454d4d08, "mmc" },
|
||||
{ 0x454d4d0b, "mmc" },
|
||||
{ 0x5350490a, "spi" },
|
||||
{ 0x5350491a, "nand" },
|
||||
{ 0x55415223, "uart" },
|
||||
{ 0x53415432, "sata" },
|
||||
{},
|
||||
};
|
||||
|
||||
struct common_tim_data {
|
||||
u32 version;
|
||||
u32 identifier;
|
||||
@ -83,7 +99,7 @@ struct mvebu_image_info {
|
||||
u32 encrypt_start_offset;
|
||||
u32 encrypt_size;
|
||||
};
|
||||
#endif
|
||||
#elif defined(CONFIG_ARMADA_32BIT)
|
||||
|
||||
/* Structure of the main header, version 1 (Armada 370/XP/375/38x/39x) */
|
||||
struct a38x_main_hdr_v1 {
|
||||
@ -123,6 +139,8 @@ struct a38x_boot_mode a38x_boot_modes[] = {
|
||||
{},
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
struct bubt_dev {
|
||||
char name[8];
|
||||
size_t (*read)(const char *file_name);
|
||||
@ -438,11 +456,14 @@ static int is_usb_active(void)
|
||||
#ifdef CONFIG_CMD_NET
|
||||
static size_t tftp_read_file(const char *file_name)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* update global variable image_load_addr before tftp file from network
|
||||
*/
|
||||
image_load_addr = get_load_addr();
|
||||
return net_loop(TFTPGET);
|
||||
ret = net_loop(TFTPGET);
|
||||
return ret > 0 ? ret : 0;
|
||||
}
|
||||
|
||||
static int is_tftp_active(void)
|
||||
@ -546,8 +567,10 @@ static int check_image_header(void)
|
||||
int image_num;
|
||||
u8 hash_160_output[SHA1_SUM_LEN];
|
||||
u8 hash_256_output[SHA256_SUM_LEN];
|
||||
u8 hash_512_output[SHA512_SUM_LEN];
|
||||
sha1_context hash1_text;
|
||||
sha256_context hash256_text;
|
||||
sha512_context hash512_text;
|
||||
u8 *hash_output;
|
||||
u32 hash_algorithm_id;
|
||||
u32 image_size_to_hash;
|
||||
@ -617,6 +640,12 @@ static int check_image_header(void)
|
||||
sha256_finish(&hash256_text, hash_256_output);
|
||||
hash_output = hash_256_output;
|
||||
break;
|
||||
case SHA512_SUM_LEN:
|
||||
sha512_starts(&hash512_text);
|
||||
sha512_update(&hash512_text, buff, image_size_to_hash);
|
||||
sha512_finish(&hash512_text, hash_512_output);
|
||||
hash_output = hash_512_output;
|
||||
break;
|
||||
default:
|
||||
printf("Error: Unsupported hash_algorithm_id = %d\n",
|
||||
hash_algorithm_id);
|
||||
@ -635,7 +664,7 @@ static int check_image_header(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#elif defined(CONFIG_ARMADA_38X)
|
||||
#elif defined(CONFIG_ARMADA_32BIT)
|
||||
static size_t a38x_header_size(const struct a38x_main_hdr_v1 *h)
|
||||
{
|
||||
if (h->version == 1)
|
||||
@ -691,34 +720,39 @@ static int check_image_header(void)
|
||||
|
||||
static int bubt_check_boot_mode(const struct bubt_dev *dst)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_ARMADA_38X)) {
|
||||
int mode;
|
||||
const struct a38x_main_hdr_v1 *hdr =
|
||||
(struct a38x_main_hdr_v1 *)get_load_addr();
|
||||
#if defined(CONFIG_ARMADA_3700) || defined(CONFIG_ARMADA_32BIT)
|
||||
int mode;
|
||||
#if defined(CONFIG_ARMADA_3700)
|
||||
const struct tim_boot_flash_sign *boot_modes = tim_boot_flash_signs;
|
||||
const struct common_tim_data *hdr =
|
||||
(struct common_tim_data *)get_load_addr();
|
||||
u32 id = hdr->boot_flash_sign;
|
||||
#elif defined(CONFIG_ARMADA_32BIT)
|
||||
const struct a38x_boot_mode *boot_modes = a38x_boot_modes;
|
||||
const struct a38x_main_hdr_v1 *hdr =
|
||||
(struct a38x_main_hdr_v1 *)get_load_addr();
|
||||
u32 id = hdr->blockid;
|
||||
#endif
|
||||
|
||||
for (mode = 0; mode < ARRAY_SIZE(a38x_boot_modes); mode++) {
|
||||
if (strcmp(a38x_boot_modes[mode].name, dst->name) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (a38x_boot_modes[mode].id == hdr->blockid)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(a38x_boot_modes); i++) {
|
||||
if (a38x_boot_modes[i].id == hdr->blockid) {
|
||||
printf("Error: A38x image meant to be booted from "
|
||||
"\"%s\", not \"%s\"!\n",
|
||||
a38x_boot_modes[i].name, dst->name);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Error: unknown boot device in A38x image header: "
|
||||
"0x%x\n", hdr->blockid);
|
||||
return -ENOEXEC;
|
||||
} else {
|
||||
return 0;
|
||||
for (mode = 0; boot_modes[mode].name; mode++) {
|
||||
if (boot_modes[mode].id == id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!boot_modes[mode].name) {
|
||||
printf("Error: unknown boot device in image header: 0x%x\n", id);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (strcmp(boot_modes[mode].name, dst->name) == 0)
|
||||
return 0;
|
||||
|
||||
printf("Error: image meant to be booted from \"%s\", not \"%s\"!\n",
|
||||
boot_modes[mode].name, dst->name);
|
||||
return -ENOEXEC;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int bubt_verify(const struct bubt_dev *dst)
|
||||
@ -836,11 +870,11 @@ int do_bubt_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||
dst = find_bubt_dev(dst_dev_name);
|
||||
if (!dst) {
|
||||
printf("Error: Unknown destination \"%s\"\n", dst_dev_name);
|
||||
return -EINVAL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!bubt_is_dev_active(dst))
|
||||
return -ENODEV;
|
||||
return 1;
|
||||
|
||||
/* Figure out the source device */
|
||||
src = find_bubt_dev(src_dev_name);
|
||||
@ -857,15 +891,15 @@ int do_bubt_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||
|
||||
image_size = bubt_read_file(src);
|
||||
if (!image_size)
|
||||
return -EIO;
|
||||
return 1;
|
||||
|
||||
err = bubt_verify(dst);
|
||||
if (err)
|
||||
return err;
|
||||
return 1;
|
||||
|
||||
err = bubt_write_file(dst, image_size);
|
||||
if (err)
|
||||
return err;
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -80,7 +80,6 @@ CONFIG_NETCONSOLE=y
|
||||
CONFIG_SPL_OF_TRANSLATE=y
|
||||
CONFIG_AHCI_PCI=y
|
||||
CONFIG_AHCI_MVEBU=y
|
||||
# CONFIG_MVEBU_GPIO is not set
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_MV=y
|
||||
@ -99,6 +98,8 @@ CONFIG_MVMDIO=y
|
||||
CONFIG_NVME_PCI=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_MVEBU=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_PINCTRL_ARMADA_38X=y
|
||||
CONFIG_DM_RTC=y
|
||||
CONFIG_RTC_ARMADA38X=y
|
||||
CONFIG_SCSI=y
|
||||
|
@ -598,4 +598,11 @@ config SLG7XL45106_I2C_GPO
|
||||
8-bit gpo expander, all gpo lines are controlled by writing
|
||||
value into data register.
|
||||
|
||||
config TURRIS_OMNIA_MCU
|
||||
bool "Turris Omnia MCU GPIO driver"
|
||||
depends on DM_GPIO
|
||||
default y if TARGET_TURRIS_OMNIA
|
||||
help
|
||||
Support for GPIOs on MCU connected to Turris Omnia via i2c.
|
||||
|
||||
endif
|
||||
|
@ -75,3 +75,4 @@ obj-$(CONFIG_MAX7320_GPIO) += max7320_gpio.o
|
||||
obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o
|
||||
obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o
|
||||
obj-$(CONFIG_SLG7XL45106_I2C_GPO) += gpio_slg7xl45106.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)TURRIS_OMNIA_MCU) += turris_omnia_mcu.o
|
||||
|
@ -133,7 +133,7 @@ static int rcar_gpio_get_function(struct udevice *dev, unsigned offset)
|
||||
static int rcar_gpio_request(struct udevice *dev, unsigned offset,
|
||||
const char *label)
|
||||
{
|
||||
return pinctrl_gpio_request(dev, offset);
|
||||
return pinctrl_gpio_request(dev, offset, label);
|
||||
}
|
||||
|
||||
static int rcar_gpio_free(struct udevice *dev, unsigned offset)
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/pinctrl.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/io.h>
|
||||
#include <errno.h>
|
||||
@ -22,7 +23,7 @@ struct mvebu_gpio_regs {
|
||||
|
||||
struct mvebu_gpio_priv {
|
||||
struct mvebu_gpio_regs *regs;
|
||||
char name[2];
|
||||
char name[sizeof("mvebuX_")];
|
||||
};
|
||||
|
||||
static int mvebu_gpio_direction_input(struct udevice *dev, unsigned int gpio)
|
||||
@ -91,14 +92,18 @@ static int mvebu_gpio_probe(struct udevice *dev)
|
||||
struct mvebu_gpio_priv *priv = dev_get_priv(dev);
|
||||
|
||||
priv->regs = dev_read_addr_ptr(dev);
|
||||
uc_priv->gpio_count = MVEBU_GPIOS_PER_BANK;
|
||||
priv->name[0] = 'A' + dev_seq(dev);
|
||||
uc_priv->gpio_count = dev_read_u32_default(dev, "ngpios", MVEBU_GPIOS_PER_BANK);
|
||||
sprintf(priv->name, "mvebu%d_", dev_seq(dev));
|
||||
uc_priv->bank_name = priv->name;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_gpio_ops mvebu_gpio_ops = {
|
||||
#if CONFIG_IS_ENABLED(PINCTRL_ARMADA_38X)
|
||||
.request = pinctrl_gpio_request,
|
||||
.rfree = pinctrl_gpio_free,
|
||||
#endif
|
||||
.direction_input = mvebu_gpio_direction_input,
|
||||
.direction_output = mvebu_gpio_direction_output,
|
||||
.get_function = mvebu_gpio_get_function,
|
||||
|
309
drivers/gpio/turris_omnia_mcu.c
Normal file
309
drivers/gpio/turris_omnia_mcu.c
Normal file
@ -0,0 +1,309 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
// (C) 2022 Pali Rohár <pali@kernel.org>
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <linux/log2.h>
|
||||
|
||||
enum commands_e {
|
||||
CMD_GET_STATUS_WORD = 0x01,
|
||||
CMD_GENERAL_CONTROL = 0x02,
|
||||
|
||||
/* available if STS_FEATURES_SUPPORTED bit set in status word */
|
||||
CMD_GET_FEATURES = 0x10,
|
||||
|
||||
/* available if FEAT_EXT_CMDS bit is set in features */
|
||||
CMD_GET_EXT_STATUS_DWORD = 0x11,
|
||||
CMD_EXT_CONTROL = 0x12,
|
||||
CMD_GET_EXT_CONTROL_STATUS = 0x13,
|
||||
};
|
||||
|
||||
/* CMD_GET_STATUS_WORD */
|
||||
enum sts_word_e {
|
||||
STS_MCU_TYPE_MASK = GENMASK(1, 0),
|
||||
STS_MCU_TYPE_STM32 = 0,
|
||||
STS_MCU_TYPE_GD32 = 1,
|
||||
STS_MCU_TYPE_MKL = 2,
|
||||
STS_FEATURES_SUPPORTED = BIT(2),
|
||||
STS_USER_REGULATOR_NOT_SUPPORTED = BIT(3),
|
||||
STS_CARD_DET = BIT(4),
|
||||
STS_MSATA_IND = BIT(5),
|
||||
STS_USB30_OVC = BIT(6),
|
||||
STS_USB31_OVC = BIT(7),
|
||||
STS_USB30_PWRON = BIT(8),
|
||||
STS_USB31_PWRON = BIT(9),
|
||||
STS_ENABLE_4V5 = BIT(10),
|
||||
STS_BUTTON_MODE = BIT(11),
|
||||
STS_BUTTON_PRESSED = BIT(12),
|
||||
STS_BUTTON_COUNTER_MASK = GENMASK(15, 13)
|
||||
};
|
||||
|
||||
/* CMD_GENERAL_CONTROL */
|
||||
enum ctl_byte_e {
|
||||
CTL_LIGHT_RST = BIT(0),
|
||||
CTL_HARD_RST = BIT(1),
|
||||
/*CTL_RESERVED = BIT(2),*/
|
||||
CTL_USB30_PWRON = BIT(3),
|
||||
CTL_USB31_PWRON = BIT(4),
|
||||
CTL_ENABLE_4V5 = BIT(5),
|
||||
CTL_BUTTON_MODE = BIT(6),
|
||||
CTL_BOOTLOADER = BIT(7)
|
||||
};
|
||||
|
||||
/* CMD_GET_FEATURES */
|
||||
enum features_e {
|
||||
FEAT_EXT_CMDS = BIT(1),
|
||||
};
|
||||
|
||||
struct turris_omnia_mcu_info {
|
||||
u16 features;
|
||||
};
|
||||
|
||||
static int turris_omnia_mcu_get_function(struct udevice *dev, uint offset)
|
||||
{
|
||||
struct turris_omnia_mcu_info *info = dev_get_plat(dev);
|
||||
|
||||
switch (offset) {
|
||||
/* bank 0 */
|
||||
case 0 ... 15:
|
||||
switch (offset) {
|
||||
case ilog2(STS_USB30_PWRON):
|
||||
case ilog2(STS_USB31_PWRON):
|
||||
case ilog2(STS_ENABLE_4V5):
|
||||
case ilog2(STS_BUTTON_MODE):
|
||||
return GPIOF_OUTPUT;
|
||||
default:
|
||||
return GPIOF_INPUT;
|
||||
}
|
||||
|
||||
/* bank 1 - supported only when FEAT_EXT_CMDS is set */
|
||||
case (16 + 0) ... (16 + 31):
|
||||
if (!(info->features & FEAT_EXT_CMDS))
|
||||
return -EINVAL;
|
||||
return GPIOF_INPUT;
|
||||
|
||||
/* bank 2 - supported only when FEAT_EXT_CMDS is set */
|
||||
case (16 + 32 + 0) ... (16 + 32 + 15):
|
||||
if (!(info->features & FEAT_EXT_CMDS))
|
||||
return -EINVAL;
|
||||
return GPIOF_OUTPUT;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int turris_omnia_mcu_get_value(struct udevice *dev, uint offset)
|
||||
{
|
||||
struct turris_omnia_mcu_info *info = dev_get_plat(dev);
|
||||
u8 val16[2];
|
||||
u8 val32[4];
|
||||
int ret;
|
||||
|
||||
switch (offset) {
|
||||
/* bank 0 */
|
||||
case 0 ... 15:
|
||||
ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, val16, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
return ((((u16)val16[1] << 8) | val16[0]) >> offset) & 0x1;
|
||||
|
||||
/* bank 1 - supported only when FEAT_EXT_CMDS is set */
|
||||
case (16 + 0) ... (16 + 31):
|
||||
if (!(info->features & FEAT_EXT_CMDS))
|
||||
return -EINVAL;
|
||||
ret = dm_i2c_read(dev, CMD_GET_EXT_STATUS_DWORD, val32, 4);
|
||||
if (ret)
|
||||
return ret;
|
||||
return ((((u32)val32[3] << 24) | ((u32)val32[2] << 16) |
|
||||
((u32)val32[1] << 8) | val32[0]) >> (offset - 16)) & 0x1;
|
||||
|
||||
/* bank 2 - supported only when FEAT_EXT_CMDS is set */
|
||||
case (16 + 32 + 0) ... (16 + 32 + 15):
|
||||
if (!(info->features & FEAT_EXT_CMDS))
|
||||
return -EINVAL;
|
||||
ret = dm_i2c_read(dev, CMD_GET_EXT_CONTROL_STATUS, val16, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
return ((((u16)val16[1] << 8) | val16[0]) >> (offset - 16 - 32)) & 0x1;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int turris_omnia_mcu_set_value(struct udevice *dev, uint offset, int value)
|
||||
{
|
||||
struct turris_omnia_mcu_info *info = dev_get_plat(dev);
|
||||
u8 val[2];
|
||||
int ret;
|
||||
u8 reg;
|
||||
|
||||
switch (offset) {
|
||||
/* bank 0 */
|
||||
case ilog2(STS_USB30_PWRON):
|
||||
reg = CMD_GENERAL_CONTROL;
|
||||
val[1] = CTL_USB30_PWRON;
|
||||
break;
|
||||
case ilog2(STS_USB31_PWRON):
|
||||
reg = CMD_GENERAL_CONTROL;
|
||||
val[1] = CTL_USB31_PWRON;
|
||||
break;
|
||||
case ilog2(STS_ENABLE_4V5):
|
||||
reg = CMD_GENERAL_CONTROL;
|
||||
val[1] = CTL_ENABLE_4V5;
|
||||
break;
|
||||
case ilog2(STS_BUTTON_MODE):
|
||||
reg = CMD_GENERAL_CONTROL;
|
||||
val[1] = CTL_BUTTON_MODE;
|
||||
break;
|
||||
|
||||
/* bank 2 - supported only when FEAT_EXT_CMDS is set */
|
||||
case (16 + 32 + 0) ... (16 + 32 + 15):
|
||||
if (!(info->features & FEAT_EXT_CMDS))
|
||||
return -EINVAL;
|
||||
reg = CMD_EXT_CONTROL;
|
||||
val[1] = BIT(offset - 16 - 32);
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val[0] = value ? val[1] : 0;
|
||||
|
||||
ret = dm_i2c_write(dev, reg, val, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int turris_omnia_mcu_direction_input(struct udevice *dev, uint offset)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = turris_omnia_mcu_get_function(dev, offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret != GPIOF_INPUT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int turris_omnia_mcu_direction_output(struct udevice *dev, uint offset, int value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = turris_omnia_mcu_get_function(dev, offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret != GPIOF_OUTPUT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return turris_omnia_mcu_set_value(dev, offset, value);
|
||||
}
|
||||
|
||||
static int turris_omnia_mcu_xlate(struct udevice *dev, struct gpio_desc *desc,
|
||||
struct ofnode_phandle_args *args)
|
||||
{
|
||||
uint bank, gpio, flags, offset;
|
||||
int ret;
|
||||
|
||||
if (args->args_count != 3)
|
||||
return -EINVAL;
|
||||
|
||||
bank = args->args[0];
|
||||
gpio = args->args[1];
|
||||
flags = args->args[2];
|
||||
|
||||
switch (bank) {
|
||||
case 0:
|
||||
if (gpio >= 16)
|
||||
return -EINVAL;
|
||||
offset = gpio;
|
||||
break;
|
||||
case 1:
|
||||
if (gpio >= 32)
|
||||
return -EINVAL;
|
||||
offset = 16 + gpio;
|
||||
break;
|
||||
case 2:
|
||||
if (gpio >= 16)
|
||||
return -EINVAL;
|
||||
offset = 16 + 32 + gpio;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = turris_omnia_mcu_get_function(dev, offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
desc->offset = offset;
|
||||
desc->flags = gpio_flags_xlate(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dm_gpio_ops turris_omnia_mcu_ops = {
|
||||
.direction_input = turris_omnia_mcu_direction_input,
|
||||
.direction_output = turris_omnia_mcu_direction_output,
|
||||
.get_value = turris_omnia_mcu_get_value,
|
||||
.set_value = turris_omnia_mcu_set_value,
|
||||
.get_function = turris_omnia_mcu_get_function,
|
||||
.xlate = turris_omnia_mcu_xlate,
|
||||
};
|
||||
|
||||
static int turris_omnia_mcu_probe(struct udevice *dev)
|
||||
{
|
||||
struct turris_omnia_mcu_info *info = dev_get_plat(dev);
|
||||
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
||||
u16 status;
|
||||
u8 val[2];
|
||||
int ret;
|
||||
|
||||
ret = dm_i2c_read(dev, CMD_GET_STATUS_WORD, val, 2);
|
||||
if (ret) {
|
||||
printf("Error: turris_omnia_mcu CMD_GET_STATUS_WORD failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
status = ((u16)val[1] << 8) | val[0];
|
||||
|
||||
if (status & STS_FEATURES_SUPPORTED) {
|
||||
ret = dm_i2c_read(dev, CMD_GET_FEATURES, val, 2);
|
||||
if (ret) {
|
||||
printf("Error: turris_omnia_mcu CMD_GET_FEATURES failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
info->features = ((u16)val[1] << 8) | val[0];
|
||||
}
|
||||
|
||||
uc_priv->bank_name = "mcu_";
|
||||
|
||||
if (info->features & FEAT_EXT_CMDS)
|
||||
uc_priv->gpio_count = 16 + 32 + 16;
|
||||
else
|
||||
uc_priv->gpio_count = 16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id turris_omnia_mcu_ids[] = {
|
||||
{ .compatible = "cznic,turris-omnia-mcu" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(turris_omnia_mcu) = {
|
||||
.name = "turris-omnia-mcu",
|
||||
.id = UCLASS_GPIO,
|
||||
.ops = &turris_omnia_mcu_ops,
|
||||
.probe = turris_omnia_mcu_probe,
|
||||
.plat_auto = sizeof(struct turris_omnia_mcu_info),
|
||||
.of_match = turris_omnia_mcu_ids,
|
||||
};
|
@ -429,7 +429,7 @@ static struct nand_ecclayout ecc_layout_8KB_bch8bit = {
|
||||
|
||||
static const struct udevice_id pxa3xx_nand_dt_ids[] = {
|
||||
{
|
||||
.compatible = "marvell,mvebu-pxa3xx-nand",
|
||||
.compatible = "marvell,armada370-nand-controller",
|
||||
.data = PXA3XX_NAND_VARIANT_ARMADA370,
|
||||
},
|
||||
{
|
||||
|
@ -1,5 +1,12 @@
|
||||
if ARCH_MVEBU
|
||||
|
||||
config PINCTRL_ARMADA_38X
|
||||
depends on ARMADA_38X && PINCTRL_FULL
|
||||
bool "Armada 38x pin control driver"
|
||||
help
|
||||
Support pin multiplexing and pin configuration control on
|
||||
Marvell's Armada-38x SoC.
|
||||
|
||||
config PINCTRL_ARMADA_37XX
|
||||
depends on ARMADA_3700 && PINCTRL_FULL
|
||||
bool "Armada 37xx pin control driver"
|
||||
|
@ -4,5 +4,6 @@
|
||||
#
|
||||
# https://spdx.org/licenses
|
||||
|
||||
obj-$(CONFIG_PINCTRL_ARMADA_38X) += pinctrl-armada-38x.o
|
||||
obj-$(CONFIG_PINCTRL_ARMADA_37XX) += pinctrl-armada-37xx.o
|
||||
obj-$(CONFIG_PINCTRL_ARMADA_8K) += pinctrl-mvebu.o
|
||||
|
@ -65,7 +65,6 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
* belonging to the group
|
||||
* @npins: Number of pins included in the second optional range
|
||||
* @funcs: A list of pinmux functions that can be selected for this group.
|
||||
* @pins: List of the pins included in the group
|
||||
*/
|
||||
struct armada_37xx_pin_group {
|
||||
const char *name;
|
||||
@ -76,7 +75,6 @@ struct armada_37xx_pin_group {
|
||||
unsigned int extra_pin;
|
||||
unsigned int extra_npins;
|
||||
const char *funcs[NB_FUNCS];
|
||||
unsigned int *pins;
|
||||
};
|
||||
|
||||
struct armada_37xx_pin_data {
|
||||
@ -97,8 +95,6 @@ struct armada_37xx_pinctrl {
|
||||
const struct armada_37xx_pin_data *data;
|
||||
struct udevice *dev;
|
||||
struct pinctrl_dev *pctl_dev;
|
||||
struct armada_37xx_pin_group *groups;
|
||||
unsigned int ngroups;
|
||||
struct armada_37xx_pmx_func *funcs;
|
||||
unsigned int nfuncs;
|
||||
};
|
||||
@ -113,6 +109,16 @@ struct armada_37xx_pinctrl {
|
||||
.funcs = {_func1, _func2} \
|
||||
}
|
||||
|
||||
#define PIN_GRP_GPIO_0(_name, _start, _nr) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.start_pin = _start, \
|
||||
.npins = _nr, \
|
||||
.reg_mask = 0, \
|
||||
.val = {0}, \
|
||||
.funcs = {"gpio"} \
|
||||
}
|
||||
|
||||
#define PIN_GRP_GPIO(_name, _start, _nr, _mask, _func1) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
@ -170,6 +176,7 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = {
|
||||
"pwm", "led"),
|
||||
PIN_GRP_GPIO("pmic1", 7, 1, BIT(7), "pmic"),
|
||||
PIN_GRP_GPIO("pmic0", 6, 1, BIT(8), "pmic"),
|
||||
PIN_GRP_GPIO_0("gpio1_5", 5, 1),
|
||||
PIN_GRP_GPIO("i2c2", 2, 2, BIT(9), "i2c"),
|
||||
PIN_GRP_GPIO("i2c1", 0, 2, BIT(10), "i2c"),
|
||||
PIN_GRP_GPIO("spi_cs1", 17, 1, BIT(12), "spi"),
|
||||
@ -186,10 +193,13 @@ static struct armada_37xx_pin_group armada_37xx_nb_groups[] = {
|
||||
static struct armada_37xx_pin_group armada_37xx_sb_groups[] = {
|
||||
PIN_GRP_GPIO("usb32_drvvbus0", 0, 1, BIT(0), "drvbus"),
|
||||
PIN_GRP_GPIO("usb2_drvvbus1", 1, 1, BIT(1), "drvbus"),
|
||||
PIN_GRP_GPIO_0("gpio2_2", 2, 1),
|
||||
PIN_GRP_GPIO("sdio_sb", 24, 6, BIT(2), "sdio"),
|
||||
PIN_GRP_GPIO("rgmii", 6, 12, BIT(3), "mii"),
|
||||
PIN_GRP_GPIO("smi", 18, 2, BIT(4), "smi"),
|
||||
PIN_GRP_GPIO("pcie1", 3, 3, BIT(5) | BIT(9) | BIT(10), "pcie"),
|
||||
PIN_GRP_GPIO("pcie1", 3, 1, BIT(5), "pcie"), /* this actually controls "pcie1_reset" */
|
||||
PIN_GRP_GPIO("pcie1_clkreq", 4, 1, BIT(9), "pcie"),
|
||||
PIN_GRP_GPIO("pcie1_wakeup", 5, 1, BIT(10), "pcie"),
|
||||
PIN_GRP_GPIO("ptp", 20, 3, BIT(11) | BIT(12) | BIT(13), "ptp"),
|
||||
PIN_GRP("ptp_clk", 21, 1, BIT(6), "ptp", "mii"),
|
||||
PIN_GRP("ptp_trig", 22, 1, BIT(7), "ptp", "mii"),
|
||||
@ -197,14 +207,14 @@ static struct armada_37xx_pin_group armada_37xx_sb_groups[] = {
|
||||
"mii", "mii_err"),
|
||||
};
|
||||
|
||||
const struct armada_37xx_pin_data armada_37xx_pin_nb = {
|
||||
static const struct armada_37xx_pin_data armada_37xx_pin_nb = {
|
||||
.nr_pins = 36,
|
||||
.name = "GPIO1",
|
||||
.groups = armada_37xx_nb_groups,
|
||||
.ngroups = ARRAY_SIZE(armada_37xx_nb_groups),
|
||||
};
|
||||
|
||||
const struct armada_37xx_pin_data armada_37xx_pin_sb = {
|
||||
static const struct armada_37xx_pin_data armada_37xx_pin_sb = {
|
||||
.nr_pins = 30,
|
||||
.name = "GPIO2",
|
||||
.groups = armada_37xx_sb_groups,
|
||||
@ -237,7 +247,7 @@ static int armada_37xx_pmx_get_groups_count(struct udevice *dev)
|
||||
{
|
||||
struct armada_37xx_pinctrl *info = dev_get_priv(dev);
|
||||
|
||||
return info->ngroups;
|
||||
return info->data->ngroups;
|
||||
}
|
||||
|
||||
static const char *armada_37xx_pmx_dummy_name = "_dummy";
|
||||
@ -247,10 +257,10 @@ static const char *armada_37xx_pmx_get_group_name(struct udevice *dev,
|
||||
{
|
||||
struct armada_37xx_pinctrl *info = dev_get_priv(dev);
|
||||
|
||||
if (!info->groups[selector].name)
|
||||
if (!info->data->groups[selector].name)
|
||||
return armada_37xx_pmx_dummy_name;
|
||||
|
||||
return info->groups[selector].name;
|
||||
return info->data->groups[selector].name;
|
||||
}
|
||||
|
||||
static int armada_37xx_pmx_get_funcs_count(struct udevice *dev)
|
||||
@ -270,12 +280,13 @@ static const char *armada_37xx_pmx_get_func_name(struct udevice *dev,
|
||||
|
||||
static int armada_37xx_pmx_set_by_name(struct udevice *dev,
|
||||
const char *name,
|
||||
struct armada_37xx_pin_group *grp)
|
||||
struct armada_37xx_pin_group *grp,
|
||||
bool warn_on_change)
|
||||
{
|
||||
struct armada_37xx_pinctrl *info = dev_get_priv(dev);
|
||||
unsigned int reg = SELECTION;
|
||||
unsigned int mask = grp->reg_mask;
|
||||
int func, val;
|
||||
int func, val, old_func;
|
||||
|
||||
dev_dbg(info->dev, "enable function %s group %s\n",
|
||||
name, grp->name);
|
||||
@ -287,6 +298,18 @@ static int armada_37xx_pmx_set_by_name(struct udevice *dev,
|
||||
|
||||
val = grp->val[func];
|
||||
|
||||
if (warn_on_change && val != (readl(info->base + reg) & mask)) {
|
||||
for (old_func = 0; (old_func < NB_FUNCS) && grp->funcs[old_func]; old_func++) {
|
||||
if (grp->val[old_func] == val)
|
||||
break;
|
||||
}
|
||||
dev_warn(info->dev, "Warning: Changing MPPs %u-%u function from %s to %s...\n",
|
||||
grp->start_pin, grp->start_pin + grp->npins - 1,
|
||||
((old_func < NB_FUNCS && grp->funcs[old_func]) ?
|
||||
grp->funcs[old_func] : "unknown"),
|
||||
name);
|
||||
}
|
||||
|
||||
clrsetbits_le32(info->base + reg, mask, val);
|
||||
|
||||
return 0;
|
||||
@ -297,10 +320,112 @@ static int armada_37xx_pmx_group_set(struct udevice *dev,
|
||||
unsigned func_selector)
|
||||
{
|
||||
struct armada_37xx_pinctrl *info = dev_get_priv(dev);
|
||||
struct armada_37xx_pin_group *grp = &info->groups[group_selector];
|
||||
struct armada_37xx_pin_group *grp = &info->data->groups[group_selector];
|
||||
const char *name = info->funcs[func_selector].name;
|
||||
|
||||
return armada_37xx_pmx_set_by_name(dev, name, grp);
|
||||
return armada_37xx_pmx_set_by_name(dev, name, grp, false);
|
||||
}
|
||||
|
||||
static int armada_37xx_pmx_gpio_request_enable(struct udevice *dev, unsigned int selector)
|
||||
{
|
||||
struct armada_37xx_pinctrl *info = dev_get_priv(dev);
|
||||
int ret = -ENOTSUPP;
|
||||
int n;
|
||||
|
||||
/* Find all groups where is requested selector pin and set each group to gpio function */
|
||||
for (n = 0; n < info->data->ngroups; n++) {
|
||||
struct armada_37xx_pin_group *grp = &info->data->groups[n];
|
||||
|
||||
if ((selector >= grp->start_pin && selector < grp->start_pin + grp->npins) ||
|
||||
(selector >= grp->extra_pin && selector < grp->extra_pin + grp->extra_npins)) {
|
||||
ret = armada_37xx_pmx_set_by_name(dev, "gpio", grp, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int armada_37xx_pmx_gpio_disable_free(struct udevice *dev, unsigned int selector)
|
||||
{
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int armada_37xx_pmx_get_pins_count(struct udevice *dev)
|
||||
{
|
||||
struct armada_37xx_pinctrl *info = dev_get_priv(dev);
|
||||
|
||||
return info->data->nr_pins;
|
||||
}
|
||||
|
||||
static const char *armada_37xx_pmx_get_pin_name(struct udevice *dev, unsigned int selector)
|
||||
{
|
||||
struct armada_37xx_pinctrl *info = dev_get_priv(dev);
|
||||
static char buf[sizeof("MPPx_XX")];
|
||||
|
||||
sprintf(buf, "MPP%c_%u", info->data->name[4], selector);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int armada_37xx_pmx_get_pin_muxing(struct udevice *dev, unsigned int selector,
|
||||
char *buf, int size)
|
||||
{
|
||||
struct armada_37xx_pinctrl *info = dev_get_priv(dev);
|
||||
int n;
|
||||
|
||||
/*
|
||||
* First check if selected pin is in some extra pin group.
|
||||
* Function in extra pin group is active only when it is not gpio.
|
||||
*/
|
||||
for (n = 0; n < info->data->ngroups; n++) {
|
||||
struct armada_37xx_pin_group *grp = &info->data->groups[n];
|
||||
|
||||
if (selector >= grp->extra_pin && selector < grp->extra_pin + grp->extra_npins) {
|
||||
unsigned int reg = SELECTION;
|
||||
unsigned int mask = grp->reg_mask;
|
||||
int f, val;
|
||||
|
||||
val = (readl(info->base + reg) & mask);
|
||||
|
||||
for (f = 0; f < NB_FUNCS && grp->funcs[f]; f++) {
|
||||
if (grp->val[f] == val) {
|
||||
if (strcmp(grp->funcs[f], "gpio") != 0) {
|
||||
strlcpy(buf, grp->funcs[f], size);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If pin is not active in some extra pin group then check regular groups. */
|
||||
for (n = 0; n < info->data->ngroups; n++) {
|
||||
struct armada_37xx_pin_group *grp = &info->data->groups[n];
|
||||
|
||||
if (selector >= grp->start_pin && selector < grp->start_pin + grp->npins) {
|
||||
unsigned int reg = SELECTION;
|
||||
unsigned int mask = grp->reg_mask;
|
||||
int f, val;
|
||||
|
||||
val = (readl(info->base + reg) & mask);
|
||||
|
||||
for (f = 0; f < NB_FUNCS && grp->funcs[f]; f++) {
|
||||
if (grp->val[f] == val) {
|
||||
strlcpy(buf, grp->funcs[f], size);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
strlcpy(buf, "unknown", size);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
strlcpy(buf, "unknown", size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -352,21 +477,9 @@ static int armada_37xx_fill_group(struct armada_37xx_pinctrl *info)
|
||||
{
|
||||
int n, num = 0, funcsize = info->data->nr_pins;
|
||||
|
||||
for (n = 0; n < info->ngroups; n++) {
|
||||
struct armada_37xx_pin_group *grp = &info->groups[n];
|
||||
int i, j, f;
|
||||
|
||||
grp->pins = devm_kzalloc(info->dev,
|
||||
(grp->npins + grp->extra_npins) *
|
||||
sizeof(*grp->pins), GFP_KERNEL);
|
||||
if (!grp->pins)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < grp->npins; i++)
|
||||
grp->pins[i] = grp->start_pin + i;
|
||||
|
||||
for (j = 0; j < grp->extra_npins; j++)
|
||||
grp->pins[i+j] = grp->extra_pin + j;
|
||||
for (n = 0; n < info->data->ngroups; n++) {
|
||||
struct armada_37xx_pin_group *grp = &info->data->groups[n];
|
||||
int f;
|
||||
|
||||
for (f = 0; (f < NB_FUNCS) && grp->funcs[f]; f++) {
|
||||
int ret;
|
||||
@ -416,8 +529,8 @@ static int armada_37xx_fill_func(struct armada_37xx_pinctrl *info)
|
||||
|
||||
groups = funcs[n].groups;
|
||||
|
||||
for (g = 0; g < info->ngroups; g++) {
|
||||
struct armada_37xx_pin_group *gp = &info->groups[g];
|
||||
for (g = 0; g < info->data->ngroups; g++) {
|
||||
struct armada_37xx_pin_group *gp = &info->data->groups[g];
|
||||
int f;
|
||||
|
||||
for (f = 0; (f < NB_FUNCS) && gp->funcs[f]; f++) {
|
||||
@ -522,6 +635,8 @@ static int armada_37xx_gpio_probe(struct udevice *dev)
|
||||
}
|
||||
|
||||
static const struct dm_gpio_ops armada_37xx_gpio_ops = {
|
||||
.request = pinctrl_gpio_request,
|
||||
.rfree = pinctrl_gpio_free,
|
||||
.set_value = armada_37xx_gpio_set,
|
||||
.get_value = armada_37xx_gpio_get,
|
||||
.get_function = armada_37xx_gpio_get_direction,
|
||||
@ -574,16 +689,21 @@ static int armada_37xx_gpiochip_register(struct udevice *parent,
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct pinctrl_ops armada_37xx_pinctrl_ops = {
|
||||
static const struct pinctrl_ops armada_37xx_pinctrl_ops = {
|
||||
.get_pins_count = armada_37xx_pmx_get_pins_count,
|
||||
.get_pin_name = armada_37xx_pmx_get_pin_name,
|
||||
.get_pin_muxing = armada_37xx_pmx_get_pin_muxing,
|
||||
.get_groups_count = armada_37xx_pmx_get_groups_count,
|
||||
.get_group_name = armada_37xx_pmx_get_group_name,
|
||||
.get_functions_count = armada_37xx_pmx_get_funcs_count,
|
||||
.get_function_name = armada_37xx_pmx_get_func_name,
|
||||
.pinmux_group_set = armada_37xx_pmx_group_set,
|
||||
.gpio_request_enable = armada_37xx_pmx_gpio_request_enable,
|
||||
.gpio_disable_free = armada_37xx_pmx_gpio_disable_free,
|
||||
.set_state = pinctrl_generic_set_state,
|
||||
};
|
||||
|
||||
int armada_37xx_pinctrl_probe(struct udevice *dev)
|
||||
static int armada_37xx_pinctrl_probe(struct udevice *dev)
|
||||
{
|
||||
struct armada_37xx_pinctrl *info = dev_get_priv(dev);
|
||||
const struct armada_37xx_pin_data *pin_data;
|
||||
@ -598,9 +718,6 @@ int armada_37xx_pinctrl_probe(struct udevice *dev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
info->groups = pin_data->groups;
|
||||
info->ngroups = pin_data->ngroups;
|
||||
|
||||
/*
|
||||
* we allocate functions for number of pins and hope there are
|
||||
* fewer unique functions than pins available
|
||||
|
589
drivers/pinctrl/mvebu/pinctrl-armada-38x.c
Normal file
589
drivers/pinctrl/mvebu/pinctrl-armada-38x.c
Normal file
@ -0,0 +1,589 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// (C) 2022 Pali Rohár <pali@kernel.org>
|
||||
|
||||
#include <common.h>
|
||||
#include <config.h>
|
||||
#include <dm.h>
|
||||
#include <dm/devres.h>
|
||||
#include <dm/lists.h>
|
||||
#include <dm/pinctrl.h>
|
||||
#include <dm/root.h>
|
||||
#include <errno.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
struct mvebu_mpp_ctrl_setting {
|
||||
const char *name;
|
||||
const char *subname;
|
||||
u8 val;
|
||||
u8 variant;
|
||||
};
|
||||
|
||||
struct mvebu_mpp_mode {
|
||||
const char *name;
|
||||
size_t nsettings;
|
||||
struct mvebu_mpp_ctrl_setting *settings;
|
||||
};
|
||||
|
||||
#define MPP_MODE(_name, ...) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.nsettings = ARRAY_SIZE(( \
|
||||
(struct mvebu_mpp_ctrl_setting[]) \
|
||||
{ __VA_ARGS__ })), \
|
||||
.settings = (struct mvebu_mpp_ctrl_setting[]){ \
|
||||
__VA_ARGS__ }, \
|
||||
}
|
||||
|
||||
#define MPP_VAR_FUNCTION(_val, _name, _subname, _mask) \
|
||||
{ \
|
||||
.val = _val, \
|
||||
.name = _name, \
|
||||
.subname = _subname, \
|
||||
.variant = _mask, \
|
||||
}
|
||||
|
||||
#define MVEBU_MPPS_PER_REG 8
|
||||
#define MVEBU_MPP_BITS 4
|
||||
#define MVEBU_MPP_MASK 0xf
|
||||
|
||||
enum {
|
||||
V_88F6810 = BIT(0),
|
||||
V_88F6820 = BIT(1),
|
||||
V_88F6828 = BIT(2),
|
||||
V_88F6810_PLUS = (V_88F6810 | V_88F6820 | V_88F6828),
|
||||
V_88F6820_PLUS = (V_88F6820 | V_88F6828),
|
||||
};
|
||||
|
||||
static struct mvebu_mpp_mode armada_38x_mpp_modes[] = {
|
||||
MPP_MODE("mpp0",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ua0", "rxd", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp1",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ua0", "txd", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp2",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "i2c0", "sck", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp3",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "i2c0", "sda", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp4",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge", "mdc", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ua1", "txd", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "ua0", "rts", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp5",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge", "mdio", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ua1", "rxd", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "ua0", "cts", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp6",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "txclkout", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge0", "crs", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "cs3", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp7",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "txd0", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad9", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp8",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "txd1", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad10", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp9",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "txd2", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad11", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp10",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "txd3", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad12", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp11",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "txctl", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad13", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp12",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "rxd0", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "pcie0", "rstout", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi0", "cs1", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad14", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "pcie3", "clkreq", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp13",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "rxd1", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "pcie0", "clkreq", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "pcie1", "clkreq", V_88F6820_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi0", "cs2", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad15", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "pcie2", "clkreq", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp14",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "rxd2", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ptp", "clk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "dram", "vttctrl", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi0", "cs3", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "we1", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "pcie3", "clkreq", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp15",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "rxd3", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge", "mdc slave", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "pcie0", "rstout", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi0", "mosi", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp16",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "rxctl", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge", "mdio slave", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "dram", "deccerr", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi0", "miso", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "pcie0", "clkreq", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "pcie1", "clkreq", V_88F6820_PLUS)),
|
||||
MPP_MODE("mpp17",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "rxclk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ptp", "clk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "ua1", "rxd", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi0", "sck", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "sata1", "prsnt", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "sata0", "prsnt", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp18",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "rxerr", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ptp", "trig", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "ua1", "txd", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi0", "cs0", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp19",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "col", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ptp", "evreq", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "ge0", "txerr", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "sata1", "prsnt", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "ua0", "cts", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "ua1", "rxd", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp20",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ge0", "txclk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ptp", "clk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "sata0", "prsnt", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "ua0", "rts", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "ua1", "txd", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp21",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "spi0", "cs1", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge1", "rxd0", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "sata0", "prsnt", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "sd0", "cmd", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "bootcs", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "sata1", "prsnt", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp22",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "spi0", "mosi", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad0", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp23",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "spi0", "sck", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad2", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp24",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "spi0", "miso", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ua0", "cts", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "ua1", "rxd", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "sd0", "d4", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ready", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp25",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "spi0", "cs0", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ua0", "rts", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "ua1", "txd", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "sd0", "d5", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "cs0", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp26",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "spi0", "cs2", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "i2c1", "sck", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "sd0", "d6", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "cs1", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp27",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "spi0", "cs3", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge1", "txclkout", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "i2c1", "sda", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "sd0", "d7", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "cs2", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp28",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge1", "txd0", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "sd0", "clk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad5", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp29",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge1", "txd1", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ale0", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp30",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge1", "txd2", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "oe", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp31",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge1", "txd3", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ale1", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp32",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge1", "txctl", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "we0", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp33",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "dram", "deccerr", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad3", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp34",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad1", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp35",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ref", "clk_out1", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "a1", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp36",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ptp", "trig", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "a0", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp37",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ptp", "clk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge1", "rxclk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "sd0", "d3", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad8", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp38",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ptp", "evreq", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge1", "rxd1", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "ref", "clk_out0", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "sd0", "d0", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad4", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp39",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "i2c1", "sck", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge1", "rxd2", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "ua0", "cts", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "sd0", "d1", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "a2", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp40",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "i2c1", "sda", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge1", "rxd3", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "ua0", "rts", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "sd0", "d2", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad6", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp41",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ua1", "rxd", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge1", "rxctl", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "ua0", "cts", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi1", "cs3", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "burst/last", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "nand", "rb0", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp42",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ua1", "txd", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "ua0", "rts", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "ad7", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp43",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "pcie0", "clkreq", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "dram", "vttctrl", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "dram", "deccerr", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi1", "cs2", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dev", "clkout", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "nand", "rb1", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp44",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "sata0", "prsnt", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "sata1", "prsnt", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "sata2", "prsnt", V_88F6828),
|
||||
MPP_VAR_FUNCTION(4, "sata3", "prsnt", V_88F6828)),
|
||||
MPP_MODE("mpp45",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ref", "clk_out0", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "pcie0", "rstout", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "ua1", "rxd", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp46",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ref", "clk_out1", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "pcie0", "rstout", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "ua1", "txd", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp47",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "sata0", "prsnt", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "sata1", "prsnt", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "sata2", "prsnt", V_88F6828),
|
||||
MPP_VAR_FUNCTION(5, "sata3", "prsnt", V_88F6828)),
|
||||
MPP_MODE("mpp48",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "sata0", "prsnt", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "dram", "vttctrl", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "tdm", "pclk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "audio", "mclk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "sd0", "d4", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "pcie0", "clkreq", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp49",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "sata2", "prsnt", V_88F6828),
|
||||
MPP_VAR_FUNCTION(2, "sata3", "prsnt", V_88F6828),
|
||||
MPP_VAR_FUNCTION(3, "tdm", "fsync", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "audio", "lrclk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "sd0", "d5", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "pcie1", "clkreq", V_88F6820_PLUS)),
|
||||
MPP_MODE("mpp50",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "pcie0", "rstout", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "tdm", "drx", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "audio", "extclk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "sd0", "cmd", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp51",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "tdm", "dtx", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "audio", "sdo", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "dram", "deccerr", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "ptp", "trig", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp52",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "pcie0", "rstout", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "tdm", "int", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "audio", "sdi", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "sd0", "d6", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "ptp", "clk", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp53",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "sata1", "prsnt", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "sata0", "prsnt", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "tdm", "rst", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "audio", "bclk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "sd0", "d7", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "ptp", "evreq", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp54",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "sata0", "prsnt", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "sata1", "prsnt", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "pcie0", "rstout", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "ge0", "txerr", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "sd0", "d3", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp55",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ua1", "cts", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge", "mdio", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "pcie1", "clkreq", V_88F6820_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi1", "cs1", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "sd0", "d0", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "ua1", "rxd", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp56",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "ua1", "rts", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "ge", "mdc", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "dram", "deccerr", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi1", "mosi", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "ua1", "txd", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp57",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi1", "sck", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "sd0", "clk", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "ua1", "txd", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp58",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "pcie1", "clkreq", V_88F6820_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "i2c1", "sck", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(3, "pcie2", "clkreq", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi1", "miso", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "sd0", "d1", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(6, "ua1", "rxd", V_88F6810_PLUS)),
|
||||
MPP_MODE("mpp59",
|
||||
MPP_VAR_FUNCTION(0, "gpio", NULL, V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(1, "pcie0", "rstout", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(2, "i2c1", "sda", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(4, "spi1", "cs0", V_88F6810_PLUS),
|
||||
MPP_VAR_FUNCTION(5, "sd0", "d2", V_88F6810_PLUS)),
|
||||
};
|
||||
|
||||
static const char * const armada_38x_mpp_function_names[] = {
|
||||
"gpio", /* make gpio always as function 0 */
|
||||
|
||||
"audio",
|
||||
"dev",
|
||||
"dram",
|
||||
"ge",
|
||||
"ge0",
|
||||
"ge1",
|
||||
"i2c0",
|
||||
"i2c1",
|
||||
"nand",
|
||||
"pcie0",
|
||||
"pcie1",
|
||||
"pcie2",
|
||||
"pcie3",
|
||||
"ptp",
|
||||
"ref",
|
||||
"sata0",
|
||||
"sata1",
|
||||
"sata2",
|
||||
"sata3",
|
||||
"sd0",
|
||||
"spi0",
|
||||
"spi1",
|
||||
"tdm",
|
||||
"ua0",
|
||||
"ua1",
|
||||
};
|
||||
|
||||
struct armada_38x_pinctrl {
|
||||
void __iomem *base;
|
||||
u8 variant;
|
||||
};
|
||||
|
||||
static int armada_38x_pinctrl_get_pins_count(struct udevice *dev)
|
||||
{
|
||||
return ARRAY_SIZE(armada_38x_mpp_modes);
|
||||
}
|
||||
|
||||
static const char *armada_38x_pinctrl_get_pin_name(struct udevice *dev, unsigned int selector)
|
||||
{
|
||||
return armada_38x_mpp_modes[selector].name;
|
||||
}
|
||||
|
||||
static int armada_38x_pinctrl_get_functions_count(struct udevice *dev)
|
||||
{
|
||||
return ARRAY_SIZE(armada_38x_mpp_function_names);
|
||||
}
|
||||
|
||||
static const char *armada_38x_pinctrl_get_function_name(struct udevice *dev, unsigned int selector)
|
||||
{
|
||||
return armada_38x_mpp_function_names[selector];
|
||||
}
|
||||
|
||||
static int armada_38x_pinctrl_get_pin_muxing(struct udevice *dev, unsigned int selector,
|
||||
char *buf, int size)
|
||||
{
|
||||
struct armada_38x_pinctrl *info = dev_get_priv(dev);
|
||||
unsigned int off = (selector / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
|
||||
unsigned int shift = (selector % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
|
||||
const char *func_name = NULL;
|
||||
const char *sub_name = NULL;
|
||||
unsigned long config;
|
||||
int i;
|
||||
|
||||
config = (readl(info->base + off) >> shift) & MVEBU_MPP_MASK;
|
||||
|
||||
for (i = 0; i < armada_38x_mpp_modes[selector].nsettings; i++) {
|
||||
if (armada_38x_mpp_modes[selector].settings[i].val == config)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < armada_38x_mpp_modes[selector].nsettings) {
|
||||
func_name = armada_38x_mpp_modes[selector].settings[i].name;
|
||||
sub_name = armada_38x_mpp_modes[selector].settings[i].subname;
|
||||
}
|
||||
|
||||
snprintf(buf, size, "%s%s%s",
|
||||
func_name ? func_name : "unknown",
|
||||
sub_name ? "_" : "",
|
||||
sub_name ? sub_name : "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int armada_38x_pinctrl_pinmux_set(struct udevice *dev, unsigned int pin_selector,
|
||||
unsigned int func_selector)
|
||||
{
|
||||
struct armada_38x_pinctrl *info = dev_get_priv(dev);
|
||||
unsigned int off = (pin_selector / MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
|
||||
unsigned int shift = (pin_selector % MVEBU_MPPS_PER_REG) * MVEBU_MPP_BITS;
|
||||
const char *func_name = armada_38x_mpp_function_names[func_selector];
|
||||
unsigned long config, reg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < armada_38x_mpp_modes[pin_selector].nsettings; i++) {
|
||||
if (strcmp(armada_38x_mpp_modes[pin_selector].settings[i].name, func_name) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= armada_38x_mpp_modes[pin_selector].nsettings)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(info->variant & armada_38x_mpp_modes[pin_selector].settings[i].variant))
|
||||
return -EINVAL;
|
||||
|
||||
reg = readl(info->base + off) & ~(MVEBU_MPP_MASK << shift);
|
||||
config = armada_38x_mpp_modes[pin_selector].settings[i].val;
|
||||
writel(reg | (config << shift), info->base + off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int armada_38x_pinctrl_gpio_request_enable(struct udevice *dev, unsigned int selector)
|
||||
{
|
||||
char buf[20];
|
||||
|
||||
armada_38x_pinctrl_get_pin_muxing(dev, selector, buf, sizeof(buf));
|
||||
if (strcmp(buf, "gpio") != 0)
|
||||
printf("Warning: Changing mpp%u function from %s to gpio...\n", selector, buf);
|
||||
|
||||
return armada_38x_pinctrl_pinmux_set(dev, selector, 0); /* gpio is always function 0 */
|
||||
}
|
||||
|
||||
static int armada_38x_pinctrl_gpio_disable_free(struct udevice *dev, unsigned int selector)
|
||||
{
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int armada_38x_pinctrl_set_state(struct udevice *dev, struct udevice *config)
|
||||
{
|
||||
return pinctrl_generic_set_state_prefix(dev, config, "marvell,");
|
||||
}
|
||||
|
||||
static int armada_38x_pinctrl_probe(struct udevice *dev)
|
||||
{
|
||||
struct armada_38x_pinctrl *info = dev_get_priv(dev);
|
||||
|
||||
info->variant = (u8)dev_get_driver_data(dev);
|
||||
info->base = dev_read_addr_ptr(dev);
|
||||
|
||||
if (!info->base)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pinctrl_ops armada_37xx_pinctrl_ops = {
|
||||
.get_pins_count = armada_38x_pinctrl_get_pins_count,
|
||||
.get_pin_name = armada_38x_pinctrl_get_pin_name,
|
||||
.get_functions_count = armada_38x_pinctrl_get_functions_count,
|
||||
.get_function_name = armada_38x_pinctrl_get_function_name,
|
||||
.get_pin_muxing = armada_38x_pinctrl_get_pin_muxing,
|
||||
.pinmux_set = armada_38x_pinctrl_pinmux_set,
|
||||
.gpio_request_enable = armada_38x_pinctrl_gpio_request_enable,
|
||||
.gpio_disable_free = armada_38x_pinctrl_gpio_disable_free,
|
||||
.set_state = armada_38x_pinctrl_set_state,
|
||||
};
|
||||
|
||||
static const struct udevice_id armada_38x_pinctrl_of_match[] = {
|
||||
{
|
||||
.compatible = "marvell,mv88f6810-pinctrl",
|
||||
.data = V_88F6810,
|
||||
},
|
||||
{
|
||||
.compatible = "marvell,mv88f6820-pinctrl",
|
||||
.data = V_88F6820,
|
||||
},
|
||||
{
|
||||
.compatible = "marvell,mv88f6828-pinctrl",
|
||||
.data = V_88F6828,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(armada_38x_pinctrl) = {
|
||||
.name = "armada-38x-pinctrl",
|
||||
.id = UCLASS_PINCTRL,
|
||||
.of_match = of_match_ptr(armada_38x_pinctrl_of_match),
|
||||
.probe = armada_38x_pinctrl_probe,
|
||||
.priv_auto = sizeof(struct armada_38x_pinctrl),
|
||||
.ops = &armada_37xx_pinctrl_ops,
|
||||
};
|
@ -52,7 +52,9 @@ void mvebu_pinctl_emmc_set_mux(struct udevice *dev, u32 pin, u32 func)
|
||||
EMMC_PHY_CTRL_SDPHY_EN);
|
||||
}
|
||||
} else if (!fdt_node_check_compatible(blob, node,
|
||||
"marvell,armada-8k-cpm-pinctrl")) {
|
||||
"marvell,armada-8k-cpm-pinctrl") ||
|
||||
!fdt_node_check_compatible(blob, node,
|
||||
"marvell,armada-7k-pinctrl")) {
|
||||
if ((pin == CP110_EMMC_CLK_PIN_ID) &&
|
||||
(func == CP110_EMMC_CLK_FUNC)) {
|
||||
clrbits_le32(priv->base_reg + CP_EMMC_PHY_CTRL_REG,
|
||||
|
@ -234,6 +234,24 @@ enum pinmux_subnode_type {
|
||||
PST_PINMUX,
|
||||
};
|
||||
|
||||
static const char *alloc_name_with_prefix(const char *name, const char *prefix)
|
||||
{
|
||||
if (prefix) {
|
||||
char *name_with_prefix = malloc(strlen(prefix) + sizeof("pins"));
|
||||
if (name_with_prefix)
|
||||
sprintf(name_with_prefix, "%s%s", prefix, name);
|
||||
return name_with_prefix;
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
static void free_name_with_prefix(const char *name_with_prefix, const char *prefix)
|
||||
{
|
||||
if (prefix)
|
||||
free((char *)name_with_prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinctrl_generic_set_state_one() - set state for a certain pin/group
|
||||
* Apply all pin multiplexing and pin configurations specified by @config
|
||||
@ -248,9 +266,11 @@ enum pinmux_subnode_type {
|
||||
*/
|
||||
static int pinctrl_generic_set_state_one(struct udevice *dev,
|
||||
struct udevice *config,
|
||||
const char *prefix,
|
||||
enum pinmux_subnode_type subnode_type,
|
||||
unsigned selector)
|
||||
{
|
||||
const char *function_propname;
|
||||
const char *propname;
|
||||
const void *value;
|
||||
struct ofprop property;
|
||||
@ -259,18 +279,26 @@ static int pinctrl_generic_set_state_one(struct udevice *dev,
|
||||
|
||||
assert(subnode_type != PST_NONE);
|
||||
|
||||
function_propname = alloc_name_with_prefix("function", prefix);
|
||||
if (!function_propname)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_for_each_property(property, config) {
|
||||
value = dev_read_prop_by_prop(&property, &propname, &len);
|
||||
if (!value)
|
||||
if (!value) {
|
||||
free_name_with_prefix(function_propname, prefix);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* pinmux subnodes already have their muxing set */
|
||||
if (subnode_type != PST_PINMUX &&
|
||||
!strcmp(propname, "function")) {
|
||||
!strcmp(propname, function_propname)) {
|
||||
func_selector = pinmux_func_name_to_selector(dev,
|
||||
value);
|
||||
if (func_selector < 0)
|
||||
if (func_selector < 0) {
|
||||
free_name_with_prefix(function_propname, prefix);
|
||||
return func_selector;
|
||||
}
|
||||
ret = pinmux_enable_setting(dev,
|
||||
subnode_type == PST_GROUP,
|
||||
selector,
|
||||
@ -291,10 +319,13 @@ static int pinctrl_generic_set_state_one(struct udevice *dev,
|
||||
selector, param, arg);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
if (ret) {
|
||||
free_name_with_prefix(function_propname, prefix);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
free_name_with_prefix(function_propname, prefix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -309,20 +340,34 @@ static int pinctrl_generic_set_state_one(struct udevice *dev,
|
||||
*/
|
||||
static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice *dev,
|
||||
struct udevice *config,
|
||||
const char *prefix,
|
||||
int *count)
|
||||
{
|
||||
const struct pinctrl_ops *ops = pinctrl_get_ops(dev);
|
||||
const char *propname;
|
||||
|
||||
*count = dev_read_string_count(config, "pins");
|
||||
propname = alloc_name_with_prefix("pins", prefix);
|
||||
if (!propname)
|
||||
return -ENOMEM;
|
||||
*count = dev_read_string_count(config, propname);
|
||||
free_name_with_prefix(propname, prefix);
|
||||
if (*count >= 0)
|
||||
return PST_PIN;
|
||||
|
||||
*count = dev_read_string_count(config, "groups");
|
||||
propname = alloc_name_with_prefix("groups", prefix);
|
||||
if (!propname)
|
||||
return -ENOMEM;
|
||||
*count = dev_read_string_count(config, propname);
|
||||
free_name_with_prefix(propname, prefix);
|
||||
if (*count >= 0)
|
||||
return PST_GROUP;
|
||||
|
||||
if (ops->pinmux_property_set) {
|
||||
*count = dev_read_size(config, "pinmux");
|
||||
propname = alloc_name_with_prefix("pinmux", prefix);
|
||||
if (!propname)
|
||||
return -ENOMEM;
|
||||
*count = dev_read_size(config, propname);
|
||||
free_name_with_prefix(propname, prefix);
|
||||
if (*count >= 0 && !(*count % sizeof(u32))) {
|
||||
*count /= sizeof(u32);
|
||||
return PST_PINMUX;
|
||||
@ -338,23 +383,30 @@ static enum pinmux_subnode_type pinctrl_generic_get_subnode_type(struct udevice
|
||||
*
|
||||
* @dev: pin controller device
|
||||
* @config: pseudo device pointing to config node
|
||||
* @prefix: device tree property prefix (e.g. vendor specific)
|
||||
* @return: 0 on success, or negative error code on failure
|
||||
*/
|
||||
static int pinctrl_generic_set_state_subnode(struct udevice *dev,
|
||||
struct udevice *config)
|
||||
struct udevice *config,
|
||||
const char *prefix)
|
||||
{
|
||||
enum pinmux_subnode_type subnode_type;
|
||||
const char *propname;
|
||||
const char *name;
|
||||
int count, selector, i, ret, scratch;
|
||||
const u32 *pinmux_groups = NULL; /* prevent use-uninitialized warning */
|
||||
|
||||
subnode_type = pinctrl_generic_get_subnode_type(dev, config, &count);
|
||||
subnode_type = pinctrl_generic_get_subnode_type(dev, config, prefix, &count);
|
||||
|
||||
debug("%s(%s, %s): count=%d\n", __func__, dev->name, config->name,
|
||||
count);
|
||||
|
||||
if (subnode_type == PST_PINMUX) {
|
||||
pinmux_groups = dev_read_prop(config, "pinmux", &scratch);
|
||||
propname = alloc_name_with_prefix("pinmux", prefix);
|
||||
if (!propname)
|
||||
return -ENOMEM;
|
||||
pinmux_groups = dev_read_prop(config, propname, &scratch);
|
||||
free_name_with_prefix(propname, prefix);
|
||||
if (!pinmux_groups)
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -362,13 +414,21 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
|
||||
for (i = 0; i < count; i++) {
|
||||
switch (subnode_type) {
|
||||
case PST_PIN:
|
||||
ret = dev_read_string_index(config, "pins", i, &name);
|
||||
propname = alloc_name_with_prefix("pins", prefix);
|
||||
if (!propname)
|
||||
return -ENOMEM;
|
||||
ret = dev_read_string_index(config, propname, i, &name);
|
||||
free_name_with_prefix(propname, prefix);
|
||||
if (ret)
|
||||
return ret;
|
||||
selector = pinctrl_pin_name_to_selector(dev, name);
|
||||
break;
|
||||
case PST_GROUP:
|
||||
ret = dev_read_string_index(config, "groups", i, &name);
|
||||
propname = alloc_name_with_prefix("groups", prefix);
|
||||
if (!propname)
|
||||
return -ENOMEM;
|
||||
ret = dev_read_string_index(config, propname, i, &name);
|
||||
free_name_with_prefix(propname, prefix);
|
||||
if (ret)
|
||||
return ret;
|
||||
selector = pinctrl_group_name_to_selector(dev, name);
|
||||
@ -390,8 +450,29 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
|
||||
if (selector < 0)
|
||||
return selector;
|
||||
|
||||
ret = pinctrl_generic_set_state_one(dev, config, subnode_type,
|
||||
selector);
|
||||
ret = pinctrl_generic_set_state_one(dev, config, prefix,
|
||||
subnode_type, selector);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pinctrl_generic_set_state_prefix(struct udevice *dev, struct udevice *config,
|
||||
const char *prefix)
|
||||
{
|
||||
struct udevice *child;
|
||||
int ret;
|
||||
|
||||
ret = pinctrl_generic_set_state_subnode(dev, config, prefix);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (device_find_first_child(config, &child);
|
||||
child;
|
||||
device_find_next_child(&child)) {
|
||||
ret = pinctrl_generic_set_state_subnode(dev, child, prefix);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@ -401,20 +482,5 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
|
||||
|
||||
int pinctrl_generic_set_state(struct udevice *dev, struct udevice *config)
|
||||
{
|
||||
struct udevice *child;
|
||||
int ret;
|
||||
|
||||
ret = pinctrl_generic_set_state_subnode(dev, config);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (device_find_first_child(config, &child);
|
||||
child;
|
||||
device_find_next_child(&child)) {
|
||||
ret = pinctrl_generic_set_state_subnode(dev, child);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return pinctrl_generic_set_state_prefix(dev, config, NULL);
|
||||
}
|
||||
|
@ -222,9 +222,10 @@ pinctrl_gpio_get_pinctrl_and_offset(struct udevice *dev, unsigned offset,
|
||||
*
|
||||
* @dev: GPIO peripheral device
|
||||
* @offset: the GPIO pin offset from the GPIO controller
|
||||
* @label: the GPIO pin label
|
||||
* @return: 0 on success, or negative error code on failure
|
||||
*/
|
||||
int pinctrl_gpio_request(struct udevice *dev, unsigned offset)
|
||||
int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label)
|
||||
{
|
||||
const struct pinctrl_ops *ops;
|
||||
struct udevice *pctldev;
|
||||
|
@ -491,6 +491,8 @@ enum pin_config_param {
|
||||
* Return: 0 on success, or negative error code on failure
|
||||
*/
|
||||
int pinctrl_generic_set_state(struct udevice *pctldev, struct udevice *config);
|
||||
int pinctrl_generic_set_state_prefix(struct udevice *pctldev, struct udevice *config,
|
||||
const char *prefix);
|
||||
#else
|
||||
static inline int pinctrl_generic_set_state(struct udevice *pctldev,
|
||||
struct udevice *config)
|
||||
@ -609,10 +611,11 @@ int pinctrl_get_pin_name(struct udevice *dev, int selector, char *buf,
|
||||
* pinctrl_gpio_request() - Request a single pin to be used as GPIO
|
||||
* @dev: GPIO peripheral device
|
||||
* @offset: GPIO pin offset from the GPIO controller
|
||||
* @label: GPIO label
|
||||
*
|
||||
* Return: 0 on success, or negative error code on failure
|
||||
*/
|
||||
int pinctrl_gpio_request(struct udevice *dev, unsigned offset);
|
||||
int pinctrl_gpio_request(struct udevice *dev, unsigned offset, const char *label);
|
||||
|
||||
/**
|
||||
* pinctrl_gpio_free() - Free a single pin used as GPIO
|
||||
|
Loading…
Reference in New Issue
Block a user