pinctrl: bcm281xx: Provide pinctrl device info as OF platform data

Introduce a new struct type, "bcm281xx_pinctrl_info", that holds
information about the pins, pin functions and regmap config for a pin
control chip. Create such a struct for the BCM218xx and pass it as
device data for the OF compatible match.

This is done in preparation for introducing additional chip types
to the driver.

Signed-off-by: Artur Weber <aweber.kernel@gmail.com>
Link: https://lore.kernel.org/20250303-bcm21664-pinctrl-v3-3-5f8b80e4ab51@gmail.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Artur Weber
2025-03-03 21:54:48 +01:00
committed by Linus Walleij
parent 07b5a2a13f
commit 596c185284
+79 -42
View File
@@ -75,21 +75,41 @@ struct bcm281xx_pin_function {
const unsigned int ngroups;
};
/*
* Device types (used in bcm281xx_pinctrl_desc to differentiate
* the two device types from each other)
*/
enum bcm281xx_pinctrl_type {
BCM281XX_PINCTRL_TYPE,
};
/*
* bcm281xx_pinctrl_info - description of a pinctrl device supported
* by this driver, intended to be used as a provider of OF match data.
*/
struct bcm281xx_pinctrl_info {
enum bcm281xx_pinctrl_type device_type;
/* List of all pins */
const struct pinctrl_pin_desc *pins;
unsigned int npins;
const struct bcm281xx_pin_function *functions;
unsigned int nfunctions;
const struct regmap_config *regmap_config;
};
/*
* bcm281xx_pinctrl_data - Broadcom-specific pinctrl data
* @reg_base - base of pinctrl registers
*/
struct bcm281xx_pinctrl_data {
struct device *dev;
void __iomem *reg_base;
/* List of all pins */
const struct pinctrl_pin_desc *pins;
const unsigned int npins;
const struct bcm281xx_pin_function *functions;
const unsigned int nfunctions;
struct regmap *regmap;
const struct bcm281xx_pinctrl_info *info;
};
/*
@@ -933,11 +953,22 @@ static const struct bcm281xx_pin_function bcm281xx_functions[] = {
BCM281XX_PIN_FUNCTION(alt4),
};
static struct bcm281xx_pinctrl_data bcm281xx_pinctrl = {
static const struct regmap_config bcm281xx_pinctrl_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = BCM281XX_PIN_VC_CAM3_SDA * 4,
};
static const struct bcm281xx_pinctrl_info bcm281xx_pinctrl = {
.device_type = BCM281XX_PINCTRL_TYPE,
.pins = bcm281xx_pinctrl_pins,
.npins = ARRAY_SIZE(bcm281xx_pinctrl_pins),
.functions = bcm281xx_functions,
.nfunctions = ARRAY_SIZE(bcm281xx_functions),
.regmap_config = &bcm281xx_pinctrl_regmap_config,
};
static inline enum bcm281xx_pin_type pin_type_get(struct pinctrl_dev *pctldev,
@@ -945,10 +976,10 @@ static inline enum bcm281xx_pin_type pin_type_get(struct pinctrl_dev *pctldev,
{
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
if (pin >= pdata->npins)
if (pin >= pdata->info->npins)
return BCM281XX_PIN_TYPE_UNKNOWN;
return *(enum bcm281xx_pin_type *)(pdata->pins[pin].drv_data);
return *(enum bcm281xx_pin_type *)(pdata->info->pins[pin].drv_data);
}
#define BCM281XX_PIN_SHIFT(type, param) \
@@ -970,18 +1001,11 @@ static inline void bcm281xx_pin_update(u32 *reg_val, u32 *reg_mask,
*reg_mask |= param_mask;
}
static const struct regmap_config bcm281xx_pinctrl_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = BCM281XX_PIN_VC_CAM3_SDA,
};
static int bcm281xx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
{
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
return pdata->npins;
return pdata->info->npins;
}
static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
@@ -989,7 +1013,7 @@ static const char *bcm281xx_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
{
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
return pdata->pins[group].name;
return pdata->info->pins[group].name;
}
static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
@@ -999,7 +1023,7 @@ static int bcm281xx_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
{
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
*pins = &pdata->pins[group].number;
*pins = &pdata->info->pins[group].number;
*num_pins = 1;
return 0;
@@ -1025,7 +1049,7 @@ static int bcm281xx_pinctrl_get_fcns_count(struct pinctrl_dev *pctldev)
{
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
return pdata->nfunctions;
return pdata->info->nfunctions;
}
static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
@@ -1033,7 +1057,7 @@ static const char *bcm281xx_pinctrl_get_fcn_name(struct pinctrl_dev *pctldev,
{
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
return pdata->functions[function].name;
return pdata->info->functions[function].name;
}
static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
@@ -1043,8 +1067,8 @@ static int bcm281xx_pinctrl_get_fcn_groups(struct pinctrl_dev *pctldev,
{
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
*groups = pdata->functions[function].groups;
*num_groups = pdata->functions[function].ngroups;
*groups = pdata->info->functions[function].groups;
*num_groups = pdata->info->functions[function].ngroups;
return 0;
}
@@ -1054,14 +1078,15 @@ static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev,
unsigned int group)
{
struct bcm281xx_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
const struct bcm281xx_pin_function *f = &pdata->functions[function];
u32 offset = 4 * pdata->pins[group].number;
const struct bcm281xx_pin_function *f = &pdata->info->functions[function];
unsigned int pin = pdata->info->pins[group].number;
u32 offset = 4 * pin;
int rc = 0;
dev_dbg(pctldev->dev,
"%s(): Enable function %s (%d) of pin %s (%d) @offset 0x%x.\n",
__func__, f->name, function, pdata->pins[group].name,
pdata->pins[group].number, offset);
__func__, f->name, function, pdata->info->pins[group].name,
pin, offset);
rc = regmap_update_bits(pdata->regmap, offset,
BCM281XX_PIN_REG_F_SEL_MASK,
@@ -1069,7 +1094,7 @@ static int bcm281xx_pinmux_set(struct pinctrl_dev *pctldev,
if (rc)
dev_err(pctldev->dev,
"Error updating register for pin %s (%d).\n",
pdata->pins[group].name, pdata->pins[group].number);
pdata->info->pins[group].name, pin);
return rc;
}
@@ -1168,7 +1193,7 @@ static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev,
"Invalid Drive Strength value (%d) for "
"pin %s (%d). Valid values are "
"(2..16) mA, even numbers only.\n",
arg, pdata->pins[pin].name, pin);
arg, pdata->info->pins[pin].name, pin);
return -EINVAL;
}
bcm281xx_pin_update(val, mask, (arg/2)-1,
@@ -1179,7 +1204,7 @@ static int bcm281xx_std_pin_update(struct pinctrl_dev *pctldev,
default:
dev_err(pctldev->dev,
"Unrecognized pin config %d for pin %s (%d).\n",
param, pdata->pins[pin].name, pin);
param, pdata->info->pins[pin].name, pin);
return -EINVAL;
} /* switch config */
@@ -1233,7 +1258,7 @@ static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
"Invalid pull-up value (%d) for pin %s "
"(%d). Valid values are 568, 720, 831, "
"1080, 1200, 1800, 2700 Ohms.\n",
arg, pdata->pins[pin].name, pin);
arg, pdata->info->pins[pin].name, pin);
return -EINVAL;
}
@@ -1266,7 +1291,7 @@ static int bcm281xx_i2c_pin_update(struct pinctrl_dev *pctldev,
default:
dev_err(pctldev->dev,
"Unrecognized pin config %d for pin %s (%d).\n",
param, pdata->pins[pin].name, pin);
param, pdata->info->pins[pin].name, pin);
return -EINVAL;
} /* switch config */
@@ -1311,7 +1336,7 @@ static int bcm281xx_hdmi_pin_update(struct pinctrl_dev *pctldev,
default:
dev_err(pctldev->dev,
"Unrecognized pin config %d for pin %s (%d).\n",
param, pdata->pins[pin].name, pin);
param, pdata->info->pins[pin].name, pin);
return -EINVAL;
} /* switch config */
@@ -1354,7 +1379,7 @@ static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
default:
dev_err(pctldev->dev, "Unknown pin type for pin %s (%d).\n",
pdata->pins[pin].name, pin);
pdata->info->pins[pin].name, pin);
return -EINVAL;
} /* switch pin type */
@@ -1364,13 +1389,13 @@ static int bcm281xx_pinctrl_pin_config_set(struct pinctrl_dev *pctldev,
dev_dbg(pctldev->dev,
"%s(): Set pin %s (%d) with config 0x%x, mask 0x%x\n",
__func__, pdata->pins[pin].name, pin, cfg_val, cfg_mask);
__func__, pdata->info->pins[pin].name, pin, cfg_val, cfg_mask);
rc = regmap_update_bits(pdata->regmap, offset, cfg_mask, cfg_val);
if (rc) {
dev_err(pctldev->dev,
"Error updating register for pin %s (%d).\n",
pdata->pins[pin].name, pin);
pdata->info->pins[pin].name, pin);
return rc;
}
@@ -1390,11 +1415,23 @@ static struct pinctrl_desc bcm281xx_pinctrl_desc = {
.owner = THIS_MODULE,
};
static struct bcm281xx_pinctrl_data bcm281xx_pinctrl_pdata;
static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
{
struct bcm281xx_pinctrl_data *pdata = &bcm281xx_pinctrl;
struct bcm281xx_pinctrl_data *pdata = &bcm281xx_pinctrl_pdata;
struct pinctrl_dev *pctl;
/* Set device pointer in platform data */
pdata->dev = &pdev->dev;
/* Get the data to use from OF match */
pdata->info = of_device_get_match_data(&pdev->dev);
if (!pdata->info) {
dev_err(&pdev->dev, "Failed to get data from OF match\n");
return -ENODEV;
}
/* So far We can assume there is only 1 bank of registers */
pdata->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(pdata->reg_base)) {
@@ -1404,15 +1441,15 @@ static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
/* Initialize the dynamic part of pinctrl_desc */
pdata->regmap = devm_regmap_init_mmio(&pdev->dev, pdata->reg_base,
&bcm281xx_pinctrl_regmap_config);
pdata->info->regmap_config);
if (IS_ERR(pdata->regmap)) {
dev_err(&pdev->dev, "Regmap MMIO init failed.\n");
return -ENODEV;
}
bcm281xx_pinctrl_desc.name = dev_name(&pdev->dev);
bcm281xx_pinctrl_desc.pins = bcm281xx_pinctrl.pins;
bcm281xx_pinctrl_desc.npins = bcm281xx_pinctrl.npins;
bcm281xx_pinctrl_desc.pins = pdata->info->pins;
bcm281xx_pinctrl_desc.npins = pdata->info->npins;
pctl = devm_pinctrl_register(&pdev->dev, &bcm281xx_pinctrl_desc, pdata);
if (IS_ERR(pctl)) {
@@ -1426,7 +1463,7 @@ static int __init bcm281xx_pinctrl_probe(struct platform_device *pdev)
}
static const struct of_device_id bcm281xx_pinctrl_of_match[] = {
{ .compatible = "brcm,bcm11351-pinctrl", },
{ .compatible = "brcm,bcm11351-pinctrl", .data = &bcm281xx_pinctrl },
{ },
};