mvebu: pinctrl: Add Armada 38x driver

This new Armada 38x driver is based on Linux kernel driver. It can set any
pin to any valid function specified in DT like Linux kernel, it provides
support for 'pinmux status -a' command and also for pinctrl_gpio_request().

Signed-off-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Stefan Roese <sr@denx.de>
This commit is contained in:
Pali Rohár 2022-07-25 13:56:09 +02:00 committed by Stefan Roese
parent 92c4a95ec7
commit 35c50a709e
3 changed files with 597 additions and 0 deletions

View file

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

View file

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

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