Quoting Adam Ford (2021-01-06 09:39:00) > There are two registers which can set the load capacitance for > XTAL1 and XTAL2. These are optional registers when using an > external crystal. Parse the device tree and set the > corresponding registers accordingly. > > Signed-off-by: Adam Ford <aford...@gmail.com> > --- > drivers/clk/clk-versaclock5.c | 64 +++++++++++++++++++++++++++++++++++ > 1 file changed, 64 insertions(+) > > diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c > index 43db67337bc0..445abc3731fb 100644 > --- a/drivers/clk/clk-versaclock5.c > +++ b/drivers/clk/clk-versaclock5.c > @@ -759,6 +759,63 @@ static int vc5_update_power(struct device_node > *np_output, > return 0; > } > > +static int vc5_map_cap_value(u32 femtofarads) > +{ > + int mapped_value; > + > + /* The datasheet explicitly states 9000 - 25000 */ > + if ((femtofarads < 9000) || (femtofarads > 25000))
Please remove useless parenthesis. > + return -EINVAL; > + > + /* The lowest target we can hit is 9430, so exit if it's less */ > + if (femtofarads < 9430) > + return 0; > + > + /* > + * According to VersaClock 6E Programming Guide, there are 6 > + * bits which translate to 64 entries in XTAL registers 12 and > + * 13. Because bits 0 and 1 increase the capacitance the > + * same, some of the values can be repeated. Plugging this > + * into a spreadsheet and generating a trendline, the output > + * equation becomes x = (y-9098.29) / 216.44, where 'y' is > + * the desired capacitance in femtofarads, and x is the value > + * of XTAL[5:0]. > + * To help with rounding, do fixed point math > + */ > + femtofarads *= 100; > + mapped_value = (femtofarads - 909829) / 21644; > + > + /* > + * The datasheet states, the maximum capacitance is 25000, > + * but the programmer guide shows a max value is 22832, > + * so values higher values could overflow, so cap it. > + */ > + mapped_value = max(mapped_value/100, 0x3f); > + > + return mapped_value; > +} > +static int vc5_update_cap_load(struct device_node *node, struct > vc5_driver_data *vc5) > +{ > + u32 value, mapped_value; > + > + if (!of_property_read_u32(node, "idt,xtal1-load-femtofarads", > &value)) { > + mapped_value = vc5_map_cap_value(value); > + if (mapped_value < 0) How can it be less than 0? It's unsigned. > + return mapped_value; > + > + regmap_write(vc5->regmap, VC5_XTAL_X1_LOAD_CAP, (mapped_value > << 2)); > + } > + > + if (!of_property_read_u32(node, "idt,xtal2-load-femtofarads", > &value)) { > + mapped_value = vc5_map_cap_value(value); > + if (mapped_value < 0) Same! > + return mapped_value; > + regmap_write(vc5->regmap, VC5_XTAL_X2_LOAD_CAP, (mapped_value > << 2)); > + } > + > + return 0; > +} > + > static int vc5_update_slew(struct device_node *np_output, > struct vc5_out_data *clk_out) > {