2023-03-27 06:29:36

by Chester Lin

[permalink] [raw]
Subject: [PATCH v5 0/5] pinctrl: s32: driver improvements and generic struct use

Hello,

This patch series contains some improvements for s32 pinctrl drivers suggested
by upstream[1], such as
- Fix error shadowings and improve return value handlings.
- Fix print format.
- Remove unnecessary blanks.
- Use proper macros and helpers to simplify codes.
- Refactor config param parsing and remove config arguments that are never used.
- Use generic struct pingroup and struct pinfunction to describe pin data.

Regards,
Chester

[1] https://lore.kernel.org/all/[email protected]/

Changes in v5:
- Remove unnecessary (void *) type casting found in pinctrl-s32g2.

Changes in v4:
- Link: https://lore.kernel.org/lkml/[email protected]/
- Merge the of_device_get_match_data() patch [v3 1/6] into the last patch
[v4 5/5, "pinctrl: s32: separate const device data ..."] in order to solve
compiler warning properly.

Changes in v3:
- Link: https://lore.kernel.org/lkml/[email protected]/
- Remove unnecessary type casting and correct type qualifiers.
- Split the previous generic-struct patch [v2 4/4] into two separate patches.
- Add a new patch [v3 6/6] to attach a real const .data with of_device_id.

Changes in v2:
- Link: https://lore.kernel.org/lkml/[email protected]/
- Use of_device_get_match_data() to get matched of_device_id data.
- Enhance sizeof() arguments.
- Fix blanks and remove unnecessary parentheses.
- Drop unnecessary marcos and s32_pin_config() implemented in v1 and set/clear
mask/config values transparently.
- Put pull-function related cases together in s32_pin_set_pull().
- Simply use generic 'struct pinfunction' rather than having extra 'struct
s32_pmx_func'.

Chester Lin (5):
pinctrl: s32: refine error/return/config checks and simplify driver
codes
pinctrl: s32cc: refactor pin config parsing
pinctrl: s32cc: embed generic struct pingroup
pinctrl: s32cc: Use generic struct data to describe pin function
pinctrl: s32: separate const device data from struct
s32_pinctrl_soc_info

drivers/pinctrl/nxp/pinctrl-s32.h | 40 ++--
drivers/pinctrl/nxp/pinctrl-s32cc.c | 282 ++++++++++++++++------------
drivers/pinctrl/nxp/pinctrl-s32g2.c | 17 +-
3 files changed, 178 insertions(+), 161 deletions(-)

--
2.37.3


2023-03-27 06:29:39

by Chester Lin

[permalink] [raw]
Subject: [PATCH v5 1/5] pinctrl: s32: refine error/return/config checks and simplify driver codes

Improve error/return code handlings and config checks in order to have
better reliability and simplify driver codes such as removing/changing
improper macros, blanks, print formats and helper calls.

Signed-off-by: Chester Lin <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
---
(No change since v2)

drivers/pinctrl/nxp/pinctrl-s32cc.c | 141 +++++++++++++++-------------
drivers/pinctrl/nxp/pinctrl-s32g2.c | 4 +-
2 files changed, 76 insertions(+), 69 deletions(-)

diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
index e1da332433a3..f698e1a240ef 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
@@ -28,7 +28,8 @@
#include "../pinctrl-utils.h"
#include "pinctrl-s32.h"

-#define S32_PIN_ID_MASK GENMASK(31, 4)
+#define S32_PIN_ID_SHIFT 4
+#define S32_PIN_ID_MASK GENMASK(31, S32_PIN_ID_SHIFT)

#define S32_MSCR_SSS_MASK GENMASK(2, 0)
#define S32_MSCR_PUS BIT(12)
@@ -46,7 +47,7 @@ static struct regmap_config s32_regmap_config = {

static u32 get_pin_no(u32 pinmux)
{
- return (pinmux & S32_PIN_ID_MASK) >> __ffs(S32_PIN_ID_MASK);
+ return (pinmux & S32_PIN_ID_MASK) >> S32_PIN_ID_SHIFT;
}

static u32 get_pin_func(u32 pinmux)
@@ -108,7 +109,7 @@ s32_get_region(struct pinctrl_dev *pctldev, unsigned int pin)
unsigned int mem_regions = ipctl->info->mem_regions;
unsigned int i;

- for (i = 0; i < mem_regions; ++i) {
+ for (i = 0; i < mem_regions; i++) {
pin_range = ipctl->regions[i].pin_range;
if (pin >= pin_range->start && pin <= pin_range->end)
return &ipctl->regions[i];
@@ -224,8 +225,7 @@ static int s32_dt_group_node_to_map(struct pinctrl_dev *pctldev,

n_pins = of_property_count_elems_of_size(np, "pinmux", sizeof(u32));
if (n_pins < 0) {
- dev_warn(dev, "Unable to find 'pinmux' property in node %s.\n",
- np->name);
+ dev_warn(dev, "Can't find 'pinmux' property in node %pOFn\n", np);
} else if (!n_pins) {
return -EINVAL;
}
@@ -317,20 +317,25 @@ static int s32_pmx_set(struct pinctrl_dev *pctldev, unsigned int selector,
info->functions[selector].name, grp->name);

/* Check beforehand so we don't have a partial config. */
- for (i = 0; i < grp->npins; ++i) {
+ for (i = 0; i < grp->npins; i++) {
if (s32_check_pin(pctldev, grp->pin_ids[i]) != 0) {
- dev_err(info->dev, "invalid pin: %d in group: %d\n",
+ dev_err(info->dev, "invalid pin: %u in group: %u\n",
grp->pin_ids[i], group);
return -EINVAL;
}
}

- for (i = 0, ret = 0; i < grp->npins && !ret; ++i) {
+ for (i = 0, ret = 0; i < grp->npins && !ret; i++) {
ret = s32_regmap_update(pctldev, grp->pin_ids[i],
S32_MSCR_SSS_MASK, grp->pin_sss[i]);
+ if (ret) {
+ dev_err(info->dev, "Failed to set pin %u\n",
+ grp->pin_ids[i]);
+ return ret;
+ }
}

- return ret;
+ return 0;
}

static int s32_pmx_get_funcs_count(struct pinctrl_dev *pctldev)
@@ -375,8 +380,8 @@ static int s32_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
int ret;

ret = s32_regmap_read(pctldev, offset, &config);
- if (ret != 0)
- return -EINVAL;
+ if (ret)
+ return ret;

/* Save current configuration */
gpio_pin = kmalloc(sizeof(*gpio_pin), GFP_KERNEL);
@@ -387,7 +392,7 @@ static int s32_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
gpio_pin->config = config;

spin_lock_irqsave(&ipctl->gpio_configs_lock, flags);
- list_add(&(gpio_pin->list), &(ipctl->gpio_configs));
+ list_add(&gpio_pin->list, &ipctl->gpio_configs);
spin_unlock_irqrestore(&ipctl->gpio_configs_lock, flags);

/* GPIO pin means SSS = 0 */
@@ -401,23 +406,20 @@ static void s32_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
unsigned int offset)
{
struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- struct list_head *pos, *tmp;
- struct gpio_pin_config *gpio_pin;
+ struct gpio_pin_config *gpio_pin, *tmp;
unsigned long flags;
int ret;

spin_lock_irqsave(&ipctl->gpio_configs_lock, flags);

- list_for_each_safe(pos, tmp, &ipctl->gpio_configs) {
- gpio_pin = list_entry(pos, struct gpio_pin_config, list);
-
+ list_for_each_entry_safe(gpio_pin, tmp, &ipctl->gpio_configs, list) {
if (gpio_pin->pin_id == offset) {
ret = s32_regmap_write(pctldev, gpio_pin->pin_id,
gpio_pin->config);
if (ret != 0)
goto unlock;

- list_del(pos);
+ list_del(&gpio_pin->list);
kfree(gpio_pin);
break;
}
@@ -461,7 +463,8 @@ static const int support_slew[] = {208, -1, -1, -1, 166, 150, 133, 83};

static int s32_get_slew_regval(int arg)
{
- int i;
+ unsigned int i;
+
/* Translate a real slew rate (MHz) to a register value */
for (i = 0; i < ARRAY_SIZE(support_slew); i++) {
if (arg == support_slew[i])
@@ -542,10 +545,11 @@ static int s32_pinconf_mscr_update(struct pinctrl_dev *pctldev,
unsigned int config = 0, mask = 0;
int i, ret;

- if (s32_check_pin(pctldev, pin_id) != 0)
- return -EINVAL;
+ ret = s32_check_pin(pctldev, pin_id);
+ if (ret)
+ return ret;

- dev_dbg(ipctl->dev, "pinconf set pin %s with %d configs\n",
+ dev_dbg(ipctl->dev, "pinconf set pin %s with %u configs\n",
pin_get_name(pctldev, pin_id), num_configs);

for (i = 0; i < num_configs; i++) {
@@ -559,11 +563,9 @@ static int s32_pinconf_mscr_update(struct pinctrl_dev *pctldev,
if (!config && !mask)
return 0;

- ret = s32_regmap_update(pctldev, pin_id, mask, config);
+ dev_dbg(ipctl->dev, "update: pin %u cfg 0x%x\n", pin_id, config);

- dev_dbg(ipctl->dev, "update: pin %d cfg 0x%x\n", pin_id, config);
-
- return ret;
+ return s32_regmap_update(pctldev, pin_id, mask, config);
}

static int s32_pinconf_get(struct pinctrl_dev *pctldev,
@@ -604,10 +606,13 @@ static void s32_pinconf_dbg_show(struct pinctrl_dev *pctldev,
struct seq_file *s, unsigned int pin_id)
{
unsigned int config;
- int ret = s32_regmap_read(pctldev, pin_id, &config);
+ int ret;

- if (!ret)
- seq_printf(s, "0x%x", config);
+ ret = s32_regmap_read(pctldev, pin_id, &config);
+ if (ret)
+ return;
+
+ seq_printf(s, "0x%x", config);
}

static void s32_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
@@ -710,7 +715,7 @@ int s32_pinctrl_resume(struct device *dev)
}
#endif

-static void s32_pinctrl_parse_groups(struct device_node *np,
+static int s32_pinctrl_parse_groups(struct device_node *np,
struct s32_pin_group *grp,
struct s32_pinctrl_soc_info *info)
{
@@ -722,21 +727,20 @@ static void s32_pinctrl_parse_groups(struct device_node *np,

dev = info->dev;

- dev_dbg(dev, "group: %s\n", np->name);
+ dev_dbg(dev, "group: %pOFn\n", np);

/* Initialise group */
grp->name = np->name;

npins = of_property_count_elems_of_size(np, "pinmux", sizeof(u32));
-
if (npins < 0) {
dev_err(dev, "Failed to read 'pinmux' property in node %s.\n",
- np->name);
- return;
+ grp->name);
+ return -EINVAL;
}
if (!npins) {
- dev_err(dev, "The group %s has no pins.\n", np->name);
- return;
+ dev_err(dev, "The group %s has no pins.\n", grp->name);
+ return -EINVAL;
}

grp->npins = npins;
@@ -745,12 +749,8 @@ static void s32_pinctrl_parse_groups(struct device_node *np,
sizeof(unsigned int), GFP_KERNEL);
grp->pin_sss = devm_kcalloc(info->dev, grp->npins,
sizeof(unsigned int), GFP_KERNEL);
-
- if (!grp->pin_ids || !grp->pin_sss) {
- dev_err(dev, "Failed to allocate memory for the group %s.\n",
- np->name);
- return;
- }
+ if (!grp->pin_ids || !grp->pin_sss)
+ return -ENOMEM;

i = 0;
of_property_for_each_u32(np, "pinmux", prop, p, pinmux) {
@@ -761,9 +761,11 @@ static void s32_pinctrl_parse_groups(struct device_node *np,
grp->pin_ids[i], grp->pin_sss[i]);
i++;
}
+
+ return 0;
}

-static void s32_pinctrl_parse_functions(struct device_node *np,
+static int s32_pinctrl_parse_functions(struct device_node *np,
struct s32_pinctrl_soc_info *info,
u32 index)
{
@@ -771,8 +773,9 @@ static void s32_pinctrl_parse_functions(struct device_node *np,
struct s32_pmx_func *func;
struct s32_pin_group *grp;
u32 i = 0;
+ int ret = 0;

- dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name);
+ dev_dbg(info->dev, "parse function(%u): %pOFn\n", index, np);

func = &info->functions[index];

@@ -780,18 +783,24 @@ static void s32_pinctrl_parse_functions(struct device_node *np,
func->name = np->name;
func->num_groups = of_get_child_count(np);
if (func->num_groups == 0) {
- dev_err(info->dev, "no groups defined in %s\n", np->full_name);
- return;
+ dev_err(info->dev, "no groups defined in %pOF\n", np);
+ return -EINVAL;
}
- func->groups = devm_kzalloc(info->dev,
- func->num_groups * sizeof(char *), GFP_KERNEL);
+ func->groups = devm_kcalloc(info->dev, func->num_groups,
+ sizeof(*func->groups), GFP_KERNEL);
+ if (!func->groups)
+ return -ENOMEM;

for_each_child_of_node(np, child) {
func->groups[i] = child->name;
grp = &info->groups[info->grp_index++];
- s32_pinctrl_parse_groups(child, grp, info);
+ ret = s32_pinctrl_parse_groups(child, grp, info);
+ if (ret)
+ return ret;
i++;
}
+
+ return 0;
}

static int s32_pinctrl_probe_dt(struct platform_device *pdev,
@@ -804,6 +813,7 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
struct regmap *map;
void __iomem *base;
int mem_regions = info->mem_regions;
+ int ret;
u32 nfuncs = 0;
u32 i = 0;

@@ -815,13 +825,12 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
return -EINVAL;
}

- ipctl->regions = devm_kzalloc(&pdev->dev,
- mem_regions * sizeof(*(ipctl->regions)),
- GFP_KERNEL);
+ ipctl->regions = devm_kcalloc(&pdev->dev, mem_regions,
+ sizeof(*ipctl->regions), GFP_KERNEL);
if (!ipctl->regions)
return -ENOMEM;

- for (i = 0; i < mem_regions; ++i) {
+ for (i = 0; i < mem_regions; i++) {
base = devm_platform_get_and_ioremap_resource(pdev, i, &res);
if (IS_ERR(base))
return PTR_ERR(base);
@@ -851,24 +860,26 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
}

info->nfunctions = nfuncs;
- info->functions = devm_kzalloc(&pdev->dev,
- nfuncs * sizeof(struct s32_pmx_func),
- GFP_KERNEL);
+ info->functions = devm_kcalloc(&pdev->dev, nfuncs,
+ sizeof(*info->functions), GFP_KERNEL);
if (!info->functions)
return -ENOMEM;

info->ngroups = 0;
for_each_child_of_node(np, child)
info->ngroups += of_get_child_count(child);
- info->groups = devm_kzalloc(&pdev->dev,
- info->ngroups * sizeof(struct s32_pin_group),
- GFP_KERNEL);
+
+ info->groups = devm_kcalloc(&pdev->dev, info->ngroups,
+ sizeof(*info->groups), GFP_KERNEL);
if (!info->groups)
return -ENOMEM;

i = 0;
- for_each_child_of_node(np, child)
- s32_pinctrl_parse_functions(child, info, i++);
+ for_each_child_of_node(np, child) {
+ ret = s32_pinctrl_parse_functions(child, info, i++);
+ if (ret)
+ return ret;
+ }

return 0;
}
@@ -923,11 +934,9 @@ int s32_pinctrl_probe(struct platform_device *pdev,

ipctl->pctl = devm_pinctrl_register(&pdev->dev, s32_pinctrl_desc,
ipctl);
-
- if (IS_ERR(ipctl->pctl)) {
- dev_err(&pdev->dev, "could not register s32 pinctrl driver\n");
- return PTR_ERR(ipctl->pctl);
- }
+ if (IS_ERR(ipctl->pctl))
+ return dev_err_probe(&pdev->dev, PTR_ERR(ipctl->pctl),
+ "could not register s32 pinctrl driver\n");

#ifdef CONFIG_PM_SLEEP
saved_context = &ipctl->saved_context;
diff --git a/drivers/pinctrl/nxp/pinctrl-s32g2.c b/drivers/pinctrl/nxp/pinctrl-s32g2.c
index 5028f4adc389..d9f3ff6794ea 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32g2.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32g2.c
@@ -757,14 +757,12 @@ static const struct dev_pm_ops s32g_pinctrl_pm_ops = {
static struct platform_driver s32g_pinctrl_driver = {
.driver = {
.name = "s32g-siul2-pinctrl",
- .owner = THIS_MODULE,
.of_match_table = s32_pinctrl_of_match,
- .pm = &s32g_pinctrl_pm_ops,
+ .pm = pm_sleep_ptr(&s32g_pinctrl_pm_ops),
.suppress_bind_attrs = true,
},
.probe = s32g_pinctrl_probe,
};
-
builtin_platform_driver(s32g_pinctrl_driver);

MODULE_AUTHOR("Matthew Nunez <[email protected]>");
--
2.37.3

2023-03-27 06:30:37

by Chester Lin

[permalink] [raw]
Subject: [PATCH v5 3/5] pinctrl: s32cc: embed generic struct pingroup

Use generic data structure to describe pin control groups in S32 SoC family
and drop duplicated struct members.

Suggested-by: Andy Shevchenko <[email protected]>
Signed-off-by: Chester Lin <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
---
(No change since v3)

drivers/pinctrl/nxp/pinctrl-s32.h | 12 ++----
drivers/pinctrl/nxp/pinctrl-s32cc.c | 57 +++++++++++++++--------------
2 files changed, 33 insertions(+), 36 deletions(-)

diff --git a/drivers/pinctrl/nxp/pinctrl-s32.h b/drivers/pinctrl/nxp/pinctrl-s32.h
index 545bf16b988d..850cd668f406 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32.h
+++ b/drivers/pinctrl/nxp/pinctrl-s32.h
@@ -15,16 +15,12 @@ struct platform_device;

/**
* struct s32_pin_group - describes an S32 pin group
- * @name: the name of this specific pin group
- * @npins: the number of pins in this group array, i.e. the number of
- * elements in pin_ids and pin_sss so we can iterate over that array
- * @pin_ids: an array of pin IDs in this group
- * @pin_sss: an array of source signal select configs paired with pin_ids
+ * @data: generic data describes group name, number of pins, and a pin array in
+ this group.
+ * @pin_sss: an array of source signal select configs paired with pin array.
*/
struct s32_pin_group {
- const char *name;
- unsigned int npins;
- unsigned int *pin_ids;
+ struct pingroup data;
unsigned int *pin_sss;
};

diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
index 36f323f87785..e65c88162d7f 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
@@ -188,7 +188,7 @@ static const char *s32_get_group_name(struct pinctrl_dev *pctldev,
struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32_pinctrl_soc_info *info = ipctl->info;

- return info->groups[selector].name;
+ return info->groups[selector].data.name;
}

static int s32_get_group_pins(struct pinctrl_dev *pctldev,
@@ -198,8 +198,8 @@ static int s32_get_group_pins(struct pinctrl_dev *pctldev,
struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32_pinctrl_soc_info *info = ipctl->info;

- *pins = info->groups[selector].pin_ids;
- *npins = info->groups[selector].npins;
+ *pins = info->groups[selector].data.pins;
+ *npins = info->groups[selector].data.npins;

return 0;
}
@@ -314,23 +314,23 @@ static int s32_pmx_set(struct pinctrl_dev *pctldev, unsigned int selector,
grp = &info->groups[group];

dev_dbg(ipctl->dev, "set mux for function %s group %s\n",
- info->functions[selector].name, grp->name);
+ info->functions[selector].name, grp->data.name);

/* Check beforehand so we don't have a partial config. */
- for (i = 0; i < grp->npins; i++) {
- if (s32_check_pin(pctldev, grp->pin_ids[i]) != 0) {
+ for (i = 0; i < grp->data.npins; i++) {
+ if (s32_check_pin(pctldev, grp->data.pins[i]) != 0) {
dev_err(info->dev, "invalid pin: %u in group: %u\n",
- grp->pin_ids[i], group);
+ grp->data.pins[i], group);
return -EINVAL;
}
}

- for (i = 0, ret = 0; i < grp->npins && !ret; i++) {
- ret = s32_regmap_update(pctldev, grp->pin_ids[i],
+ for (i = 0, ret = 0; i < grp->data.npins && !ret; i++) {
+ ret = s32_regmap_update(pctldev, grp->data.pins[i],
S32_MSCR_SSS_MASK, grp->pin_sss[i]);
if (ret) {
dev_err(info->dev, "Failed to set pin %u\n",
- grp->pin_ids[i]);
+ grp->data.pins[i]);
return ret;
}
}
@@ -606,8 +606,8 @@ static int s32_pconf_group_set(struct pinctrl_dev *pctldev, unsigned int selecto
int i, ret;

grp = &info->groups[selector];
- for (i = 0; i < grp->npins; i++) {
- ret = s32_pinconf_mscr_update(pctldev, grp->pin_ids[i],
+ for (i = 0; i < grp->data.npins; i++) {
+ ret = s32_pinconf_mscr_update(pctldev, grp->data.pins[i],
configs, num_configs);
if (ret)
return ret;
@@ -641,9 +641,9 @@ static void s32_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,

seq_puts(s, "\n");
grp = &info->groups[selector];
- for (i = 0; i < grp->npins; i++) {
- name = pin_get_name(pctldev, grp->pin_ids[i]);
- ret = s32_regmap_read(pctldev, grp->pin_ids[i], &config);
+ for (i = 0; i < grp->data.npins; i++) {
+ name = pin_get_name(pctldev, grp->data.pins[i]);
+ ret = s32_regmap_read(pctldev, grp->data.pins[i], &config);
if (ret)
return;
seq_printf(s, "%s: 0x%x\n", name, config);
@@ -736,6 +736,7 @@ static int s32_pinctrl_parse_groups(struct device_node *np,
const __be32 *p;
struct device *dev;
struct property *prop;
+ unsigned int *pins, *sss;
int i, npins;
u32 pinmux;

@@ -744,38 +745,38 @@ static int s32_pinctrl_parse_groups(struct device_node *np,
dev_dbg(dev, "group: %pOFn\n", np);

/* Initialise group */
- grp->name = np->name;
+ grp->data.name = np->name;

npins = of_property_count_elems_of_size(np, "pinmux", sizeof(u32));
if (npins < 0) {
dev_err(dev, "Failed to read 'pinmux' property in node %s.\n",
- grp->name);
+ grp->data.name);
return -EINVAL;
}
if (!npins) {
- dev_err(dev, "The group %s has no pins.\n", grp->name);
+ dev_err(dev, "The group %s has no pins.\n", grp->data.name);
return -EINVAL;
}

- grp->npins = npins;
+ grp->data.npins = npins;

- grp->pin_ids = devm_kcalloc(info->dev, grp->npins,
- sizeof(unsigned int), GFP_KERNEL);
- grp->pin_sss = devm_kcalloc(info->dev, grp->npins,
- sizeof(unsigned int), GFP_KERNEL);
- if (!grp->pin_ids || !grp->pin_sss)
+ pins = devm_kcalloc(info->dev, npins, sizeof(*pins), GFP_KERNEL);
+ sss = devm_kcalloc(info->dev, npins, sizeof(*sss), GFP_KERNEL);
+ if (!pins || !sss)
return -ENOMEM;

i = 0;
of_property_for_each_u32(np, "pinmux", prop, p, pinmux) {
- grp->pin_ids[i] = get_pin_no(pinmux);
- grp->pin_sss[i] = get_pin_func(pinmux);
+ pins[i] = get_pin_no(pinmux);
+ sss[i] = get_pin_func(pinmux);

- dev_dbg(info->dev, "pin-id: 0x%x, sss: 0x%x",
- grp->pin_ids[i], grp->pin_sss[i]);
+ dev_dbg(info->dev, "pin: 0x%x, sss: 0x%x", pins[i], sss[i]);
i++;
}

+ grp->data.pins = pins;
+ grp->pin_sss = sss;
+
return 0;
}

--
2.37.3

2023-03-27 06:30:44

by Chester Lin

[permalink] [raw]
Subject: [PATCH v5 2/5] pinctrl: s32cc: refactor pin config parsing

Move common codes into smaller inline functions and remove argument checks
that are not actually used by pull up/down bits in the S32 MSCR register.

Signed-off-by: Chester Lin <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
---
(No change since v3)

drivers/pinctrl/nxp/pinctrl-s32cc.c | 52 ++++++++++++++++++-----------
1 file changed, 33 insertions(+), 19 deletions(-)

diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
index f698e1a240ef..36f323f87785 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
@@ -474,11 +474,38 @@ static int s32_get_slew_regval(int arg)
return -EINVAL;
}

-static int s32_get_pin_conf(enum pin_config_param param, u32 arg,
- unsigned int *mask, unsigned int *config)
+static inline void s32_pin_set_pull(enum pin_config_param param,
+ unsigned int *mask, unsigned int *config)
{
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+ *config &= ~(S32_MSCR_PUS | S32_MSCR_PUE);
+ break;
+ case PIN_CONFIG_BIAS_PULL_UP:
+ *config |= S32_MSCR_PUS | S32_MSCR_PUE;
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ *config &= ~S32_MSCR_PUS;
+ *config |= S32_MSCR_PUE;
+ break;
+ default:
+ return;
+ }
+
+ *mask |= S32_MSCR_PUS | S32_MSCR_PUE;
+}
+
+static int s32_parse_pincfg(unsigned long pincfg, unsigned int *mask,
+ unsigned int *config)
+{
+ enum pin_config_param param;
+ u32 arg;
int ret;

+ param = pinconf_to_config_param(pincfg);
+ arg = pinconf_to_config_argument(pincfg);
+
switch (param) {
/* All pins are persistent over suspend */
case PIN_CONFIG_PERSIST_STATE:
@@ -508,26 +535,15 @@ static int s32_get_pin_conf(enum pin_config_param param, u32 arg,
*config |= S32_MSCR_SRE((u32)ret);
*mask |= S32_MSCR_SRE(~0);
break;
+ case PIN_CONFIG_BIAS_DISABLE:
case PIN_CONFIG_BIAS_PULL_UP:
- if (arg)
- *config |= S32_MSCR_PUS;
- else
- *config &= ~S32_MSCR_PUS;
- fallthrough;
case PIN_CONFIG_BIAS_PULL_DOWN:
- if (arg)
- *config |= S32_MSCR_PUE;
- else
- *config &= ~S32_MSCR_PUE;
- *mask |= S32_MSCR_PUE | S32_MSCR_PUS;
+ s32_pin_set_pull(param, mask, config);
break;
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
*config &= ~(S32_MSCR_ODE | S32_MSCR_OBE | S32_MSCR_IBE);
*mask |= S32_MSCR_ODE | S32_MSCR_OBE | S32_MSCR_IBE;
- fallthrough;
- case PIN_CONFIG_BIAS_DISABLE:
- *config &= ~(S32_MSCR_PUS | S32_MSCR_PUE);
- *mask |= S32_MSCR_PUS | S32_MSCR_PUE;
+ s32_pin_set_pull(param, mask, config);
break;
default:
return -EOPNOTSUPP;
@@ -553,9 +569,7 @@ static int s32_pinconf_mscr_update(struct pinctrl_dev *pctldev,
pin_get_name(pctldev, pin_id), num_configs);

for (i = 0; i < num_configs; i++) {
- ret = s32_get_pin_conf(pinconf_to_config_param(configs[i]),
- pinconf_to_config_argument(configs[i]),
- &mask, &config);
+ ret = s32_parse_pincfg(configs[i], &mask, &config);
if (ret)
return ret;
}
--
2.37.3

2023-03-27 06:30:47

by Chester Lin

[permalink] [raw]
Subject: [PATCH v5 4/5] pinctrl: s32cc: Use generic struct data to describe pin function

Replace struct s32_pmx_func with generic struct pinfunction since they
have the same data fields.

Suggested-by: Andy Shevchenko <[email protected]>
Signed-off-by: Chester Lin <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
---
(No change since v3)

drivers/pinctrl/nxp/pinctrl-s32.h | 14 +-------------
drivers/pinctrl/nxp/pinctrl-s32cc.c | 18 +++++++++++-------
2 files changed, 12 insertions(+), 20 deletions(-)

diff --git a/drivers/pinctrl/nxp/pinctrl-s32.h b/drivers/pinctrl/nxp/pinctrl-s32.h
index 850cd668f406..2f7aecd462e4 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32.h
+++ b/drivers/pinctrl/nxp/pinctrl-s32.h
@@ -24,18 +24,6 @@ struct s32_pin_group {
unsigned int *pin_sss;
};

-/**
- * struct s32_pmx_func - describes S32 pinmux functions
- * @name: the name of this specific function
- * @groups: corresponding pin groups
- * @num_groups: the number of groups
- */
-struct s32_pmx_func {
- const char *name;
- const char **groups;
- unsigned int num_groups;
-};
-
/**
* struct s32_pin_range - pin ID range for each memory region.
* @start: start pin ID
@@ -52,7 +40,7 @@ struct s32_pinctrl_soc_info {
unsigned int npins;
struct s32_pin_group *groups;
unsigned int ngroups;
- struct s32_pmx_func *functions;
+ struct pinfunction *functions;
unsigned int nfunctions;
unsigned int grp_index;
const struct s32_pin_range *mem_pin_ranges;
diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
index e65c88162d7f..8373468719b6 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
@@ -364,7 +364,7 @@ static int s32_pmx_get_groups(struct pinctrl_dev *pctldev,
const struct s32_pinctrl_soc_info *info = ipctl->info;

*groups = info->functions[selector].groups;
- *num_groups = info->functions[selector].num_groups;
+ *num_groups = info->functions[selector].ngroups;

return 0;
}
@@ -785,8 +785,9 @@ static int s32_pinctrl_parse_functions(struct device_node *np,
u32 index)
{
struct device_node *child;
- struct s32_pmx_func *func;
+ struct pinfunction *func;
struct s32_pin_group *grp;
+ const char **groups;
u32 i = 0;
int ret = 0;

@@ -796,18 +797,19 @@ static int s32_pinctrl_parse_functions(struct device_node *np,

/* Initialise function */
func->name = np->name;
- func->num_groups = of_get_child_count(np);
- if (func->num_groups == 0) {
+ func->ngroups = of_get_child_count(np);
+ if (func->ngroups == 0) {
dev_err(info->dev, "no groups defined in %pOF\n", np);
return -EINVAL;
}
- func->groups = devm_kcalloc(info->dev, func->num_groups,
+
+ groups = devm_kcalloc(info->dev, func->ngroups,
sizeof(*func->groups), GFP_KERNEL);
- if (!func->groups)
+ if (!groups)
return -ENOMEM;

for_each_child_of_node(np, child) {
- func->groups[i] = child->name;
+ groups[i] = child->name;
grp = &info->groups[info->grp_index++];
ret = s32_pinctrl_parse_groups(child, grp, info);
if (ret)
@@ -815,6 +817,8 @@ static int s32_pinctrl_parse_functions(struct device_node *np,
i++;
}

+ func->groups = groups;
+
return 0;
}

--
2.37.3

2023-03-27 06:31:38

by Chester Lin

[permalink] [raw]
Subject: [PATCH v5 5/5] pinctrl: s32: separate const device data from struct s32_pinctrl_soc_info

The .data field in struct of_device_id is used as a const member so it's
inappropriate to attach struct s32_pinctrl_soc_info with of_device_id
because some members in s32_pinctrl_soc_info need to be filled by
pinctrl-s32cc at runtime.

For this reason, struct s32_pinctrl_soc_info must be allocated in
pinctrl-s32cc and then create a new struct s32_pinctrl_soc_data in order
to represent const .data in of_device_id. To combine these two structures,
a s32_pinctrl_soc_data pointer is introduced in s32_pinctrl_soc_info.

Besides, use of_device_get_match_data() instead of of_match_device() since
the driver only needs to retrieve the .data from of_device_id.

Suggested-by: Andy Shevchenko <[email protected]>
Signed-off-by: Chester Lin <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
---
Changes in v5:
- Remove unnecessary (void *) type casting found in pinctrl-s32g2.

Changes in v4:
- Retrieve the matched device data by calling of_device_get_match_data()
and remove unnecessary type casting. (Merged from the previous v3 series
[PATCH v3 1/6])

drivers/pinctrl/nxp/pinctrl-s32.h | 14 +++++++++-----
drivers/pinctrl/nxp/pinctrl-s32cc.c | 30 +++++++++++++++++------------
drivers/pinctrl/nxp/pinctrl-s32g2.c | 14 +++++---------
3 files changed, 32 insertions(+), 26 deletions(-)

diff --git a/drivers/pinctrl/nxp/pinctrl-s32.h b/drivers/pinctrl/nxp/pinctrl-s32.h
index 2f7aecd462e4..add3c77ddfed 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32.h
+++ b/drivers/pinctrl/nxp/pinctrl-s32.h
@@ -34,24 +34,28 @@ struct s32_pin_range {
unsigned int end;
};

-struct s32_pinctrl_soc_info {
- struct device *dev;
+struct s32_pinctrl_soc_data {
const struct pinctrl_pin_desc *pins;
unsigned int npins;
+ const struct s32_pin_range *mem_pin_ranges;
+ unsigned int mem_regions;
+};
+
+struct s32_pinctrl_soc_info {
+ struct device *dev;
+ const struct s32_pinctrl_soc_data *soc_data;
struct s32_pin_group *groups;
unsigned int ngroups;
struct pinfunction *functions;
unsigned int nfunctions;
unsigned int grp_index;
- const struct s32_pin_range *mem_pin_ranges;
- unsigned int mem_regions;
};

#define S32_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
#define S32_PIN_RANGE(_start, _end) { .start = _start, .end = _end }

int s32_pinctrl_probe(struct platform_device *pdev,
- struct s32_pinctrl_soc_info *info);
+ const struct s32_pinctrl_soc_data *soc_data);
int s32_pinctrl_resume(struct device *dev);
int s32_pinctrl_suspend(struct device *dev);
#endif /* __DRIVERS_PINCTRL_S32_H */
diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
index 8373468719b6..41e024160f36 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
@@ -106,7 +106,7 @@ s32_get_region(struct pinctrl_dev *pctldev, unsigned int pin)
{
struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32_pin_range *pin_range;
- unsigned int mem_regions = ipctl->info->mem_regions;
+ unsigned int mem_regions = ipctl->info->soc_data->mem_regions;
unsigned int i;

for (i = 0; i < mem_regions; i++) {
@@ -688,8 +688,8 @@ int s32_pinctrl_suspend(struct device *dev)
int ret;
unsigned int config;

- for (i = 0; i < info->npins; i++) {
- pin = &info->pins[i];
+ for (i = 0; i < info->soc_data->npins; i++) {
+ pin = &info->soc_data->pins[i];

if (!s32_pinctrl_should_save(ipctl, pin->number))
continue;
@@ -713,8 +713,8 @@ int s32_pinctrl_resume(struct device *dev)
struct s32_pinctrl_context *saved_context = &ipctl->saved_context;
int ret, i;

- for (i = 0; i < info->npins; i++) {
- pin = &info->pins[i];
+ for (i = 0; i < info->soc_data->npins; i++) {
+ pin = &info->soc_data->pins[i];

if (!s32_pinctrl_should_save(ipctl, pin->number))
continue;
@@ -831,7 +831,7 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
struct resource *res;
struct regmap *map;
void __iomem *base;
- int mem_regions = info->mem_regions;
+ unsigned int mem_regions = info->soc_data->mem_regions;
int ret;
u32 nfuncs = 0;
u32 i = 0;
@@ -869,7 +869,7 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
}

ipctl->regions[i].map = map;
- ipctl->regions[i].pin_range = &info->mem_pin_ranges[i];
+ ipctl->regions[i].pin_range = &info->soc_data->mem_pin_ranges[i];
}

nfuncs = of_get_child_count(np);
@@ -904,20 +904,26 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
}

int s32_pinctrl_probe(struct platform_device *pdev,
- struct s32_pinctrl_soc_info *info)
+ const struct s32_pinctrl_soc_data *soc_data)
{
struct s32_pinctrl *ipctl;
int ret;
struct pinctrl_desc *s32_pinctrl_desc;
+ struct s32_pinctrl_soc_info *info;
#ifdef CONFIG_PM_SLEEP
struct s32_pinctrl_context *saved_context;
#endif

- if (!info || !info->pins || !info->npins) {
+ if (!soc_data || !soc_data->pins || !soc_data->npins) {
dev_err(&pdev->dev, "wrong pinctrl info\n");
return -EINVAL;
}

+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->soc_data = soc_data;
info->dev = &pdev->dev;

/* Create state holders etc for this driver */
@@ -938,8 +944,8 @@ int s32_pinctrl_probe(struct platform_device *pdev,
return -ENOMEM;

s32_pinctrl_desc->name = dev_name(&pdev->dev);
- s32_pinctrl_desc->pins = info->pins;
- s32_pinctrl_desc->npins = info->npins;
+ s32_pinctrl_desc->pins = info->soc_data->pins;
+ s32_pinctrl_desc->npins = info->soc_data->npins;
s32_pinctrl_desc->pctlops = &s32_pctrl_ops;
s32_pinctrl_desc->pmxops = &s32_pmx_ops;
s32_pinctrl_desc->confops = &s32_pinconf_ops;
@@ -960,7 +966,7 @@ int s32_pinctrl_probe(struct platform_device *pdev,
#ifdef CONFIG_PM_SLEEP
saved_context = &ipctl->saved_context;
saved_context->pads =
- devm_kcalloc(&pdev->dev, info->npins,
+ devm_kcalloc(&pdev->dev, info->soc_data->npins,
sizeof(*saved_context->pads),
GFP_KERNEL);
if (!saved_context->pads)
diff --git a/drivers/pinctrl/nxp/pinctrl-s32g2.c b/drivers/pinctrl/nxp/pinctrl-s32g2.c
index d9f3ff6794ea..4d01e9a2a23e 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32g2.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32g2.c
@@ -721,7 +721,7 @@ static const struct s32_pin_range s32_pin_ranges_siul2[] = {
S32_PIN_RANGE(942, 1007),
};

-static struct s32_pinctrl_soc_info s32_pinctrl_info = {
+static struct s32_pinctrl_soc_data s32_pinctrl_data = {
.pins = s32_pinctrl_pads_siul2,
.npins = ARRAY_SIZE(s32_pinctrl_pads_siul2),
.mem_pin_ranges = s32_pin_ranges_siul2,
@@ -730,9 +730,8 @@ static struct s32_pinctrl_soc_info s32_pinctrl_info = {

static const struct of_device_id s32_pinctrl_of_match[] = {
{
-
.compatible = "nxp,s32g2-siul2-pinctrl",
- .data = (void *) &s32_pinctrl_info,
+ .data = &s32_pinctrl_data,
},
{ /* sentinel */ }
};
@@ -740,14 +739,11 @@ MODULE_DEVICE_TABLE(of, s32_pinctrl_of_match);

static int s32g_pinctrl_probe(struct platform_device *pdev)
{
- const struct of_device_id *of_id =
- of_match_device(s32_pinctrl_of_match, &pdev->dev);
+ const struct s32_pinctrl_soc_data *soc_data;

- if (!of_id)
- return -ENODEV;
+ soc_data = of_device_get_match_data(&pdev->dev);

- return s32_pinctrl_probe
- (pdev, (struct s32_pinctrl_soc_info *) of_id->data);
+ return s32_pinctrl_probe(pdev, soc_data);
}

static const struct dev_pm_ops s32g_pinctrl_pm_ops = {
--
2.37.3

2023-03-27 12:02:33

by Andy Shevchenko

[permalink] [raw]
Subject: Re: [PATCH v5 5/5] pinctrl: s32: separate const device data from struct s32_pinctrl_soc_info

On Mon, Mar 27, 2023 at 9:28 AM Chester Lin <[email protected]> wrote:
>
> The .data field in struct of_device_id is used as a const member so it's
> inappropriate to attach struct s32_pinctrl_soc_info with of_device_id
> because some members in s32_pinctrl_soc_info need to be filled by
> pinctrl-s32cc at runtime.
>
> For this reason, struct s32_pinctrl_soc_info must be allocated in
> pinctrl-s32cc and then create a new struct s32_pinctrl_soc_data in order
> to represent const .data in of_device_id. To combine these two structures,
> a s32_pinctrl_soc_data pointer is introduced in s32_pinctrl_soc_info.
>
> Besides, use of_device_get_match_data() instead of of_match_device() since
> the driver only needs to retrieve the .data from of_device_id.

...

> -static struct s32_pinctrl_soc_info s32_pinctrl_info = {
> +static struct s32_pinctrl_soc_data s32_pinctrl_data = {

I'm wondering why it's not const.

But don't resend too quickly, let's wait for Linus to comment on this
and other stuff. It might be that he can amend this when applying.

...

> + const struct s32_pinctrl_soc_data *soc_data;
>
> + soc_data = of_device_get_match_data(&pdev->dev);

--
With Best Regards,
Andy Shevchenko

2023-03-27 21:38:36

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH v5 1/5] pinctrl: s32: refine error/return/config checks and simplify driver codes

On Mon, Mar 27, 2023 at 8:28 AM Chester Lin <[email protected]> wrote:

> Improve error/return code handlings and config checks in order to have
> better reliability and simplify driver codes such as removing/changing
> improper macros, blanks, print formats and helper calls.
>
> Signed-off-by: Chester Lin <[email protected]>
> Reviewed-by: Andy Shevchenko <[email protected]>

Patch applied!

Yours,
Linus Walleij

2023-03-27 21:39:54

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH v5 2/5] pinctrl: s32cc: refactor pin config parsing

On Mon, Mar 27, 2023 at 8:28 AM Chester Lin <[email protected]> wrote:

> Move common codes into smaller inline functions and remove argument checks
> that are not actually used by pull up/down bits in the S32 MSCR register.
>
> Signed-off-by: Chester Lin <[email protected]>
> Reviewed-by: Andy Shevchenko <[email protected]>

Patch applied!

Yours,
Linus Walleij

2023-03-27 21:40:50

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH v5 3/5] pinctrl: s32cc: embed generic struct pingroup

On Mon, Mar 27, 2023 at 8:28 AM Chester Lin <[email protected]> wrote:

> Use generic data structure to describe pin control groups in S32 SoC family
> and drop duplicated struct members.
>
> Suggested-by: Andy Shevchenko <[email protected]>
> Signed-off-by: Chester Lin <[email protected]>
> Reviewed-by: Andy Shevchenko <[email protected]>

Patch applied!

Yours,
Linus Walleij

2023-03-27 21:45:59

by Linus Walleij

[permalink] [raw]
Subject: Re: [PATCH v5 5/5] pinctrl: s32: separate const device data from struct s32_pinctrl_soc_info

On Mon, Mar 27, 2023 at 1:59 PM Andy Shevchenko
<[email protected]> wrote:
> On Mon, Mar 27, 2023 at 9:28 AM Chester Lin <[email protected]> wrote:
> >
> > The .data field in struct of_device_id is used as a const member so it's
> > inappropriate to attach struct s32_pinctrl_soc_info with of_device_id
> > because some members in s32_pinctrl_soc_info need to be filled by
> > pinctrl-s32cc at runtime.
> >
> > For this reason, struct s32_pinctrl_soc_info must be allocated in
> > pinctrl-s32cc and then create a new struct s32_pinctrl_soc_data in order
> > to represent const .data in of_device_id. To combine these two structures,
> > a s32_pinctrl_soc_data pointer is introduced in s32_pinctrl_soc_info.
> >
> > Besides, use of_device_get_match_data() instead of of_match_device() since
> > the driver only needs to retrieve the .data from of_device_id.
>
> ...
>
> > -static struct s32_pinctrl_soc_info s32_pinctrl_info = {
> > +static struct s32_pinctrl_soc_data s32_pinctrl_data = {
>
> I'm wondering why it's not const.
>
> But don't resend too quickly, let's wait for Linus to comment on this
> and other stuff. It might be that he can amend this when applying.

I don't dare to add const here given the compiler warnings it
can easily spawn.

Chester can you investigate if these can be static const?

You would only need to resend this patch 5/5 because I applied
all the others to lower your patch stack.

Thanks for fixing!
Yours,
Linus Walleij

2023-03-29 04:30:04

by Chester Lin

[permalink] [raw]
Subject: [RESEND PATCH v5 5/5] pinctrl: s32: separate const device data from struct s32_pinctrl_soc_info

The .data field in struct of_device_id is used as a const member so it's
inappropriate to attach struct s32_pinctrl_soc_info with of_device_id
because some members in s32_pinctrl_soc_info need to be filled by
pinctrl-s32cc at runtime.

For this reason, struct s32_pinctrl_soc_info must be allocated in
pinctrl-s32cc and then create a new struct s32_pinctrl_soc_data in order
to represent const .data in of_device_id. To combine these two structures,
a s32_pinctrl_soc_data pointer is introduced in s32_pinctrl_soc_info.

Besides, use of_device_get_match_data() instead of of_match_device() since
the driver only needs to retrieve the .data from of_device_id.

Suggested-by: Andy Shevchenko <[email protected]>
Signed-off-by: Chester Lin <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
---
(This is a patch revised from the previous [PATCH v5 5/5], Message-ID:
<[email protected]>)

Changes in v5:
- Remove unnecessary (void *) type casting found in pinctrl-s32g2.
- [NEW] Add the const qualifier on the s32_pinctrl_data.

drivers/pinctrl/nxp/pinctrl-s32.h | 14 +++++++++-----
drivers/pinctrl/nxp/pinctrl-s32cc.c | 30 +++++++++++++++++------------
drivers/pinctrl/nxp/pinctrl-s32g2.c | 14 +++++---------
3 files changed, 32 insertions(+), 26 deletions(-)

diff --git a/drivers/pinctrl/nxp/pinctrl-s32.h b/drivers/pinctrl/nxp/pinctrl-s32.h
index 2f7aecd462e4..add3c77ddfed 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32.h
+++ b/drivers/pinctrl/nxp/pinctrl-s32.h
@@ -34,24 +34,28 @@ struct s32_pin_range {
unsigned int end;
};

-struct s32_pinctrl_soc_info {
- struct device *dev;
+struct s32_pinctrl_soc_data {
const struct pinctrl_pin_desc *pins;
unsigned int npins;
+ const struct s32_pin_range *mem_pin_ranges;
+ unsigned int mem_regions;
+};
+
+struct s32_pinctrl_soc_info {
+ struct device *dev;
+ const struct s32_pinctrl_soc_data *soc_data;
struct s32_pin_group *groups;
unsigned int ngroups;
struct pinfunction *functions;
unsigned int nfunctions;
unsigned int grp_index;
- const struct s32_pin_range *mem_pin_ranges;
- unsigned int mem_regions;
};

#define S32_PINCTRL_PIN(pin) PINCTRL_PIN(pin, #pin)
#define S32_PIN_RANGE(_start, _end) { .start = _start, .end = _end }

int s32_pinctrl_probe(struct platform_device *pdev,
- struct s32_pinctrl_soc_info *info);
+ const struct s32_pinctrl_soc_data *soc_data);
int s32_pinctrl_resume(struct device *dev);
int s32_pinctrl_suspend(struct device *dev);
#endif /* __DRIVERS_PINCTRL_S32_H */
diff --git a/drivers/pinctrl/nxp/pinctrl-s32cc.c b/drivers/pinctrl/nxp/pinctrl-s32cc.c
index 8373468719b6..41e024160f36 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32cc.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32cc.c
@@ -106,7 +106,7 @@ s32_get_region(struct pinctrl_dev *pctldev, unsigned int pin)
{
struct s32_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
const struct s32_pin_range *pin_range;
- unsigned int mem_regions = ipctl->info->mem_regions;
+ unsigned int mem_regions = ipctl->info->soc_data->mem_regions;
unsigned int i;

for (i = 0; i < mem_regions; i++) {
@@ -688,8 +688,8 @@ int s32_pinctrl_suspend(struct device *dev)
int ret;
unsigned int config;

- for (i = 0; i < info->npins; i++) {
- pin = &info->pins[i];
+ for (i = 0; i < info->soc_data->npins; i++) {
+ pin = &info->soc_data->pins[i];

if (!s32_pinctrl_should_save(ipctl, pin->number))
continue;
@@ -713,8 +713,8 @@ int s32_pinctrl_resume(struct device *dev)
struct s32_pinctrl_context *saved_context = &ipctl->saved_context;
int ret, i;

- for (i = 0; i < info->npins; i++) {
- pin = &info->pins[i];
+ for (i = 0; i < info->soc_data->npins; i++) {
+ pin = &info->soc_data->pins[i];

if (!s32_pinctrl_should_save(ipctl, pin->number))
continue;
@@ -831,7 +831,7 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
struct resource *res;
struct regmap *map;
void __iomem *base;
- int mem_regions = info->mem_regions;
+ unsigned int mem_regions = info->soc_data->mem_regions;
int ret;
u32 nfuncs = 0;
u32 i = 0;
@@ -869,7 +869,7 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
}

ipctl->regions[i].map = map;
- ipctl->regions[i].pin_range = &info->mem_pin_ranges[i];
+ ipctl->regions[i].pin_range = &info->soc_data->mem_pin_ranges[i];
}

nfuncs = of_get_child_count(np);
@@ -904,20 +904,26 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev,
}

int s32_pinctrl_probe(struct platform_device *pdev,
- struct s32_pinctrl_soc_info *info)
+ const struct s32_pinctrl_soc_data *soc_data)
{
struct s32_pinctrl *ipctl;
int ret;
struct pinctrl_desc *s32_pinctrl_desc;
+ struct s32_pinctrl_soc_info *info;
#ifdef CONFIG_PM_SLEEP
struct s32_pinctrl_context *saved_context;
#endif

- if (!info || !info->pins || !info->npins) {
+ if (!soc_data || !soc_data->pins || !soc_data->npins) {
dev_err(&pdev->dev, "wrong pinctrl info\n");
return -EINVAL;
}

+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->soc_data = soc_data;
info->dev = &pdev->dev;

/* Create state holders etc for this driver */
@@ -938,8 +944,8 @@ int s32_pinctrl_probe(struct platform_device *pdev,
return -ENOMEM;

s32_pinctrl_desc->name = dev_name(&pdev->dev);
- s32_pinctrl_desc->pins = info->pins;
- s32_pinctrl_desc->npins = info->npins;
+ s32_pinctrl_desc->pins = info->soc_data->pins;
+ s32_pinctrl_desc->npins = info->soc_data->npins;
s32_pinctrl_desc->pctlops = &s32_pctrl_ops;
s32_pinctrl_desc->pmxops = &s32_pmx_ops;
s32_pinctrl_desc->confops = &s32_pinconf_ops;
@@ -960,7 +966,7 @@ int s32_pinctrl_probe(struct platform_device *pdev,
#ifdef CONFIG_PM_SLEEP
saved_context = &ipctl->saved_context;
saved_context->pads =
- devm_kcalloc(&pdev->dev, info->npins,
+ devm_kcalloc(&pdev->dev, info->soc_data->npins,
sizeof(*saved_context->pads),
GFP_KERNEL);
if (!saved_context->pads)
diff --git a/drivers/pinctrl/nxp/pinctrl-s32g2.c b/drivers/pinctrl/nxp/pinctrl-s32g2.c
index d9f3ff6794ea..224a12ce70ed 100644
--- a/drivers/pinctrl/nxp/pinctrl-s32g2.c
+++ b/drivers/pinctrl/nxp/pinctrl-s32g2.c
@@ -721,7 +721,7 @@ static const struct s32_pin_range s32_pin_ranges_siul2[] = {
S32_PIN_RANGE(942, 1007),
};

-static struct s32_pinctrl_soc_info s32_pinctrl_info = {
+static const struct s32_pinctrl_soc_data s32_pinctrl_data = {
.pins = s32_pinctrl_pads_siul2,
.npins = ARRAY_SIZE(s32_pinctrl_pads_siul2),
.mem_pin_ranges = s32_pin_ranges_siul2,
@@ -730,9 +730,8 @@ static struct s32_pinctrl_soc_info s32_pinctrl_info = {

static const struct of_device_id s32_pinctrl_of_match[] = {
{
-
.compatible = "nxp,s32g2-siul2-pinctrl",
- .data = (void *) &s32_pinctrl_info,
+ .data = &s32_pinctrl_data,
},
{ /* sentinel */ }
};
@@ -740,14 +739,11 @@ MODULE_DEVICE_TABLE(of, s32_pinctrl_of_match);

static int s32g_pinctrl_probe(struct platform_device *pdev)
{
- const struct of_device_id *of_id =
- of_match_device(s32_pinctrl_of_match, &pdev->dev);
+ const struct s32_pinctrl_soc_data *soc_data;

- if (!of_id)
- return -ENODEV;
+ soc_data = of_device_get_match_data(&pdev->dev);

- return s32_pinctrl_probe
- (pdev, (struct s32_pinctrl_soc_info *) of_id->data);
+ return s32_pinctrl_probe(pdev, soc_data);
}

static const struct dev_pm_ops s32g_pinctrl_pm_ops = {
--
2.37.3

2023-03-29 04:36:42

by Chester Lin

[permalink] [raw]
Subject: Re: [PATCH v5 5/5] pinctrl: s32: separate const device data from struct s32_pinctrl_soc_info

Hi Linus and Andy,

On Mon, Mar 27, 2023 at 11:39:18PM +0200, Linus Walleij wrote:
> On Mon, Mar 27, 2023 at 1:59 PM Andy Shevchenko
> <[email protected]> wrote:
> > On Mon, Mar 27, 2023 at 9:28 AM Chester Lin <[email protected]> wrote:
> > >
> > > The .data field in struct of_device_id is used as a const member so it's
> > > inappropriate to attach struct s32_pinctrl_soc_info with of_device_id
> > > because some members in s32_pinctrl_soc_info need to be filled by
> > > pinctrl-s32cc at runtime.
> > >
> > > For this reason, struct s32_pinctrl_soc_info must be allocated in
> > > pinctrl-s32cc and then create a new struct s32_pinctrl_soc_data in order
> > > to represent const .data in of_device_id. To combine these two structures,
> > > a s32_pinctrl_soc_data pointer is introduced in s32_pinctrl_soc_info.
> > >
> > > Besides, use of_device_get_match_data() instead of of_match_device() since
> > > the driver only needs to retrieve the .data from of_device_id.
> >
> > ...
> >
> > > -static struct s32_pinctrl_soc_info s32_pinctrl_info = {
> > > +static struct s32_pinctrl_soc_data s32_pinctrl_data = {
> >
> > I'm wondering why it's not const.
> >
> > But don't resend too quickly, let's wait for Linus to comment on this
> > and other stuff. It might be that he can amend this when applying.
>
> I don't dare to add const here given the compiler warnings it
> can easily spawn.
>
> Chester can you investigate if these can be static const?
>
> You would only need to resend this patch 5/5 because I applied
> all the others to lower your patch stack.
>
> Thanks for fixing!
> Yours,
> Linus Walleij

Thanks for reviewing this patch and Andy's suggestion looks good to me. The
s32_pinctrl_data should be const as well since the 'data' pointer in
of_device_id is declared as const.

Anyway, I have resent a revised 5/5 under the same mail thread:
https://lore.kernel.org/all/[email protected]/T/#u

It can be compiled by the following two gcc versions without a warning on
drivers/pinctrl/nxp

- aarch64-native:
- gcc version 7.5.0 (SUSE Linux) <aarch64-native>

- cross-compilation on x86-64
- gcc version 13.0.1 20230127 (experimental) [revision ca8fb0096713a8477614ef874f16ba5bf16c48bc] (SUSE Linux)

Thanks!

Regards,
Chester