blob: 8e72463316d3df0c7ea33ce91938004864e02c28 [file] [log] [blame]
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright 2021 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <zephyr.h>
#include <device.h>
#include <devicetree.h>
#include <drivers/gpio.h>
#include <shell/shell.h>
#include <sys/__assert.h>
#include <sys/printk.h>
#include "io.h"
struct gpio_info {
const char *const label;
const char *const dev_name;
const struct device *dev;
gpio_pin_t pin;
int flags;
};
#define GPIO(group, name) \
[name] = { DT_LABEL(DT_PATH(group, name)), \
DT_GPIO_LABEL(DT_PATH(group, name), gpios), NULL, \
DT_GPIO_PIN(DT_PATH(group, name), gpios), \
DT_GPIO_FLAGS(DT_PATH(group, name), gpios) }
static struct gpio_info gpios[] = {
GPIO(leds, power_good_led),
GPIO(sd_mux, sd_mux_sel),
GPIO(sd_mux, sd_mux_en_l),
GPIO(sd_mux, usd_pwr_sel),
GPIO(sd_mux, usd_pwr_en),
GPIO(sd_mux, usd_cd_det),
GPIO(sysmon, sysmon_sel),
GPIO(fpga, pwr_en),
GPIO(fpga, pwr_good),
GPIO(fpga, boot_mode1),
GPIO(fpga, boot_mode0),
GPIO(fpga, por_l_load_l),
GPIO(fpga, fpga_done),
GPIO(misc, tp126),
GPIO(misc, tp125),
GPIO(misc, board_version_2),
GPIO(misc, board_version_1),
GPIO(misc, board_version_0),
GPIO(i2c_switch, exp_reset),
GPIO(i2c_switch, exp_irq),
GPIO(videomux, gp213_it68051p1_ch_sel),
GPIO(videomux, dp1_ps8468_sw),
GPIO(videomux, hdmi1_gp213_ch_sel),
GPIO(videomux, somp1_mode_sel),
GPIO(videomux, gp213_it68051p0_ch_sel),
GPIO(videomux, dp2_ps8468_sw),
GPIO(videomux, hdmi2_gp213_ch_sel),
GPIO(videomux, somp2_mode_sel),
GPIO(videomux, dp1_ps8468_rst_l),
GPIO(videomux, dp2_ps8468_rst_l),
GPIO(videomux, dp1_hdmi_rst_l),
GPIO(videomux, dp2_hdmi_rst_l),
GPIO(it68051, it68051p0_pwr_det),
GPIO(it68051, it68051p1_pwr_det),
GPIO(it68051, it68051_rst_l),
GPIO(it68051, it68051p0_ddc_bp_l),
GPIO(it68051, it68051p1_ddc_bp_l),
GPIO(it68051, gp213_it68051p1_hpd),
GPIO(dp_cfg, dp1_ps8468_mode),
GPIO(dp_cfg, dp1_ps8468_cfg0),
GPIO(dp_cfg, dp1_ps8468_cfg1),
GPIO(dp_cfg, dp1_ps8468_cfg2),
GPIO(dp_cfg, dp1_ps8468_cfg3),
GPIO(dp_cfg, dp1_ps8468_cfg4),
GPIO(dp_cfg, dp1_ps8468_eq0),
GPIO(dp_cfg, dp1_ps8468_eq1),
GPIO(dp_cfg, dp2_ps8468_mode),
GPIO(dp_cfg, dp2_ps8468_cfg0),
GPIO(dp_cfg, dp2_ps8468_cfg1),
GPIO(dp_cfg, dp2_ps8468_cfg2),
GPIO(dp_cfg, dp2_ps8468_cfg3),
GPIO(dp_cfg, dp2_ps8468_cfg4),
GPIO(dp_cfg, dp2_ps8468_eq0),
GPIO(dp_cfg, dp2_ps8468_eq1),
};
static int io_init_devices(const struct device *ptr)
{
ARG_UNUSED(ptr);
for (int idx = 0; idx < ARRAY_SIZE(gpios); ++idx) {
gpios[idx].dev = device_get_binding(gpios[idx].dev_name);
if (!gpios[idx].dev) {
printk("io_init_devices: "
"device_get_binding(%s) failed!\n",
gpios[idx].dev_name);
continue;
}
int ret = gpio_pin_configure(gpios[idx].dev, gpios[idx].pin,
gpios[idx].flags);
if (ret != 0) {
printk("io_init_devices: "
"gpio_pin_configure(%s(*%p), %d(\"%s\"), 0x%x) "
"failed, ret = %d\n",
gpios[idx].dev_name, gpios[idx].dev,
gpios[idx].pin, gpios[idx].label,
gpios[idx].flags, ret);
}
}
return 0;
}
SYS_INIT(io_init_devices, APPLICATION, 1);
int gpio_get_level(enum gpio_signal signal)
{
return gpio_pin_get(gpios[signal].dev, gpios[signal].pin);
}
int gpio_set_level(enum gpio_signal signal, int value)
{
return gpio_pin_set(gpios[signal].dev, gpios[signal].pin, value);
}
const struct device *gpio_get_device(enum gpio_signal signal)
{
return gpios[signal].dev;
}
gpio_pin_t gpio_get_pin(enum gpio_signal signal)
{
return gpios[signal].pin;
}
/* TODO(pfagerburg) move to another module */
int misc_io_get_board_version(void)
{
int version;
int val;
val = gpio_get_level(board_version_2);
if (val < 0) {
return val;
}
version = val << 2;
val = gpio_get_level(board_version_1);
if (val < 0) {
return val;
}
version |= val << 1;
val = gpio_get_level(board_version_0);
if (val < 0) {
return val;
}
version |= val;
return version;
}
/* Shell commands for debugging/testing use. See README.md for details. */
/* TODO (pfagerburg) replace with generic "set [IO name] on|off" commands. */
/**
* @brief Get value of TP126
*/
static int cmd_io_get_tp126(const struct shell *shell, size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
int val = gpio_get_level(tp126);
shell_fprintf(shell, SHELL_VT100_COLOR_DEFAULT, "TP126 = %d\n", val);
return 0;
}
/**
* @brief Get value of TP125
*/
static int cmd_io_get_tp125(const struct shell *shell, size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
int val = gpio_get_level(tp125);
shell_fprintf(shell, SHELL_VT100_COLOR_DEFAULT, "TP125 = %d\n", val);
return 0;
}
/**
* @brief Get the board version from BOARD_VERSION[2:0]
*/
static int cmd_io_get_ver(const struct shell *shell, size_t argc, char **argv)
{
ARG_UNUSED(argc);
ARG_UNUSED(argv);
int val = misc_io_get_board_version();
shell_fprintf(shell, SHELL_VT100_COLOR_DEFAULT,
"BOARD_VERSION[2:0] = %d\n", val);
return 0;
}
SHELL_STATIC_SUBCMD_SET_CREATE(
get_io, SHELL_CMD(tp126, NULL, "TP126", cmd_io_get_tp126),
SHELL_CMD(tp125, NULL, "TP125", cmd_io_get_tp125),
SHELL_CMD(ver, NULL, "BOARD_VERSION[2:0]", cmd_io_get_ver),
SHELL_SUBCMD_SET_END);
/**
* @brief Set TP126 to on
*/
static int cmd_io_set_tp126_on(const struct shell *shell, size_t argc,
char **argv)
{
ARG_UNUSED(shell);
ARG_UNUSED(argc);
ARG_UNUSED(argv);
return gpio_set_level(tp126, 1);
}
/**
* @brief Set TP126 to off
*/
static int cmd_io_set_tp126_off(const struct shell *shell, size_t argc,
char **argv)
{
ARG_UNUSED(shell);
ARG_UNUSED(argc);
ARG_UNUSED(argv);
return gpio_set_level(tp126, 0);
}
/**
* @brief Set TP125 to on
*/
static int cmd_io_set_tp125_on(const struct shell *shell, size_t argc,
char **argv)
{
ARG_UNUSED(shell);
ARG_UNUSED(argc);
ARG_UNUSED(argv);
return gpio_set_level(tp125, 1);
}
/**
* @brief Set TP126 to off
*/
static int cmd_io_set_tp125_off(const struct shell *shell, size_t argc,
char **argv)
{
ARG_UNUSED(shell);
ARG_UNUSED(argc);
ARG_UNUSED(argv);
return gpio_set_level(tp125, 0);
}
SHELL_STATIC_SUBCMD_SET_CREATE(
tp126_on_off, SHELL_CMD(on, NULL, "set TP126 on", cmd_io_set_tp126_on),
SHELL_CMD(off, NULL, "set TP126 off", cmd_io_set_tp126_off),
SHELL_SUBCMD_SET_END);
SHELL_STATIC_SUBCMD_SET_CREATE(
tp125_on_off, SHELL_CMD(on, NULL, "set TP125 on", cmd_io_set_tp125_on),
SHELL_CMD(off, NULL, "set TP125 off", cmd_io_set_tp125_off),
SHELL_SUBCMD_SET_END);
SHELL_STATIC_SUBCMD_SET_CREATE(
set_io, SHELL_CMD(tp126, &tp126_on_off, "set TP126", NULL),
SHELL_CMD(tp125, &tp125_on_off, "set TP125", NULL),
SHELL_SUBCMD_SET_END);
SHELL_STATIC_SUBCMD_SET_CREATE(io_cmds,
SHELL_CMD(get, &get_io, "get IO value", NULL),
SHELL_CMD(set, &set_io, "set IO pin", NULL),
SHELL_SUBCMD_SET_END /* Array terminated. */
);
SHELL_CMD_REGISTER(io, &io_cmds, "Control IO pins", NULL);