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:
committed by
Linus Walleij
parent
07b5a2a13f
commit
596c185284
@@ -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 },
|
||||
{ },
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user