Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,38 @@
# SPDX-License-Identifier: GPL-2.0-or-later
config PINCTRL_RTD
tristate "Realtek DHC core pin controller driver"
depends on ARCH_REALTEK || (COMPILE_TEST && OF)
default ARCH_REALTEK
select PINMUX
select GENERIC_PINCONF
select REGMAP_MMIO
config PINCTRL_RTD1619B
tristate "Realtek DHC 1619B pin controller driver"
depends on PINCTRL_RTD
default ARCH_REALTEK
config PINCTRL_RTD1319D
tristate "Realtek DHC 1319D pin controller driver"
depends on PINCTRL_RTD
default ARCH_REALTEK
config PINCTRL_RTD1315E
tristate "Realtek DHC 1315E pin controller driver"
depends on PINCTRL_RTD
default ARCH_REALTEK
config PINCTRL_RTD1625
tristate "Realtek DHC 1625 pin controller driver"
depends on PINCTRL_RTD
default ARCH_REALTEK
help
This driver enables support for the pin controller on the Realtek
RTD1625 SoCs.
It implements pin multiplexing for function selection and GPIO enabling.
It also utilizes the generic pin configuration interface to manage
electrical properties for both individual pins and pin groups.
Say Y here to enable the pinctrl driver for RTD1625 SoCs
@@ -0,0 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Realtek DHC pin control drivers
obj-$(CONFIG_PINCTRL_RTD) += pinctrl-rtd.o
obj-$(CONFIG_PINCTRL_RTD1619B) += pinctrl-rtd1619b.o
obj-$(CONFIG_PINCTRL_RTD1319D) += pinctrl-rtd1319d.o
obj-$(CONFIG_PINCTRL_RTD1315E) += pinctrl-rtd1315e.o
obj-$(CONFIG_PINCTRL_RTD1625) += pinctrl-rtd1625.o
@@ -0,0 +1,750 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Realtek DHC pin controller driver
*
* Copyright (c) 2023 Realtek Semiconductor Corp.
*/
#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h>
#include <linux/seq_file.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include "../core.h"
#include "../pinctrl-utils.h"
#include "pinctrl-rtd.h"
struct rtd_pinctrl {
struct device *dev;
struct pinctrl_dev *pcdev;
void __iomem *base;
struct pinctrl_desc desc;
const struct rtd_pinctrl_desc *info;
struct regmap *regmap_pinctrl;
u32 **saved_regs;
};
/* custom pinconf parameters */
#define RTD_DRIVE_STRENGTH_P (PIN_CONFIG_END + 1)
#define RTD_DRIVE_STRENGTH_N (PIN_CONFIG_END + 2)
#define RTD_DUTY_CYCLE (PIN_CONFIG_END + 3)
#define RTD_HIGH_VIL (PIN_CONFIG_END + 4)
static const struct pinconf_generic_params rtd_custom_bindings[] = {
{"realtek,drive-strength-p", RTD_DRIVE_STRENGTH_P, 0},
{"realtek,drive-strength-n", RTD_DRIVE_STRENGTH_N, 0},
{"realtek,duty-cycle", RTD_DUTY_CYCLE, 0},
{"realtek,high-vil-microvolt", RTD_HIGH_VIL, 0},
};
static int rtd_pinctrl_get_groups_count(struct pinctrl_dev *pcdev)
{
struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);
return data->info->num_groups;
}
static const char *rtd_pinctrl_get_group_name(struct pinctrl_dev *pcdev,
unsigned int selector)
{
struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);
return data->info->groups[selector].name;
}
static int rtd_pinctrl_get_group_pins(struct pinctrl_dev *pcdev,
unsigned int selector,
const unsigned int **pins,
unsigned int *num_pins)
{
struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);
*pins = data->info->groups[selector].pins;
*num_pins = data->info->groups[selector].num_pins;
return 0;
}
static void rtd_pinctrl_dbg_show(struct pinctrl_dev *pcdev,
struct seq_file *s,
unsigned int offset)
{
struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);
const struct rtd_pin_desc *mux = &data->info->muxes[offset];
const struct rtd_pin_mux_desc *func;
u32 val;
u32 mask;
u32 pin_val;
int is_map;
if (!mux->name) {
seq_puts(s, "[not defined]");
return;
}
val = readl_relaxed(data->base + mux->mux_offset);
mask = mux->mux_mask;
pin_val = val & mask;
is_map = 0;
func = &mux->functions[0];
seq_puts(s, "function: ");
while (func->name) {
if (func->mux_value == pin_val) {
is_map = 1;
seq_printf(s, "[%s] ", func->name);
} else {
seq_printf(s, "%s ", func->name);
}
func++;
}
if (!is_map)
seq_puts(s, "[not defined]");
}
static const struct pinctrl_ops rtd_pinctrl_ops = {
.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
.dt_free_map = pinctrl_utils_free_map,
.get_groups_count = rtd_pinctrl_get_groups_count,
.get_group_name = rtd_pinctrl_get_group_name,
.get_group_pins = rtd_pinctrl_get_group_pins,
.pin_dbg_show = rtd_pinctrl_dbg_show,
};
static int rtd_pinctrl_get_functions_count(struct pinctrl_dev *pcdev)
{
struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);
return data->info->num_functions;
}
static const char *rtd_pinctrl_get_function_name(struct pinctrl_dev *pcdev,
unsigned int selector)
{
struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);
return data->info->functions[selector].name;
}
static int rtd_pinctrl_get_function_groups(struct pinctrl_dev *pcdev,
unsigned int selector,
const char * const **groups,
unsigned int * const num_groups)
{
struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);
*groups = data->info->functions[selector].groups;
*num_groups = data->info->functions[selector].num_groups;
return 0;
}
static const struct rtd_pin_desc *rtd_pinctrl_find_mux(struct rtd_pinctrl *data, unsigned int pin)
{
if (data->info->muxes[pin].name)
return &data->info->muxes[pin];
return NULL;
}
static int rtd_pinctrl_set_one_mux(struct pinctrl_dev *pcdev,
unsigned int pin, const char *func_name)
{
struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);
const struct rtd_pin_desc *mux;
int ret = 0;
int i;
mux = rtd_pinctrl_find_mux(data, pin);
if (!mux)
return 0;
if (!mux->functions) {
if (!mux->name)
dev_err(pcdev->dev, "NULL pin has no functions\n");
else
dev_err(pcdev->dev, "No functions available for pin %s\n", mux->name);
return -ENOTSUPP;
}
for (i = 0; mux->functions[i].name; i++) {
if (strcmp(mux->functions[i].name, func_name) != 0)
continue;
ret = regmap_update_bits(data->regmap_pinctrl, mux->mux_offset, mux->mux_mask,
mux->functions[i].mux_value);
return ret;
}
if (!mux->name) {
dev_err(pcdev->dev, "NULL pin provided for function %s\n", func_name);
return -EINVAL;
}
dev_err(pcdev->dev, "No function %s available for pin %s\n", func_name, mux->name);
return -EINVAL;
}
static int rtd_pinctrl_set_mux(struct pinctrl_dev *pcdev,
unsigned int function, unsigned int group)
{
struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);
const unsigned int *pins;
unsigned int num_pins;
const char *func_name;
const char *group_name;
int i, ret;
func_name = data->info->functions[function].name;
group_name = data->info->groups[group].name;
ret = rtd_pinctrl_get_group_pins(pcdev, group, &pins, &num_pins);
if (ret) {
dev_err(pcdev->dev, "Getting pins for group %s failed\n", group_name);
return ret;
}
for (i = 0; i < num_pins; i++) {
ret = rtd_pinctrl_set_one_mux(pcdev, pins[i], func_name);
if (ret)
return ret;
}
return 0;
}
static int rtd_pinctrl_gpio_request_enable(struct pinctrl_dev *pcdev,
struct pinctrl_gpio_range *range,
unsigned int offset)
{
return rtd_pinctrl_set_one_mux(pcdev, offset, "gpio");
}
static const struct pinmux_ops rtd_pinmux_ops = {
.get_functions_count = rtd_pinctrl_get_functions_count,
.get_function_name = rtd_pinctrl_get_function_name,
.get_function_groups = rtd_pinctrl_get_function_groups,
.set_mux = rtd_pinctrl_set_mux,
.gpio_request_enable = rtd_pinctrl_gpio_request_enable,
};
static const struct pinctrl_pin_desc
*rtd_pinctrl_get_pin_by_number(struct rtd_pinctrl *data, int number)
{
int i;
for (i = 0; i < data->info->num_pins; i++) {
if (data->info->pins[i].number == number)
return &data->info->pins[i];
}
return NULL;
}
static const struct rtd_pin_config_desc
*rtd_pinctrl_find_config(struct rtd_pinctrl *data, unsigned int pin)
{
if (data->info->configs[pin].name)
return &data->info->configs[pin];
return NULL;
}
static const struct rtd_pin_sconfig_desc *rtd_pinctrl_find_sconfig(struct rtd_pinctrl *data,
unsigned int pin)
{
int i;
const struct pinctrl_pin_desc *pin_desc;
const char *pin_name;
pin_desc = rtd_pinctrl_get_pin_by_number(data, pin);
if (!pin_desc)
return NULL;
pin_name = pin_desc->name;
for (i = 0; i < data->info->num_sconfigs; i++) {
if (strcmp(data->info->sconfigs[i].name, pin_name) == 0)
return &data->info->sconfigs[i];
}
return NULL;
}
static int rtd_pconf_parse_conf(struct rtd_pinctrl *data,
unsigned int pinnr,
enum pin_config_param param,
unsigned int arg)
{
const struct rtd_pin_config_desc *config_desc;
const struct rtd_pin_sconfig_desc *sconfig_desc;
u8 set_val = 0;
u16 strength;
u32 val;
u32 mask;
u32 pulsel_off, pulen_off, smt_off, curr_off, pow_off, reg_off, p_off, n_off,
input_volt_off, sr_off, hvil_off;
const char *name = data->info->pins[pinnr].name;
int ret = 0;
config_desc = rtd_pinctrl_find_config(data, pinnr);
if (!config_desc) {
dev_err(data->dev, "Pin config unsupported for pin: %s\n", name);
return -ENOTSUPP;
}
switch ((u32)param) {
case PIN_CONFIG_INPUT_SCHMITT:
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
if (config_desc->smt_offset == NA) {
dev_err(data->dev, "Input schmitt unsupported for pin: %s\n", name);
return -ENOTSUPP;
}
smt_off = config_desc->base_bit + config_desc->smt_offset;
reg_off = config_desc->reg_offset;
set_val = arg;
mask = BIT(smt_off);
val = set_val ? BIT(smt_off) : 0;
break;
case PIN_CONFIG_DRIVE_PUSH_PULL:
if (config_desc->pud_en_offset == NA) {
dev_err(data->dev, "Push pull unsupported for pin: %s\n", name);
return -ENOTSUPP;
}
pulen_off = config_desc->base_bit + config_desc->pud_en_offset;
reg_off = config_desc->reg_offset;
mask = BIT(pulen_off);
val = 0;
break;
case PIN_CONFIG_BIAS_DISABLE:
if (config_desc->pud_en_offset == NA) {
dev_err(data->dev, "Bias disable unsupported for pin: %s\n", name);
return -ENOTSUPP;
}
pulen_off = config_desc->base_bit + config_desc->pud_en_offset;
reg_off = config_desc->reg_offset;
mask = BIT(pulen_off);
val = 0;
break;
case PIN_CONFIG_BIAS_PULL_UP:
if (config_desc->pud_en_offset == NA) {
dev_err(data->dev, "Bias pull up unsupported for pin:%s\n", name);
return -ENOTSUPP;
}
pulen_off = config_desc->base_bit + config_desc->pud_en_offset;
pulsel_off = config_desc->base_bit + config_desc->pud_sel_offset;
reg_off = config_desc->reg_offset;
mask = BIT(pulen_off) | BIT(pulsel_off);
val = mask;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
if (config_desc->pud_en_offset == NA) {
dev_err(data->dev, "Bias pull down unsupported for pin: %s\n", name);
return -ENOTSUPP;
}
pulen_off = config_desc->base_bit + config_desc->pud_en_offset;
pulsel_off = config_desc->base_bit + config_desc->pud_sel_offset;
reg_off = config_desc->reg_offset;
mask = BIT(pulen_off) | BIT(pulsel_off);
val = BIT(pulen_off);
break;
case PIN_CONFIG_DRIVE_STRENGTH:
curr_off = config_desc->base_bit + config_desc->curr_offset;
reg_off = config_desc->reg_offset;
strength = arg;
val = 0;
switch (config_desc->curr_type) {
case PADDRI_4_8:
if (strength == 4)
val = 0;
else if (strength == 8)
val = BIT(curr_off);
else
return -EINVAL;
break;
case PADDRI_2_4:
if (strength == 2)
val = 0;
else if (strength == 4)
val = BIT(curr_off);
else
return -EINVAL;
break;
case NA:
dev_err(data->dev, "Drive strength unsupported for pin: %s\n", name);
return -ENOTSUPP;
default:
return -EINVAL;
}
mask = BIT(curr_off);
break;
case PIN_CONFIG_POWER_SOURCE:
if (config_desc->power_offset == NA) {
dev_err(data->dev, "Power source unsupported for pin: %s\n", name);
return -ENOTSUPP;
}
reg_off = config_desc->reg_offset;
pow_off = config_desc->base_bit + config_desc->power_offset;
if (pow_off >= 32) {
reg_off += 0x4;
pow_off -= 32;
}
set_val = arg;
mask = BIT(pow_off);
val = set_val ? mask : 0;
break;
case PIN_CONFIG_SLEW_RATE:
if (config_desc->slew_rate_offset == NA) {
dev_err(data->dev, "Slew rate setting unsupported for pin: %s\n", name);
return -ENOTSUPP;
}
switch (arg) {
case 1:
set_val = 0;
break;
case 10:
set_val = 1;
break;
case 20:
set_val = 2;
break;
case 30:
set_val = 3;
break;
default:
return -EINVAL;
}
sr_off = config_desc->base_bit + config_desc->slew_rate_offset;
reg_off = config_desc->reg_offset;
mask = 0x3 << sr_off;
val = arg << sr_off;
break;
case PIN_CONFIG_INPUT_VOLTAGE_UV:
if (config_desc->input_volt_offset == NA) {
dev_err(data->dev, "Input voltage level setting unsupported for pin:%s\n",
name);
return -ENOTSUPP;
}
if (arg == 3300000)
set_val = 1;
else if (arg == 1800000)
set_val = 0;
else
return -EINVAL;
input_volt_off = config_desc->base_bit + config_desc->input_volt_offset;
reg_off = config_desc->reg_offset;
mask = BIT(input_volt_off);
val = set_val ? BIT(input_volt_off) : 0;
break;
case RTD_HIGH_VIL:
if (config_desc->hvil_offset == NA) {
dev_err(data->dev, "High vil setting unsupported for pin:%s\n", name);
return -ENOTSUPP;
}
hvil_off = config_desc->base_bit + config_desc->hvil_offset;
reg_off = config_desc->reg_offset;
mask = BIT(hvil_off);
val = 1;
break;
case RTD_DRIVE_STRENGTH_P:
sconfig_desc = rtd_pinctrl_find_sconfig(data, pinnr);
if (!sconfig_desc) {
dev_err(data->dev, "P driving unsupported for pin: %s\n", name);
return -ENOTSUPP;
}
set_val = arg;
reg_off = sconfig_desc->reg_offset;
p_off = sconfig_desc->pdrive_offset;
if (p_off >= 32) {
reg_off += 0x4;
p_off -= 32;
}
mask = GENMASK(p_off + sconfig_desc->pdrive_maskbits - 1, p_off);
val = set_val << p_off;
break;
case RTD_DRIVE_STRENGTH_N:
sconfig_desc = rtd_pinctrl_find_sconfig(data, pinnr);
if (!sconfig_desc) {
dev_err(data->dev, "N driving unsupported for pin: %s\n", name);
return -ENOTSUPP;
}
set_val = arg;
reg_off = sconfig_desc->reg_offset;
n_off = sconfig_desc->ndrive_offset;
if (n_off >= 32) {
reg_off += 0x4;
n_off -= 32;
}
mask = GENMASK(n_off + sconfig_desc->ndrive_maskbits - 1, n_off);
val = set_val << n_off;
break;
case RTD_DUTY_CYCLE:
sconfig_desc = rtd_pinctrl_find_sconfig(data, pinnr);
if (!sconfig_desc || sconfig_desc->dcycle_offset == NA) {
dev_err(data->dev, "Duty cycle unsupported for pin: %s\n", name);
return -ENOTSUPP;
}
set_val = arg;
reg_off = config_desc->reg_offset;
mask = GENMASK(sconfig_desc->dcycle_offset +
sconfig_desc->dcycle_maskbits - 1, sconfig_desc->dcycle_offset);
val = set_val << sconfig_desc->dcycle_offset;
break;
default:
dev_dbg(data->dev, "unsupported pinconf: %d\n", (u32)param);
return -ENOTSUPP;
}
ret = regmap_update_bits(data->regmap_pinctrl, reg_off, mask, val);
if (ret)
dev_err(data->dev, "could not update pinconf(%d) for pin(%s)\n", (u32)param, name);
return ret;
}
static int rtd_pin_config_get(struct pinctrl_dev *pcdev, unsigned int pinnr,
unsigned long *config)
{
unsigned int param = pinconf_to_config_param(*config);
unsigned int arg = 0;
switch (param) {
default:
return -ENOTSUPP;
}
*config = pinconf_to_config_packed(param, arg);
return 0;
}
static int rtd_pin_config_set(struct pinctrl_dev *pcdev, unsigned int pinnr,
unsigned long *configs, unsigned int num_configs)
{
struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);
int i;
int ret = 0;
for (i = 0; i < num_configs; i++) {
ret = rtd_pconf_parse_conf(data, pinnr,
pinconf_to_config_param(configs[i]),
pinconf_to_config_argument(configs[i]));
if (ret < 0)
return ret;
}
return 0;
}
static int rtd_pin_config_group_set(struct pinctrl_dev *pcdev, unsigned int group,
unsigned long *configs, unsigned int num_configs)
{
struct rtd_pinctrl *data = pinctrl_dev_get_drvdata(pcdev);
const unsigned int *pins;
unsigned int num_pins;
const char *group_name;
int i, ret;
group_name = data->info->groups[group].name;
ret = rtd_pinctrl_get_group_pins(pcdev, group, &pins, &num_pins);
if (ret) {
dev_err(pcdev->dev, "Getting pins for group %s failed\n", group_name);
return ret;
}
for (i = 0; i < num_pins; i++) {
ret = rtd_pin_config_set(pcdev, pins[i], configs, num_configs);
if (ret)
return ret;
}
return 0;
}
static const struct pinconf_ops rtd_pinconf_ops = {
.is_generic = true,
.pin_config_get = rtd_pin_config_get,
.pin_config_set = rtd_pin_config_set,
.pin_config_group_set = rtd_pin_config_group_set,
};
static const struct regmap_config rtd_pinctrl_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.use_relaxed_mmio = true,
};
static int rtd_pinctrl_init_pm(struct rtd_pinctrl *data)
{
const struct rtd_pin_range *pin_range = data->info->pin_range;
struct device *dev = data->pcdev->dev;
const struct rtd_reg_range *range;
size_t num_entries;
int i;
data->saved_regs = devm_kcalloc(dev, pin_range->num_ranges, sizeof(u32 *), GFP_KERNEL);
if (!data->saved_regs)
return -ENOMEM;
for (i = 0; i < pin_range->num_ranges; i++) {
range = &pin_range->ranges[i];
num_entries = range->len / 4;
data->saved_regs[i] = devm_kzalloc(dev, num_entries * sizeof(u32), GFP_KERNEL);
if (!data->saved_regs[i])
return -ENOMEM;
}
return 0;
}
int rtd_pinctrl_probe(struct platform_device *pdev, const struct rtd_pinctrl_desc *desc)
{
struct rtd_pinctrl *data;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(data->base))
return dev_err_probe(&pdev->dev, PTR_ERR(data->base),
"Failed to ioremap resource\n");
data->dev = &pdev->dev;
data->info = desc;
data->desc.name = dev_name(&pdev->dev);
data->desc.pins = data->info->pins;
data->desc.npins = data->info->num_pins;
data->desc.pctlops = &rtd_pinctrl_ops;
data->desc.pmxops = &rtd_pinmux_ops;
data->desc.confops = &rtd_pinconf_ops;
data->desc.custom_params = rtd_custom_bindings;
data->desc.num_custom_params = ARRAY_SIZE(rtd_custom_bindings);
data->desc.owner = THIS_MODULE;
data->regmap_pinctrl = devm_regmap_init_mmio(data->dev, data->base,
&rtd_pinctrl_regmap_config);
if (IS_ERR(data->regmap_pinctrl))
return dev_err_probe(data->dev, PTR_ERR(data->regmap_pinctrl),
"Failed to init regmap\n");
data->pcdev = devm_pinctrl_register(&pdev->dev, &data->desc, data);
if (IS_ERR(data->pcdev))
return dev_err_probe(data->dev, PTR_ERR(data->pcdev),
"Failed to register pinctrl\n");
platform_set_drvdata(pdev, data);
dev_dbg(&pdev->dev, "probed\n");
if (data->info->pin_range) {
if (rtd_pinctrl_init_pm(data))
return -ENOMEM;
}
return 0;
}
EXPORT_SYMBOL(rtd_pinctrl_probe);
static int realtek_pinctrl_suspend(struct device *dev)
{
struct rtd_pinctrl *data = dev_get_drvdata(dev);
const struct rtd_pin_range *pin_range = data->info->pin_range;
const struct rtd_reg_range *range;
u32 *range_regs;
int count;
int i, j;
int ret;
if (!data->saved_regs)
return 0;
for (i = 0; i < pin_range->num_ranges; i++) {
range = &pin_range->ranges[i];
range_regs = data->saved_regs[i];
count = range->len / 4;
for (j = 0; j < count; j++) {
ret = regmap_read(data->regmap_pinctrl, range->offset + (j * 4),
&range_regs[j]);
if (ret) {
dev_err(dev, "failed to store register 0x%x: %d\n",
range->offset + (j * 4), ret);
return ret;
}
}
}
return 0;
}
static int realtek_pinctrl_resume(struct device *dev)
{
struct rtd_pinctrl *data = dev_get_drvdata(dev);
const struct rtd_pin_range *pin_range = data->info->pin_range;
const struct rtd_reg_range *range;
u32 *range_regs;
int count;
int i, j;
int ret;
if (!data->saved_regs)
return 0;
for (i = 0; i < pin_range->num_ranges; i++) {
range = &pin_range->ranges[i];
range_regs = data->saved_regs[i];
count = range->len / 4;
for (j = 0; j < count; j++) {
ret = regmap_write(data->regmap_pinctrl, range->offset + (j * 4),
range_regs[j]);
if (ret) {
dev_err(dev, "failed to restore register 0x%x: %d\n",
range->offset + (j * 4), ret);
return ret;
}
}
}
return 0;
}
const struct dev_pm_ops realtek_pinctrl_pm_ops = {
NOIRQ_SYSTEM_SLEEP_PM_OPS(realtek_pinctrl_suspend, realtek_pinctrl_resume)
};
EXPORT_SYMBOL_GPL(realtek_pinctrl_pm_ops);
MODULE_DESCRIPTION("Realtek DHC SoC pinctrl driver");
MODULE_LICENSE("GPL");
@@ -0,0 +1,174 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2023 Realtek Semiconductor Corp.
*/
#define NA 0xffffffff
#define PADDRI_4_8 1
#define PADDRI_2_4 0
struct rtd_pin_group_desc {
const char *name;
const unsigned int *pins;
unsigned int num_pins;
};
struct rtd_pin_func_desc {
const char *name;
const char * const *groups;
unsigned int num_groups;
};
struct rtd_pin_mux_desc {
const char *name;
u32 mux_value;
};
struct rtd_pin_config_desc {
const char *name;
unsigned int reg_offset;
unsigned int base_bit;
unsigned int pud_en_offset;
unsigned int pud_sel_offset;
unsigned int curr_offset;
unsigned int smt_offset;
unsigned int power_offset;
unsigned int curr_type;
unsigned int input_volt_offset;
unsigned int slew_rate_offset;
unsigned int hvil_offset;
};
struct rtd_pin_sconfig_desc {
const char *name;
unsigned int reg_offset;
unsigned int dcycle_offset;
unsigned int dcycle_maskbits;
unsigned int ndrive_offset;
unsigned int ndrive_maskbits;
unsigned int pdrive_offset;
unsigned int pdrive_maskbits;
};
struct rtd_reg_range {
unsigned int offset;
size_t len;
};
struct rtd_pin_range {
const struct rtd_reg_range *ranges;
const int num_ranges;
};
struct rtd_pin_desc {
const char *name;
unsigned int mux_offset;
u32 mux_mask;
const struct rtd_pin_mux_desc *functions;
};
struct rtd_pin_reg_list {
unsigned int reg_offset;
unsigned int val;
};
#define SHIFT_LEFT(_val, _shift) ((_val) << (_shift))
#define RTK_PIN_MUX(_name, _mux_off, _mux_mask, ...) \
{ \
.name = # _name, \
.mux_offset = _mux_off, \
.mux_mask = _mux_mask, \
.functions = (const struct rtd_pin_mux_desc []) { \
__VA_ARGS__, { } \
}, \
}
#define RTK_PIN_CONFIG(_name, _reg_off, _base_bit, _pud_en_off, \
_pud_sel_off, _curr_off, _smt_off, _pow_off, _curr_type) \
{ \
.name = # _name, \
.reg_offset = _reg_off, \
.base_bit = _base_bit, \
.pud_en_offset = _pud_en_off, \
.pud_sel_offset = _pud_sel_off, \
.curr_offset = _curr_off, \
.smt_offset = _smt_off, \
.power_offset = _pow_off, \
.curr_type = _curr_type, \
}
#define RTK_PIN_CONFIG_V2(_name, _reg_off, _base_bit, _pud_en_off, \
_pud_sel_off, _curr_off, _smt_off, _pow_off, _input_volt_off, \
_curr_type) \
{ \
.name = # _name, \
.reg_offset = _reg_off, \
.base_bit = _base_bit, \
.pud_en_offset = _pud_en_off, \
.pud_sel_offset = _pud_sel_off, \
.curr_offset = _curr_off, \
.smt_offset = _smt_off, \
.power_offset = _pow_off, \
.input_volt_offset = _input_volt_off, \
.curr_type = _curr_type, \
}
#define RTK_PIN_CONFIG_I2C(_name, _reg_off, _base_bit, _pud_en_off, \
_pud_sel_off, _curr_off, _smt_off, _hvil_off, _sr_off, _pow_off, \
_input_volt_off, _curr_type) \
{ \
.name = # _name, \
.reg_offset = _reg_off, \
.base_bit = _base_bit, \
.pud_en_offset = _pud_en_off, \
.pud_sel_offset = _pud_sel_off, \
.curr_offset = _curr_off, \
.smt_offset = _smt_off, \
.hvil_offset = _hvil_off, \
.slew_rate_offset = _sr_off, \
.power_offset = _pow_off, \
.input_volt_offset = _input_volt_off, \
.curr_type = _curr_type, \
}
#define RTK_PIN_SCONFIG(_name, _reg_off, _d_offset, _d_mask, \
_n_offset, _n_mask, _p_offset, _p_mask) \
{ \
.name = # _name, \
.reg_offset = _reg_off, \
.dcycle_offset = _d_offset, \
.dcycle_maskbits = _d_mask, \
.ndrive_offset = _n_offset, \
.ndrive_maskbits = _n_mask, \
.pdrive_offset = _p_offset, \
.pdrive_maskbits = _p_mask, \
}
#define RTK_PIN_FUNC(_mux_val, _name) \
{ \
.name = _name, \
.mux_value = _mux_val, \
}
struct rtd_pinctrl_desc {
const struct pinctrl_pin_desc *pins;
unsigned int num_pins;
const struct rtd_pin_group_desc *groups;
unsigned int num_groups;
const struct rtd_pin_func_desc *functions;
unsigned int num_functions;
const struct rtd_pin_desc *muxes;
unsigned int num_muxes;
const struct rtd_pin_config_desc *configs;
unsigned int num_configs;
const struct rtd_pin_sconfig_desc *sconfigs;
unsigned int num_sconfigs;
struct rtd_pin_reg_list *lists;
unsigned int num_regs;
const struct rtd_pin_range *pin_range;
};
int rtd_pinctrl_probe(struct platform_device *pdev, const struct rtd_pinctrl_desc *desc);
extern const struct dev_pm_ops realtek_pinctrl_pm_ops;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff