test: pinmux: Add test for pin muxing
This extends the pinctrl-sandbox driver to support pin muxing, and adds a test for that behaviour. The test is done in C and not python (like the existing tests for the pinctrl uclass) because it needs to call pinctrl_select_state. Another option could be to add a command that invokes pinctrl_select_state and then test everything in test/py/tests/test_pinmux.py. The pinctrl-sandbox driver now mimics the way that many pinmux devices work. There are two groups of pins which are muxed together, as well as four pins which are muxed individually. I have tried to test all normal paths. However, very few error cases are explicitly checked for. Signed-off-by: Sean Anderson <seanga2@gmail.com> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
5eee93e5b1
commit
7f0f1806e3
@ -960,6 +960,7 @@ M: Simon Glass <sjg@chromium.org>
|
||||
S: Maintained
|
||||
F: arch/sandbox/
|
||||
F: doc/arch/sandbox.rst
|
||||
F: include/dt-bindings/*/sandbox*.h
|
||||
|
||||
SH
|
||||
M: Marek Vasut <marek.vasut+renesas@gmail.com>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/gpio/sandbox-gpio.h>
|
||||
#include <dt-bindings/pinctrl/sandbox-pinmux.h>
|
||||
|
||||
/ {
|
||||
model = "sandbox";
|
||||
@ -1094,30 +1095,60 @@
|
||||
pinctrl {
|
||||
compatible = "sandbox,pinctrl";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&gpios>;
|
||||
pinctrl-names = "default", "alternate";
|
||||
pinctrl-0 = <&pinctrl_gpios>, <&pinctrl_i2s>;
|
||||
pinctrl-1 = <&pinctrl_spi>, <&pinctrl_i2c>;
|
||||
|
||||
gpios: gpios {
|
||||
pinctrl_gpios: gpios {
|
||||
gpio0 {
|
||||
pins = "GPIO0";
|
||||
pins = "P5";
|
||||
function = "GPIO";
|
||||
bias-pull-up;
|
||||
input-disable;
|
||||
};
|
||||
gpio1 {
|
||||
pins = "GPIO1";
|
||||
pins = "P6";
|
||||
function = "GPIO";
|
||||
output-high;
|
||||
drive-open-drain;
|
||||
};
|
||||
gpio2 {
|
||||
pins = "GPIO2";
|
||||
pinmux = <SANDBOX_PINMUX(7, SANDBOX_PINMUX_GPIO)>;
|
||||
bias-pull-down;
|
||||
input-enable;
|
||||
};
|
||||
gpio3 {
|
||||
pins = "GPIO3";
|
||||
pinmux = <SANDBOX_PINMUX(8, SANDBOX_PINMUX_GPIO)>;
|
||||
bias-disable;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_i2c: i2c {
|
||||
groups {
|
||||
groups = "I2C_UART";
|
||||
function = "I2C";
|
||||
};
|
||||
|
||||
pins {
|
||||
pins = "P0", "P1";
|
||||
drive-open-drain;
|
||||
};
|
||||
};
|
||||
|
||||
pinctrl_i2s: i2s {
|
||||
groups = "SPI_I2S";
|
||||
function = "I2S";
|
||||
};
|
||||
|
||||
pinctrl_spi: spi {
|
||||
groups = "SPI_I2S";
|
||||
function = "SPI";
|
||||
|
||||
cs {
|
||||
pinmux = <SANDBOX_PINMUX(5, SANDBOX_PINMUX_CS)>,
|
||||
<SANDBOX_PINMUX(6, SANDBOX_PINMUX_CS)>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hwspinlock@0 {
|
||||
|
@ -1,57 +1,70 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
|
||||
* Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
|
||||
* Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
|
||||
*/
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <log.h>
|
||||
#include <dm/pinctrl.h>
|
||||
#include <dt-bindings/pinctrl/sandbox-pinmux.h>
|
||||
#include <log.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
/*
|
||||
* This driver emulates a pin controller with the following rules:
|
||||
* - The pinctrl config for each pin must be set individually
|
||||
* - The first three pins (P0-P2) must be muxed as a group
|
||||
* - The next two pins (P3-P4) must be muxed as a group
|
||||
* - The last four pins (P5-P8) must be muxed individually
|
||||
*/
|
||||
|
||||
static const char * const sandbox_pins[] = {
|
||||
"SCL",
|
||||
"SDA",
|
||||
"TX",
|
||||
"RX",
|
||||
"W1",
|
||||
"GPIO0",
|
||||
"GPIO1",
|
||||
"GPIO2",
|
||||
"GPIO3",
|
||||
#define PIN(x) \
|
||||
[x] = "P" #x
|
||||
PIN(0),
|
||||
PIN(1),
|
||||
PIN(2),
|
||||
PIN(3),
|
||||
PIN(4),
|
||||
PIN(5),
|
||||
PIN(6),
|
||||
PIN(7),
|
||||
PIN(8),
|
||||
#undef PIN
|
||||
};
|
||||
|
||||
static const char * const sandbox_pins_muxing[] = {
|
||||
"I2C SCL",
|
||||
"I2C SDA",
|
||||
"Uart TX",
|
||||
"Uart RX",
|
||||
"1-wire gpio",
|
||||
"gpio",
|
||||
"gpio",
|
||||
"gpio",
|
||||
"gpio",
|
||||
static const char * const sandbox_pins_muxing[][2] = {
|
||||
{ "UART TX", "I2C SCL" },
|
||||
{ "UART RX", "I2C SDA" },
|
||||
{ "SPI SCLK", "I2S SCK" },
|
||||
{ "SPI MOSI", "I2S SD" },
|
||||
{ "SPI MISO", "I2S WS" },
|
||||
{ "GPIO0", "SPI CS0" },
|
||||
{ "GPIO1", "SPI CS1" },
|
||||
{ "GPIO2", "PWM0" },
|
||||
{ "GPIO3", "PWM1" },
|
||||
};
|
||||
|
||||
#define SANDBOX_GROUP_I2C_UART 0
|
||||
#define SANDBOX_GROUP_SPI_I2S 1
|
||||
|
||||
static const char * const sandbox_groups[] = {
|
||||
"i2c",
|
||||
"serial_a",
|
||||
"serial_b",
|
||||
"spi",
|
||||
"w1",
|
||||
[SANDBOX_GROUP_I2C_UART] = "I2C_UART",
|
||||
[SANDBOX_GROUP_SPI_I2S] = "SPI_I2S",
|
||||
};
|
||||
|
||||
static const char * const sandbox_functions[] = {
|
||||
"i2c",
|
||||
"serial",
|
||||
"spi",
|
||||
"w1",
|
||||
"gpio",
|
||||
"gpio",
|
||||
"gpio",
|
||||
"gpio",
|
||||
#define FUNC(id) \
|
||||
[SANDBOX_PINMUX_##id] = #id
|
||||
FUNC(UART),
|
||||
FUNC(I2C),
|
||||
FUNC(SPI),
|
||||
FUNC(I2S),
|
||||
FUNC(GPIO),
|
||||
FUNC(CS),
|
||||
FUNC(PWM),
|
||||
#undef FUNC
|
||||
};
|
||||
|
||||
static const struct pinconf_param sandbox_conf_params[] = {
|
||||
@ -68,9 +81,12 @@ static const struct pinconf_param sandbox_conf_params[] = {
|
||||
{ "input-disable", PIN_CONFIG_INPUT_ENABLE, 0 },
|
||||
};
|
||||
|
||||
/* bitfield used to save param and value of each pin/selector */
|
||||
static unsigned int sandbox_pins_param[ARRAY_SIZE(sandbox_pins)];
|
||||
static unsigned int sandbox_pins_value[ARRAY_SIZE(sandbox_pins)];
|
||||
/* Bitfield used to save param and value of each pin/selector */
|
||||
struct sandbox_pinctrl_priv {
|
||||
unsigned int mux;
|
||||
unsigned int pins_param[ARRAY_SIZE(sandbox_pins)];
|
||||
unsigned int pins_value[ARRAY_SIZE(sandbox_pins)];
|
||||
};
|
||||
|
||||
static int sandbox_get_pins_count(struct udevice *dev)
|
||||
{
|
||||
@ -87,16 +103,18 @@ static int sandbox_get_pin_muxing(struct udevice *dev,
|
||||
char *buf, int size)
|
||||
{
|
||||
const struct pinconf_param *p;
|
||||
struct sandbox_pinctrl_priv *priv = dev_get_priv(dev);
|
||||
int i;
|
||||
|
||||
snprintf(buf, size, "%s", sandbox_pins_muxing[selector]);
|
||||
snprintf(buf, size, "%s",
|
||||
sandbox_pins_muxing[selector][!!(priv->mux & BIT(selector))]);
|
||||
|
||||
if (sandbox_pins_param[selector]) {
|
||||
if (priv->pins_param[selector]) {
|
||||
for (i = 0, p = sandbox_conf_params;
|
||||
i < ARRAY_SIZE(sandbox_conf_params);
|
||||
i++, p++) {
|
||||
if ((sandbox_pins_param[selector] & BIT(p->param)) &&
|
||||
(!!(sandbox_pins_value[selector] & BIT(p->param)) ==
|
||||
if ((priv->pins_param[selector] & BIT(p->param)) &&
|
||||
(!!(priv->pins_value[selector] & BIT(p->param)) ==
|
||||
p->default_value)) {
|
||||
strncat(buf, " ", size);
|
||||
strncat(buf, p->property, size);
|
||||
@ -133,12 +151,32 @@ static const char *sandbox_get_function_name(struct udevice *dev,
|
||||
static int sandbox_pinmux_set(struct udevice *dev, unsigned pin_selector,
|
||||
unsigned func_selector)
|
||||
{
|
||||
int mux;
|
||||
struct sandbox_pinctrl_priv *priv = dev_get_priv(dev);
|
||||
|
||||
debug("sandbox pinmux: pin = %d (%s), function = %d (%s)\n",
|
||||
pin_selector, sandbox_get_pin_name(dev, pin_selector),
|
||||
func_selector, sandbox_get_function_name(dev, func_selector));
|
||||
|
||||
sandbox_pins_param[pin_selector] = 0;
|
||||
sandbox_pins_value[pin_selector] = 0;
|
||||
if (pin_selector < 5)
|
||||
return -EINVAL;
|
||||
|
||||
switch (func_selector) {
|
||||
case SANDBOX_PINMUX_GPIO:
|
||||
mux = 0;
|
||||
break;
|
||||
case SANDBOX_PINMUX_CS:
|
||||
case SANDBOX_PINMUX_PWM:
|
||||
mux = BIT(pin_selector);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->mux &= ~BIT(pin_selector);
|
||||
priv->mux |= mux;
|
||||
priv->pins_param[pin_selector] = 0;
|
||||
priv->pins_value[pin_selector] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -147,25 +185,75 @@ static int sandbox_pinmux_group_set(struct udevice *dev,
|
||||
unsigned group_selector,
|
||||
unsigned func_selector)
|
||||
{
|
||||
bool mux;
|
||||
int i, group_start, group_end;
|
||||
struct sandbox_pinctrl_priv *priv = dev_get_priv(dev);
|
||||
unsigned int mask;
|
||||
|
||||
debug("sandbox pinmux: group = %d (%s), function = %d (%s)\n",
|
||||
group_selector, sandbox_get_group_name(dev, group_selector),
|
||||
func_selector, sandbox_get_function_name(dev, func_selector));
|
||||
|
||||
if (group_selector == SANDBOX_GROUP_I2C_UART) {
|
||||
group_start = 0;
|
||||
group_end = 1;
|
||||
|
||||
if (func_selector == SANDBOX_PINMUX_UART)
|
||||
mux = false;
|
||||
else if (func_selector == SANDBOX_PINMUX_I2C)
|
||||
mux = true;
|
||||
else
|
||||
return -EINVAL;
|
||||
} else if (group_selector == SANDBOX_GROUP_SPI_I2S) {
|
||||
group_start = 2;
|
||||
group_end = 4;
|
||||
|
||||
if (func_selector == SANDBOX_PINMUX_SPI)
|
||||
mux = false;
|
||||
else if (func_selector == SANDBOX_PINMUX_I2S)
|
||||
mux = true;
|
||||
else
|
||||
return -EINVAL;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mask = GENMASK(group_end, group_start);
|
||||
priv->mux &= ~mask;
|
||||
priv->mux |= mux ? mask : 0;
|
||||
|
||||
for (i = group_start; i < group_end; i++) {
|
||||
priv->pins_param[i] = 0;
|
||||
priv->pins_value[i] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sandbox_pinmux_property_set(struct udevice *dev, u32 pinmux_group)
|
||||
{
|
||||
int ret;
|
||||
unsigned pin_selector = pinmux_group & 0xFFFF;
|
||||
unsigned func_selector = pinmux_group >> 16;
|
||||
|
||||
ret = sandbox_pinmux_set(dev, pin_selector, func_selector);
|
||||
return ret ? ret : pin_selector;
|
||||
}
|
||||
|
||||
static int sandbox_pinconf_set(struct udevice *dev, unsigned pin_selector,
|
||||
unsigned param, unsigned argument)
|
||||
{
|
||||
struct sandbox_pinctrl_priv *priv = dev_get_priv(dev);
|
||||
|
||||
debug("sandbox pinconf: pin = %d (%s), param = %d, arg = %d\n",
|
||||
pin_selector, sandbox_get_pin_name(dev, pin_selector),
|
||||
param, argument);
|
||||
|
||||
sandbox_pins_param[pin_selector] |= BIT(param);
|
||||
priv->pins_param[pin_selector] |= BIT(param);
|
||||
if (argument)
|
||||
sandbox_pins_value[pin_selector] |= BIT(param);
|
||||
priv->pins_value[pin_selector] |= BIT(param);
|
||||
else
|
||||
sandbox_pins_value[pin_selector] &= ~BIT(param);
|
||||
priv->pins_value[pin_selector] &= ~BIT(param);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -191,6 +279,7 @@ const struct pinctrl_ops sandbox_pinctrl_ops = {
|
||||
.get_function_name = sandbox_get_function_name,
|
||||
.pinmux_set = sandbox_pinmux_set,
|
||||
.pinmux_group_set = sandbox_pinmux_group_set,
|
||||
.pinmux_property_set = sandbox_pinmux_property_set,
|
||||
.pinconf_num_params = ARRAY_SIZE(sandbox_conf_params),
|
||||
.pinconf_params = sandbox_conf_params,
|
||||
.pinconf_set = sandbox_pinconf_set,
|
||||
@ -207,5 +296,6 @@ U_BOOT_DRIVER(sandbox_pinctrl) = {
|
||||
.name = "sandbox_pinctrl",
|
||||
.id = UCLASS_PINCTRL,
|
||||
.of_match = sandbox_pinctrl_match,
|
||||
.priv_auto_alloc_size = sizeof(struct sandbox_pinctrl_priv),
|
||||
.ops = &sandbox_pinctrl_ops,
|
||||
};
|
||||
|
19
include/dt-bindings/pinctrl/sandbox-pinmux.h
Normal file
19
include/dt-bindings/pinctrl/sandbox-pinmux.h
Normal file
@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef SANDBOX_PINMUX_H
|
||||
#define SANDBOX_PINMUX_H
|
||||
|
||||
#define SANDBOX_PINMUX_UART 0
|
||||
#define SANDBOX_PINMUX_I2C 1
|
||||
#define SANDBOX_PINMUX_SPI 2
|
||||
#define SANDBOX_PINMUX_I2S 3
|
||||
#define SANDBOX_PINMUX_GPIO 4
|
||||
#define SANDBOX_PINMUX_CS 5
|
||||
#define SANDBOX_PINMUX_PWM 6
|
||||
|
||||
#define SANDBOX_PINMUX(pin, func) ((func) << 16 | (pin))
|
||||
|
||||
#endif /* SANDBOX_PINMUX_H */
|
@ -81,4 +81,7 @@ obj-$(CONFIG_CLK_K210_SET_RATE) += k210_pll.o
|
||||
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
|
||||
obj-$(CONFIG_RESET_SYSCON) += syscon-reset.o
|
||||
obj-$(CONFIG_SCMI_FIRMWARE) += scmi.o
|
||||
ifneq ($(CONFIG_PINMUX),)
|
||||
obj-$(CONFIG_PINCONF) += pinmux.o
|
||||
endif
|
||||
endif
|
||||
|
57
test/dm/pinmux.c
Normal file
57
test/dm/pinmux.c
Normal file
@ -0,0 +1,57 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/pinctrl.h>
|
||||
#include <dm/test.h>
|
||||
#include <test/ut.h>
|
||||
|
||||
static int dm_test_pinmux(struct unit_test_state *uts)
|
||||
{
|
||||
char buf[64];
|
||||
struct udevice *dev;
|
||||
|
||||
#define test_muxing(selector, expected) do { \
|
||||
ut_assertok(pinctrl_get_pin_muxing(dev, selector, buf, sizeof(buf))); \
|
||||
ut_asserteq_str(expected, (char *)&buf); \
|
||||
} while (0)
|
||||
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_PINCTRL, "pinctrl", &dev));
|
||||
test_muxing(0, "UART TX.");
|
||||
test_muxing(1, "UART RX.");
|
||||
test_muxing(2, "I2S SCK.");
|
||||
test_muxing(3, "I2S SD.");
|
||||
test_muxing(4, "I2S WS.");
|
||||
test_muxing(5, "GPIO0 bias-pull-up input-disable.");
|
||||
test_muxing(6, "GPIO1 drive-open-drain.");
|
||||
test_muxing(7, "GPIO2 bias-pull-down input-enable.");
|
||||
test_muxing(8, "GPIO3 bias-disable.");
|
||||
|
||||
ut_assertok(pinctrl_select_state(dev, "alternate"));
|
||||
test_muxing(0, "I2C SCL drive-open-drain.");
|
||||
test_muxing(1, "I2C SDA drive-open-drain.");
|
||||
test_muxing(2, "SPI SCLK.");
|
||||
test_muxing(3, "SPI MOSI.");
|
||||
test_muxing(4, "SPI MISO.");
|
||||
test_muxing(5, "SPI CS0.");
|
||||
test_muxing(6, "SPI CS1.");
|
||||
test_muxing(7, "GPIO2 bias-pull-down input-enable.");
|
||||
test_muxing(8, "GPIO3 bias-disable.");
|
||||
|
||||
ut_assertok(pinctrl_select_state(dev, "0"));
|
||||
test_muxing(0, "I2C SCL drive-open-drain.");
|
||||
test_muxing(1, "I2C SDA drive-open-drain.");
|
||||
test_muxing(2, "I2S SCK.");
|
||||
test_muxing(3, "I2S SD.");
|
||||
test_muxing(4, "I2S WS.");
|
||||
test_muxing(5, "GPIO0 bias-pull-up input-disable.");
|
||||
test_muxing(6, "GPIO1 drive-open-drain.");
|
||||
test_muxing(7, "GPIO2 bias-pull-down input-enable.");
|
||||
test_muxing(8, "GPIO3 bias-disable.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_pinmux, UT_TESTF_SCAN_FDT);
|
@ -28,15 +28,15 @@ def test_pinmux_status_all(u_boot_console):
|
||||
assert ('a6 : gpio output .' in output)
|
||||
|
||||
assert ('pinctrl:' in output)
|
||||
assert ('SCL : I2C SCL.' in output)
|
||||
assert ('SDA : I2C SDA.' in output)
|
||||
assert ('TX : Uart TX.' in output)
|
||||
assert ('RX : Uart RX.' in output)
|
||||
assert ('W1 : 1-wire gpio.' in output)
|
||||
assert ('GPIO0 : gpio bias-pull-up input-disable.' in output)
|
||||
assert ('GPIO1 : gpio drive-open-drain.' in output)
|
||||
assert ('GPIO2 : gpio bias-pull-down input-enable.' in output)
|
||||
assert ('GPIO3 : gpio bias-disable.' in output)
|
||||
assert ('P0 : UART TX.' in output)
|
||||
assert ('P1 : UART RX.' in output)
|
||||
assert ('P2 : I2S SCK.' in output)
|
||||
assert ('P3 : I2S SD.' in output)
|
||||
assert ('P4 : I2S WS.' in output)
|
||||
assert ('P5 : GPIO0 bias-pull-up input-disable.' in output)
|
||||
assert ('P6 : GPIO1 drive-open-drain.' in output)
|
||||
assert ('P7 : GPIO2 bias-pull-down input-enable.' in output)
|
||||
assert ('P8 : GPIO3 bias-disable.' in output)
|
||||
|
||||
@pytest.mark.buildconfigspec('cmd_pinmux')
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@ -73,12 +73,12 @@ def test_pinmux_status(u_boot_console):
|
||||
assert (not 'pinctrl-gpio:' in output)
|
||||
assert (not 'pinctrl:' in output)
|
||||
|
||||
assert ('SCL : I2C SCL.' in output)
|
||||
assert ('SDA : I2C SDA.' in output)
|
||||
assert ('TX : Uart TX.' in output)
|
||||
assert ('RX : Uart RX.' in output)
|
||||
assert ('W1 : 1-wire gpio.' in output)
|
||||
assert ('GPIO0 : gpio bias-pull-up input-disable.' in output)
|
||||
assert ('GPIO1 : gpio drive-open-drain.' in output)
|
||||
assert ('GPIO2 : gpio bias-pull-down input-enable.' in output)
|
||||
assert ('GPIO3 : gpio bias-disable.' in output)
|
||||
assert ('P0 : UART TX.' in output)
|
||||
assert ('P1 : UART RX.' in output)
|
||||
assert ('P2 : I2S SCK.' in output)
|
||||
assert ('P3 : I2S SD.' in output)
|
||||
assert ('P4 : I2S WS.' in output)
|
||||
assert ('P5 : GPIO0 bias-pull-up input-disable.' in output)
|
||||
assert ('P6 : GPIO1 drive-open-drain.' in output)
|
||||
assert ('P7 : GPIO2 bias-pull-down input-enable.' in output)
|
||||
assert ('P8 : GPIO3 bias-disable.' in output)
|
||||
|
Loading…
Reference in New Issue
Block a user