in clk-si5351.c [1163:1342]
static int si5351_dt_parse(struct i2c_client *client,
enum si5351_variant variant)
{
struct device_node *child, *np = client->dev.of_node;
struct si5351_platform_data *pdata;
struct property *prop;
const __be32 *p;
int num = 0;
u32 val;
if (np == NULL)
return 0;
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
/*
* property silabs,pll-source : <num src>, [<..>]
* allow to selectively set pll source
*/
of_property_for_each_u32(np, "silabs,pll-source", prop, p, num) {
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;
break;
case 1:
if (variant != SI5351_VARIANT_C) {
dev_err(&client->dev,
"invalid parent %d for pll %d\n",
val, num);
return -EINVAL;
}
pdata->pll_src[num] = SI5351_PLL_SRC_CLKIN;
break;
default:
dev_err(&client->dev,
"invalid parent %d for pll %d\n", val, num);
return -EINVAL;
}
}
/* per clkout properties */
for_each_child_of_node(np, child) {
if (of_property_read_u32(child, "reg", &num)) {
dev_err(&client->dev, "missing reg property of %pOFn\n",
child);
goto put_child;
}
if (num >= 8 ||
(variant == SI5351_VARIANT_A3 && num >= 3)) {
dev_err(&client->dev, "invalid clkout %d\n", num);
goto put_child;
}
if (!of_property_read_u32(child, "silabs,multisynth-source",
&val)) {
switch (val) {
case 0:
pdata->clkout[num].multisynth_src =
SI5351_MULTISYNTH_SRC_VCO0;
break;
case 1:
pdata->clkout[num].multisynth_src =
SI5351_MULTISYNTH_SRC_VCO1;
break;
default:
dev_err(&client->dev,
"invalid parent %d for multisynth %d\n",
val, num);
goto put_child;
}
}
if (!of_property_read_u32(child, "silabs,clock-source", &val)) {
switch (val) {
case 0:
pdata->clkout[num].clkout_src =
SI5351_CLKOUT_SRC_MSYNTH_N;
break;
case 1:
pdata->clkout[num].clkout_src =
SI5351_CLKOUT_SRC_MSYNTH_0_4;
break;
case 2:
pdata->clkout[num].clkout_src =
SI5351_CLKOUT_SRC_XTAL;
break;
case 3:
if (variant != SI5351_VARIANT_C) {
dev_err(&client->dev,
"invalid parent %d for clkout %d\n",
val, num);
goto put_child;
}
pdata->clkout[num].clkout_src =
SI5351_CLKOUT_SRC_CLKIN;
break;
default:
dev_err(&client->dev,
"invalid parent %d for clkout %d\n",
val, num);
goto put_child;
}
}
if (!of_property_read_u32(child, "silabs,drive-strength",
&val)) {
switch (val) {
case SI5351_DRIVE_2MA:
case SI5351_DRIVE_4MA:
case SI5351_DRIVE_6MA:
case SI5351_DRIVE_8MA:
pdata->clkout[num].drive = val;
break;
default:
dev_err(&client->dev,
"invalid drive strength %d for clkout %d\n",
val, num);
goto put_child;
}
}
if (!of_property_read_u32(child, "silabs,disable-state",
&val)) {
switch (val) {
case 0:
pdata->clkout[num].disable_state =
SI5351_DISABLE_LOW;
break;
case 1:
pdata->clkout[num].disable_state =
SI5351_DISABLE_HIGH;
break;
case 2:
pdata->clkout[num].disable_state =
SI5351_DISABLE_FLOATING;
break;
case 3:
pdata->clkout[num].disable_state =
SI5351_DISABLE_NEVER;
break;
default:
dev_err(&client->dev,
"invalid disable state %d for clkout %d\n",
val, num);
goto put_child;
}
}
if (!of_property_read_u32(child, "clock-frequency", &val))
pdata->clkout[num].rate = val;
pdata->clkout[num].pll_master =
of_property_read_bool(child, "silabs,pll-master");
pdata->clkout[num].pll_reset =
of_property_read_bool(child, "silabs,pll-reset");
}
client->dev.platform_data = pdata;
return 0;
put_child:
of_node_put(child);
return -EINVAL;
}