diff --git a/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml b/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml index 2ac1131fd922..c268debe5b8d 100644 --- a/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml +++ b/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml @@ -59,6 +59,12 @@ properties: minItems: 1 maxItems: 2 + idt,xtal-load-femtofarads: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 9000 + maximum: 22760 + description: Optional load capacitor for XTAL1 and XTAL2 + patternProperties: "^OUT[1-4]$": type: object diff --git a/Documentation/devicetree/bindings/clock/silabs,si570.txt b/Documentation/devicetree/bindings/clock/silabs,si570.txt index 901935e929d2..5dda17df1ac5 100644 --- a/Documentation/devicetree/bindings/clock/silabs,si570.txt +++ b/Documentation/devicetree/bindings/clock/silabs,si570.txt @@ -28,6 +28,8 @@ Optional properties: - clock-frequency: Output frequency to generate. This defines the output frequency set during boot. It can be reprogrammed during runtime through the common clock framework. + - silabs,skip-recall: Do not perform NVM->RAM recall operation. It will rely + on hardware loading of RAM from NVM at power on. Example: si570: clock-generator@5d { diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c index 177368cac6dd..a55b37fc2c8b 100644 --- a/drivers/clk/clk-ast2600.c +++ b/drivers/clk/clk-ast2600.c @@ -17,7 +17,8 @@ #define ASPEED_G6_NUM_CLKS 71 -#define ASPEED_G6_SILICON_REV 0x004 +#define ASPEED_G6_SILICON_REV 0x014 +#define CHIP_REVISION_ID GENMASK(23, 16) #define ASPEED_G6_RESET_CTRL 0x040 #define ASPEED_G6_RESET_CTRL2 0x050 @@ -190,18 +191,34 @@ static struct clk_hw *ast2600_calc_pll(const char *name, u32 val) static struct clk_hw *ast2600_calc_apll(const char *name, u32 val) { unsigned int mult, div; + u32 chip_id = readl(scu_g6_base + ASPEED_G6_SILICON_REV); - if (val & BIT(20)) { - /* Pass through mode */ - mult = div = 1; + if (((chip_id & CHIP_REVISION_ID) >> 16) >= 2) { + if (val & BIT(24)) { + /* Pass through mode */ + mult = div = 1; + } else { + /* F = 25Mhz * [(m + 1) / (n + 1)] / (p + 1) */ + u32 m = val & 0x1fff; + u32 n = (val >> 13) & 0x3f; + u32 p = (val >> 19) & 0xf; + + mult = (m + 1); + div = (n + 1) * (p + 1); + } } else { - /* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */ - u32 m = (val >> 5) & 0x3f; - u32 od = (val >> 4) & 0x1; - u32 n = val & 0xf; + if (val & BIT(20)) { + /* Pass through mode */ + mult = div = 1; + } else { + /* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */ + u32 m = (val >> 5) & 0x3f; + u32 od = (val >> 4) & 0x1; + u32 n = val & 0xf; - mult = (2 - od) * (m + 2); - div = n + 1; + mult = (2 - od) * (m + 2); + div = n + 1; + } } return clk_hw_register_fixed_factor(NULL, name, "clkin", 0, mult, div); diff --git a/drivers/clk/clk-bd718x7.c b/drivers/clk/clk-bd718x7.c index b52e8d6f660c..17d90e09f1c0 100644 --- a/drivers/clk/clk-bd718x7.c +++ b/drivers/clk/clk-bd718x7.c @@ -31,12 +31,12 @@ struct bd718xx_clk { u8 reg; u8 mask; struct platform_device *pdev; - struct rohm_regmap_dev *mfd; + struct regmap *regmap; }; static int bd71837_clk_set(struct bd718xx_clk *c, unsigned int status) { - return regmap_update_bits(c->mfd->regmap, c->reg, c->mask, status); + return regmap_update_bits(c->regmap, c->reg, c->mask, status); } static void bd71837_clk_disable(struct clk_hw *hw) @@ -62,7 +62,7 @@ static int bd71837_clk_is_enabled(struct clk_hw *hw) int rval; struct bd718xx_clk *c = container_of(hw, struct bd718xx_clk, hw); - rval = regmap_read(c->mfd->regmap, c->reg, &enabled); + rval = regmap_read(c->regmap, c->reg, &enabled); if (rval) return rval; @@ -82,7 +82,6 @@ static int bd71837_clk_probe(struct platform_device *pdev) int rval = -ENOMEM; const char *parent_clk; struct device *parent = pdev->dev.parent; - struct rohm_regmap_dev *mfd = dev_get_drvdata(parent); struct clk_init_data init = { .name = "bd718xx-32k-out", .ops = &bd71837_clk_ops, @@ -93,6 +92,10 @@ static int bd71837_clk_probe(struct platform_device *pdev) if (!c) return -ENOMEM; + c->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!c->regmap) + return -ENODEV; + init.num_parents = 1; parent_clk = of_clk_get_parent_name(parent->of_node, 0); @@ -119,7 +122,6 @@ static int bd71837_clk_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Unknown clk chip\n"); return -EINVAL; } - c->mfd = mfd; c->pdev = pdev; c->hw.init = &init; diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index 70aa521e7e7f..88898b97a443 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright 2013 Freescale Semiconductor, Inc. + * Copyright 2021 NXP * * clock driver for Freescale QorIQ SoCs. */ @@ -564,7 +565,9 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 1, 1, 1, -1 }, - .pll_mask = 0x3f, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) | + BIT(CGB_PLL1) | BIT(CGB_PLL2), .flags = CG_PLL_8BIT, }, { @@ -580,7 +583,9 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 1, 1, 1, -1 }, - .pll_mask = 0x3f, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) | + BIT(CGB_PLL1) | BIT(CGB_PLL2), .flags = CG_PLL_8BIT, }, { @@ -591,7 +596,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, -1 }, - .pll_mask = 0x03, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), }, { .compat = "fsl,ls1028a-clockgen", @@ -605,7 +611,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 0, 0, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), .flags = CG_VER3 | CG_LITTLE_ENDIAN, }, { @@ -620,7 +627,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), .flags = CG_PLL_8BIT, }, { @@ -635,7 +643,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), .flags = CG_PLL_8BIT, }, { @@ -649,7 +658,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), .flags = CG_VER3 | CG_LITTLE_ENDIAN, }, { @@ -660,7 +670,7 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, -1 }, - .pll_mask = 0x03, + .pll_mask = BIT(PLATFORM_PLL) | BIT(CGA_PLL1), }, { .compat = "fsl,ls2080a-clockgen", @@ -670,7 +680,9 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 1, 1, -1 }, - .pll_mask = 0x37, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | + BIT(CGB_PLL1) | BIT(CGB_PLL2), .flags = CG_VER3 | CG_LITTLE_ENDIAN, }, { @@ -681,7 +693,9 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 0, 0, 1, 1, 1, 1, -1 }, - .pll_mask = 0x37, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | + BIT(CGB_PLL1) | BIT(CGB_PLL2), .flags = CG_VER3 | CG_LITTLE_ENDIAN, }, { @@ -694,7 +708,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 1, 1, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), }, { .compat = "fsl,p3041-clockgen", @@ -706,7 +721,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 1, 1, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), }, { .compat = "fsl,p4080-clockgen", @@ -718,7 +734,9 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 0, 0, 1, 1, 1, 1, -1 }, - .pll_mask = 0x1f, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | + BIT(CGA_PLL3) | BIT(CGA_PLL4), }, { .compat = "fsl,p5020-clockgen", @@ -730,7 +748,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 1, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), }, { .compat = "fsl,p5040-clockgen", @@ -742,7 +761,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 1, 1, -1 }, - .pll_mask = 0x0f, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3), }, { .compat = "fsl,t1023-clockgen", @@ -757,7 +777,7 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, -1 }, - .pll_mask = 0x03, + .pll_mask = BIT(PLATFORM_PLL) | BIT(CGA_PLL1), .flags = CG_PLL_8BIT, }, { @@ -770,7 +790,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 0, 0, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), .flags = CG_PLL_8BIT, }, { @@ -786,7 +807,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), .flags = CG_PLL_8BIT, }, { @@ -802,7 +824,9 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 1, -1 }, - .pll_mask = 0x3f, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) | + BIT(CGB_PLL1) | BIT(CGB_PLL2), .flags = CG_PLL_8BIT, }, {}, diff --git a/drivers/clk/clk-si570.c b/drivers/clk/clk-si570.c index 34b25609f55f..eea50121718a 100644 --- a/drivers/clk/clk-si570.c +++ b/drivers/clk/clk-si570.c @@ -4,7 +4,7 @@ * * Copyright (C) 2010, 2011 Ericsson AB. * Copyright (C) 2011 Guenter Roeck. - * Copyright (C) 2011 - 2013 Xilinx Inc. + * Copyright (C) 2011 - 2021 Xilinx Inc. * * Author: Guenter Roeck * Sören Brinkmann @@ -123,14 +123,18 @@ static int si570_get_divs(struct clk_si570 *data, u64 *rfreq, * si570_get_defaults() - Get default values * @data: Driver data structure * @fout: Factory frequency output + * @skip_recall: If true, don't recall NVM into RAM * Returns 0 on success, negative errno otherwise. */ -static int si570_get_defaults(struct clk_si570 *data, u64 fout) +static int si570_get_defaults(struct clk_si570 *data, u64 fout, + bool skip_recall) { int err; u64 fdco; - regmap_write(data->regmap, SI570_REG_CONTROL, SI570_CNTRL_RECALL); + if (!skip_recall) + regmap_write(data->regmap, SI570_REG_CONTROL, + SI570_CNTRL_RECALL); err = si570_get_divs(data, &data->rfreq, &data->n1, &data->hs_div); if (err) @@ -400,6 +404,7 @@ static int si570_probe(struct i2c_client *client, struct clk_si570 *data; struct clk_init_data init; u32 initial_fout, factory_fout, stability; + bool skip_recall; int err; enum clk_si570_variant variant = id->driver_data; @@ -441,6 +446,9 @@ static int si570_probe(struct i2c_client *client, return err; } + skip_recall = of_property_read_bool(client->dev.of_node, + "silabs,skip-recall"); + data->regmap = devm_regmap_init_i2c(client, &si570_regmap_config); if (IS_ERR(data->regmap)) { dev_err(&client->dev, "failed to allocate register map\n"); @@ -448,7 +456,7 @@ static int si570_probe(struct i2c_client *client, } i2c_set_clientdata(client, data); - err = si570_get_defaults(data, factory_fout); + err = si570_get_defaults(data, factory_fout, skip_recall); if (err) return err; diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 43db67337bc0..344cd6c61188 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 with 0.5pF + * steps, but the Programmer's guide shows the steps are 0.430pF. + * After getting feedback from Renesas, the .5pF steps were the + * goal, but 430nF was the actual values. + * Because of this, the actual range goes to 22760 instead of 25000 + */ + if (femtofarads < 9000 || femtofarads > 22760) + return -EINVAL; + + /* + * The Programmer's guide shows XTAL[5:0] but in reality, + * XTAL[0] and XTAL[1] are both LSB which makes the math + * strange. With clarfication from Renesas, setting the + * values should be simpler by ignoring XTAL[0] + */ + mapped_value = DIV_ROUND_CLOSEST(femtofarads - 9000, 430); + + /* + * Since the calculation ignores XTAL[0], there is one + * special case where mapped_value = 32. In reality, this means + * the real mapped value should be 111111b. In other cases, + * the mapped_value needs to be shifted 1 to the left. + */ + if (mapped_value > 31) + mapped_value = 0x3f; + else + mapped_value <<= 1; + + return mapped_value; +} +static int vc5_update_cap_load(struct device_node *node, struct vc5_driver_data *vc5) +{ + u32 value; + int mapped_value; + + if (!of_property_read_u32(node, "idt,xtal-load-femtofarads", &value)) { + mapped_value = vc5_map_cap_value(value); + if (mapped_value < 0) + return mapped_value; + + /* + * The mapped_value is really the high 6 bits of + * VC5_XTAL_X1_LOAD_CAP and VC5_XTAL_X2_LOAD_CAP, so + * shift the value 2 places. + */ + regmap_update_bits(vc5->regmap, VC5_XTAL_X1_LOAD_CAP, ~0x03, mapped_value << 2); + regmap_update_bits(vc5->regmap, VC5_XTAL_X2_LOAD_CAP, ~0x03, mapped_value << 2); + } + + return 0; +} + static int vc5_update_slew(struct device_node *np_output, struct vc5_out_data *clk_out) { @@ -884,6 +941,13 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) return -EINVAL; } + /* Configure Optional Loading Capacitance for external XTAL */ + if (!(vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)) { + ret = vc5_update_cap_load(client->dev.of_node, vc5); + if (ret) + goto err_clk_register; + } + init.name = kasprintf(GFP_KERNEL, "%pOFn.mux", client->dev.of_node); init.ops = &vc5_mux_ops; init.flags = 0;