The of_property_for_each_u32() macro needs five parameters, two of which
are primarily meant as internal variables for the macro itself (in the
for() clause). Yet these two parameters are used by a few drivers, and this
can be considered misuse or at least bad practice.
Now that the kernel uses C11 to build, these two parameters can be avoided
by declaring them internally, thus changing this pattern:
struct property *prop;
const __be32 *p;
u32 val;
of_property_for_each_u32(np, "xyz", prop, p, val) { ... }
to this:
u32 val;
of_property_for_each_u32(np, "xyz", val) { ... }
However two variables cannot be declared in the for clause even with C11,
so declare one struct that contain the two variables we actually need. As
the variables inside this struct are not meant to be used by users of this
macro, give the struct instance the noticeable name "_it" so it is visible
during code reviews, helping to avoid new code to use it directly.
Most usages are trivially converted as they do not use those two
parameters, as expected. The non-trivial cases are:
- drivers/clk/clk.c, of_clk_get_parent_name(): easily doable anyway
- drivers/clk/clk-si5351.c, si5351_dt_parse(): this is more complex as the
checks had to be replicated in a different way, making code more verbose
and somewhat uglier, but I refrained from a full rework to keep as much
of the original code untouched having no hardware to test my changes
All the changes have been build tested. The few for which I have the
hardware have been runtime-tested too.
Reviewed-by: Andre Przywara <andre.przywara@arm.com> # drivers/clk/sunxi/clk-simple-gates.c, drivers/clk/sunxi/clk-sun8i-bus-gates.c
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> # drivers/gpio/gpio-brcmstb.c
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com> # drivers/irqchip/irq-atmel-aic-common.c
Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> # drivers/iio/adc/ti_am335x_adc.c
Acked-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com> # drivers/pwm/pwm-samsung.c
Acked-by: Richard Leitner <richard.leitner@linux.dev> # drivers/usb/misc/usb251xb.c
Acked-by: Mark Brown <broonie@kernel.org> # sound/soc/codecs/arizona.c
Reviewed-by: Richard Fitzgerald <rf@opensource.cirrus.com> # sound/soc/codecs/arizona.c
Acked-by: Michael Ellerman <mpe@ellerman.id.au> # arch/powerpc/sysdev/xive/spapr.c
Acked-by: Stephen Boyd <sboyd@kernel.org> # clk
Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Acked-by: Lee Jones <lee@kernel.org>
Link: https://lore.kernel.org/r/20240724-of_property_for_each_u32-v3-1-bea82ce429e2@bootlin.com
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
struct device_node *np;
struct resource r;
void __iomem *tima;
- struct property *prop;
u8 max_prio = 7;
- const __be32 *p;
u32 val, cpu;
s64 rc;
max_prio = val - 1;
/* Iterate the EQ sizes and pick one */
- of_property_for_each_u32(np, "ibm,xive-eq-sizes", prop, p, val) {
+ of_property_for_each_u32(np, "ibm,xive-eq-sizes", val) {
xive_queue_shift = val;
if (val == PAGE_SHIFT)
break;
struct device_node *np;
struct resource r;
void __iomem *tima;
- struct property *prop;
u8 max_prio;
u32 val;
u32 len;
}
/* Iterate the EQ sizes and pick one */
- of_property_for_each_u32(np, "ibm,xive-eq-sizes", prop, reg, val) {
+ of_property_for_each_u32(np, "ibm,xive-eq-sizes", val) {
xive_queue_shift = val;
if (val == PAGE_SHIFT)
break;
const char *name)
{
struct device_node *np = ddata->dev->of_node;
- struct property *prop;
- const __be32 *p;
u32 val;
- of_property_for_each_u32(np, name, prop, p, val) {
+ of_property_for_each_u32(np, name, val) {
if (val >= SYSC_NR_IDLEMODES) {
dev_err(ddata->dev, "invalid idlemode: %i\n", val);
return -EINVAL;
static int __set_clk_rates(struct device_node *node, bool clk_supplier)
{
struct of_phandle_args clkspec;
- struct property *prop;
- const __be32 *cur;
int rc, index = 0;
struct clk *clk;
u32 rate;
- of_property_for_each_u32(node, "assigned-clock-rates", prop, cur, rate) {
+ of_property_for_each_u32(node, "assigned-clock-rates", rate) {
if (rate) {
rc = of_parse_phandle_with_args(node, "assigned-clocks",
"#clock-cells", index, &clkspec);
{
struct device_node *child, *np = client->dev.of_node;
struct si5351_platform_data *pdata;
- struct property *prop;
- const __be32 *p;
+ u32 array[4];
+ int sz, i;
int num = 0;
u32 val;
* property silabs,pll-source : <num src>, [<..>]
* allow to selectively set pll source
*/
- of_property_for_each_u32(np, "silabs,pll-source", prop, p, num) {
+ sz = of_property_read_variable_u32_array(np, "silabs,pll-source", array, 2, 4);
+ sz = (sz == -EINVAL) ? 0 : sz; /* Missing property is OK */
+ if (sz < 0)
+ return dev_err_probe(&client->dev, sz, "invalid pll-source\n");
+ if (sz % 2)
+ return dev_err_probe(&client->dev, -EINVAL,
+ "missing pll-source for pll %d\n", array[sz - 1]);
+
+ for (i = 0; i < sz; i += 2) {
+ num = array[i];
+ val = array[i + 1];
+
if (num >= 2) {
dev_err(&client->dev,
"invalid pll %d on pll-source prop\n", num);
return -EINVAL;
}
- p = of_prop_next_u32(prop, p, &val);
- if (!p) {
- dev_err(&client->dev,
- "missing pll-source for pll %d\n", num);
- return -EINVAL;
- }
-
switch (val) {
case 0:
pdata->pll_src[num] = SI5351_PLL_SRC_XTAL;
pdata->pll_reset[0] = true;
pdata->pll_reset[1] = true;
- of_property_for_each_u32(np, "silabs,pll-reset-mode", prop, p, num) {
+ sz = of_property_read_variable_u32_array(np, "silabs,pll-reset-mode", array, 2, 4);
+ sz = (sz == -EINVAL) ? 0 : sz; /* Missing property is OK */
+ if (sz < 0)
+ return dev_err_probe(&client->dev, sz, "invalid pll-reset-mode\n");
+ if (sz % 2)
+ return dev_err_probe(&client->dev, -EINVAL,
+ "missing pll-reset-mode for pll %d\n", array[sz - 1]);
+
+ for (i = 0; i < sz; i += 2) {
+ num = array[i];
+ val = array[i + 1];
+
if (num >= 2) {
dev_err(&client->dev,
"invalid pll %d on pll-reset-mode prop\n", num);
return -EINVAL;
}
- p = of_prop_next_u32(prop, p, &val);
- if (!p) {
- dev_err(&client->dev,
- "missing pll-reset-mode for pll %d\n", num);
- return -EINVAL;
- }
switch (val) {
case 0:
const char *of_clk_get_parent_name(const struct device_node *np, int index)
{
struct of_phandle_args clkspec;
- struct property *prop;
const char *clk_name;
- const __be32 *vp;
+ bool found = false;
u32 pv;
int rc;
int count;
/* if there is an indices property, use it to transfer the index
* specified into an array offset for the clock-output-names property.
*/
- of_property_for_each_u32(clkspec.np, "clock-indices", prop, vp, pv) {
+ of_property_for_each_u32(clkspec.np, "clock-indices", pv) {
if (index == pv) {
index = count;
+ found = true;
break;
}
count++;
}
/* We went off the end of 'clock-indices' without finding it */
- if (prop && !vp)
+ if (of_property_present(clkspec.np, "clock-indices") && !found)
return NULL;
if (of_property_read_string_index(clkspec.np, "clock-output-names",
int of_clk_detect_critical(struct device_node *np, int index,
unsigned long *flags)
{
- struct property *prop;
- const __be32 *cur;
uint32_t idx;
if (!np || !flags)
return -EINVAL;
- of_property_for_each_u32(np, "clock-critical", prop, cur, idx)
+ of_property_for_each_u32(np, "clock-critical", idx)
if (index == idx)
*flags |= CLK_IS_CRITICAL;
static void qcom_cc_drop_protected(struct device *dev, struct qcom_cc *cc)
{
struct device_node *np = dev->of_node;
- struct property *prop;
- const __be32 *p;
u32 i;
- of_property_for_each_u32(np, "protected-clocks", prop, p, i) {
+ of_property_for_each_u32(np, "protected-clocks", i) {
if (i >= cc->num_rclks)
continue;
{
struct clk_onecell_data *clk_data;
const char *clk_parent, *clk_name;
- struct property *prop;
struct resource res;
void __iomem *clk_reg;
void __iomem *reg;
- const __be32 *p;
int number, i = 0, j;
u8 clk_bit;
u32 index;
if (!clk_data->clks)
goto err_free_data;
- of_property_for_each_u32(node, "clock-indices", prop, p, index) {
+ of_property_for_each_u32(node, "clock-indices", index) {
of_property_read_string_index(node, "clock-output-names",
i, &clk_name);
const char *parents[PARENT_MAX];
struct clk_onecell_data *clk_data;
const char *clk_name;
- struct property *prop;
struct resource res;
void __iomem *clk_reg;
void __iomem *reg;
- const __be32 *p;
int number, i;
u8 clk_bit;
int index;
goto err_free_data;
i = 0;
- of_property_for_each_u32(node, "clock-indices", prop, p, index) {
+ of_property_for_each_u32(node, "clock-indices", index) {
of_property_read_string_index(node, "clock-output-names",
i, &clk_name);
static int __init samsung_pwm_alloc(struct device_node *np,
const struct samsung_pwm_variant *variant)
{
- struct property *prop;
- const __be32 *cur;
u32 val;
int i, ret;
for (i = 0; i < SAMSUNG_PWM_NUM; ++i)
pwm.irq[i] = irq_of_parse_and_map(np, i);
- of_property_for_each_u32(np, "samsung,pwm-outputs", prop, cur, val) {
+ of_property_for_each_u32(np, "samsung,pwm-outputs", val) {
if (val >= SAMSUNG_PWM_NUM) {
pr_warn("%s: invalid channel index in samsung,pwm-outputs property\n", __func__);
continue;
void __iomem *reg_base;
struct brcmstb_gpio_priv *priv;
struct resource *res;
- struct property *prop;
- const __be32 *p;
u32 bank_width;
int num_banks = 0;
int num_gpios = 0;
flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
#endif
- of_property_for_each_u32(np, "brcm,gpio-bank-widths", prop, p,
- bank_width) {
+ of_property_for_each_u32(np, "brcm,gpio-bank-widths", bank_width) {
struct brcmstb_gpio_bank *bank;
struct gpio_chip *gc;
struct tiadc_device *adc_dev)
{
struct device_node *node = pdev->dev.of_node;
- struct property *prop;
- const __be32 *cur;
int channels = 0;
u32 val;
int i;
- of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
+ of_property_for_each_u32(node, "ti,adc-channels", val) {
adc_dev->channel_line[channels] = val;
/* Set Default values for optional DT parameters */
struct device_node *node = irq_domain_get_of_node(domain);
struct irq_chip_generic *gc;
struct aic_chip_data *aic;
- struct property *prop;
- const __be32 *p;
u32 hwirq;
gc = irq_get_domain_generic_chip(domain, 0);
aic = gc->private;
aic->ext_irqs |= 1;
- of_property_for_each_u32(node, "atmel,external-irqs", prop, p, hwirq) {
+ of_property_for_each_u32(node, "atmel,external-irqs", hwirq) {
gc = irq_get_domain_generic_chip(domain, hwirq);
if (!gc) {
pr_warn("AIC: external irq %d >= %d skip it\n",
{
struct device_node *node = irq_domain_get_of_node(domain);
struct evic_chip_data *priv = domain->host_data;
- struct property *prop;
- const __le32 *p;
u32 hwirq;
int i = 0;
const char *pname = "microchip,external-irqs";
- of_property_for_each_u32(node, pname, prop, p, hwirq) {
+ of_property_for_each_u32(node, pname, hwirq) {
if (i >= ARRAY_SIZE(priv->ext_irqs)) {
pr_warn("More than %d external irq, skip rest\n",
ARRAY_SIZE(priv->ext_irqs));
struct clk *clk;
struct device_node *node;
struct mfd_cell *cell;
- struct property *prop;
- const __be32 *cur;
bool use_tsc = false, use_mag = false;
u32 val;
int err;
}
node = of_get_child_by_name(pdev->dev.of_node, "adc");
- of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) {
+ of_property_for_each_u32(node, "ti,adc-channels", val) {
adc_channels++;
if (val > 7) {
dev_err(&pdev->dev, " PIN numbers are 0..7 (not %d)\n",
struct s32_pin_group *grp,
struct s32_pinctrl_soc_info *info)
{
- const __be32 *p;
struct device *dev;
- struct property *prop;
unsigned int *pins, *sss;
int i, npins;
u32 pinmux;
return -ENOMEM;
i = 0;
- of_property_for_each_u32(np, "pinmux", prop, p, pinmux) {
+ of_property_for_each_u32(np, "pinmux", pinmux) {
pins[i] = get_pin_no(pinmux);
sss[i] = get_pin_func(pinmux);
unsigned int *reserved_maps,
unsigned int *num_maps)
{
- struct property *prop;
- const __be32 *p;
int ret, pinmux_groups;
u32 pinmux_group;
unsigned long *configs = NULL;
if (ret < 0)
goto exit;
- of_property_for_each_u32(np, "pinmux", prop, p, pinmux_group) {
+ of_property_for_each_u32(np, "pinmux", pinmux_group) {
const char *group_name, *func_name;
u32 pin = FIELD_GET(K210_PG_PIN, pinmux_group);
u32 func = FIELD_GET(K210_PG_FUNC, pinmux_group);
struct samsung_pwm_chip *our_chip = to_samsung_pwm_chip(chip);
struct device_node *np = pwmchip_parent(chip)->of_node;
const struct of_device_id *match;
- struct property *prop;
- const __be32 *cur;
u32 val;
match = of_match_node(samsung_pwm_matches, np);
memcpy(&our_chip->variant, match->data, sizeof(our_chip->variant));
- of_property_for_each_u32(np, "samsung,pwm-outputs", prop, cur, val) {
+ of_property_for_each_u32(np, "samsung,pwm-outputs", val) {
if (val >= SAMSUNG_PWM_NUM) {
dev_err(pwmchip_parent(chip),
"%s: invalid channel index in samsung,pwm-outputs property\n",
{
u32 key;
struct device_node *np;
- struct property *prop;
- const __be32 *p;
np = of_find_node_by_path("/chosen/linux,sysrq-reset-seq");
if (!np) {
/* Reset in case a __weak definition was present */
sysrq_reset_seq_len = 0;
- of_property_for_each_u32(np, "keyset", prop, p, key) {
+ of_property_for_each_u32(np, "keyset", key) {
if (key == KEY_RESERVED || key > KEY_MAX ||
sysrq_reset_seq_len == SYSRQ_KEY_RESET_MAX)
break;
bool ds_only, u8 *fld)
{
struct device *dev = hub->dev;
- struct property *prop;
- const __be32 *p;
u32 port;
- of_property_for_each_u32(dev->of_node, prop_name, prop, p, port) {
+ of_property_for_each_u32(dev->of_node, prop_name, port) {
if ((port >= ds_only ? 1 : 0) && (port <= port_cnt))
*fld |= BIT(port);
else
#define of_match_ptr(_ptr) (_ptr)
/*
- * struct property *prop;
- * const __be32 *p;
* u32 u;
*
- * of_property_for_each_u32(np, "propname", prop, p, u)
+ * of_property_for_each_u32(np, "propname", u)
* printk("U32 value: %x\n", u);
*/
const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
err == 0; \
err = of_phandle_iterator_next(it))
-#define of_property_for_each_u32(np, propname, prop, p, u) \
- for (prop = of_find_property(np, propname, NULL), \
- p = of_prop_next_u32(prop, NULL, &u); \
- p; \
- p = of_prop_next_u32(prop, p, &u))
+#define of_property_for_each_u32(np, propname, u) \
+ for (struct {struct property *prop; const __be32 *item; } _it = \
+ {of_find_property(np, propname, NULL), \
+ of_prop_next_u32(_it.prop, NULL, &u)}; \
+ _it.item; \
+ _it.item = of_prop_next_u32(_it.prop, _it.item, &u))
#define of_property_for_each_string(np, propname, prop, s) \
for (prop = of_find_property(np, propname, NULL), \
{
struct arizona_pdata *pdata = &arizona->pdata;
struct device_node *np = arizona->dev->of_node;
- struct property *prop;
- const __be32 *cur;
u32 val;
u32 pdm_val[ARIZONA_MAX_PDM_SPK];
int ret;
int count = 0;
count = 0;
- of_property_for_each_u32(np, "wlf,inmode", prop, cur, val) {
+ of_property_for_each_u32(np, "wlf,inmode", val) {
if (count == ARRAY_SIZE(pdata->inmode))
break;
}
count = 0;
- of_property_for_each_u32(np, "wlf,dmic-ref", prop, cur, val) {
+ of_property_for_each_u32(np, "wlf,dmic-ref", val) {
if (count == ARRAY_SIZE(pdata->dmic_ref))
break;
}
count = 0;
- of_property_for_each_u32(np, "wlf,out-mono", prop, cur, val) {
+ of_property_for_each_u32(np, "wlf,out-mono", val) {
if (count == ARRAY_SIZE(pdata->out_mono))
break;
}
count = 0;
- of_property_for_each_u32(np, "wlf,max-channels-clocked", prop, cur, val) {
+ of_property_for_each_u32(np, "wlf,max-channels-clocked", val) {
if (count == ARRAY_SIZE(pdata->max_channels_clocked))
break;
}
count = 0;
- of_property_for_each_u32(np, "wlf,out-volume-limit", prop, cur, val) {
+ of_property_for_each_u32(np, "wlf,out-volume-limit", val) {
if (count == ARRAY_SIZE(pdata->out_vol_limit))
break;