Merge branches 'clk-vc5', 'clk-silabs', 'clk-aspeed', 'clk-qoriq' and 'clk-rohm' into clk-next

- Support crystal load capacitance for Versaclock VC5
 - Add a "skip recall" DT binding for Silicon Labs' si570 to avoid glitches at boot

* clk-vc5:
  clk: vc5: Add support for optional load capacitance
  dt-bindings: clk: versaclock5: Add optional load capacitance property

* clk-silabs:
  clk: si570: Skip NVM to RAM recall operation if an optional property is set
  dt-bindings: clock: si570: Add 'silabs,skip-recall' property

* clk-aspeed:
  clk: aspeed: Fix APLL calculate formula from ast2600-A2

* clk-qoriq:
  clk: qoriq: use macros to generate pll_mask

* clk-rohm:
  clk: BD718x7: Do not depend on parent driver data
This commit is contained in:
Stephen Boyd 2021-02-16 14:09:12 -08:00
7 changed files with 161 additions and 38 deletions

View file

@ -59,6 +59,12 @@ properties:
minItems: 1 minItems: 1
maxItems: 2 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: patternProperties:
"^OUT[1-4]$": "^OUT[1-4]$":
type: object type: object

View file

@ -28,6 +28,8 @@ Optional properties:
- clock-frequency: Output frequency to generate. This defines the output - clock-frequency: Output frequency to generate. This defines the output
frequency set during boot. It can be reprogrammed during frequency set during boot. It can be reprogrammed during
runtime through the common clock framework. 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: Example:
si570: clock-generator@5d { si570: clock-generator@5d {

View file

@ -17,7 +17,8 @@
#define ASPEED_G6_NUM_CLKS 71 #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_CTRL 0x040
#define ASPEED_G6_RESET_CTRL2 0x050 #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) static struct clk_hw *ast2600_calc_apll(const char *name, u32 val)
{ {
unsigned int mult, div; unsigned int mult, div;
u32 chip_id = readl(scu_g6_base + ASPEED_G6_SILICON_REV);
if (val & BIT(20)) { if (((chip_id & CHIP_REVISION_ID) >> 16) >= 2) {
/* Pass through mode */ if (val & BIT(24)) {
mult = div = 1; /* 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 { } else {
/* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */ if (val & BIT(20)) {
u32 m = (val >> 5) & 0x3f; /* Pass through mode */
u32 od = (val >> 4) & 0x1; mult = div = 1;
u32 n = val & 0xf; } 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); mult = (2 - od) * (m + 2);
div = n + 1; div = n + 1;
}
} }
return clk_hw_register_fixed_factor(NULL, name, "clkin", 0, return clk_hw_register_fixed_factor(NULL, name, "clkin", 0,
mult, div); mult, div);

View file

@ -31,12 +31,12 @@ struct bd718xx_clk {
u8 reg; u8 reg;
u8 mask; u8 mask;
struct platform_device *pdev; struct platform_device *pdev;
struct rohm_regmap_dev *mfd; struct regmap *regmap;
}; };
static int bd71837_clk_set(struct bd718xx_clk *c, unsigned int status) 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) 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; int rval;
struct bd718xx_clk *c = container_of(hw, struct bd718xx_clk, hw); 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) if (rval)
return rval; return rval;
@ -82,7 +82,6 @@ static int bd71837_clk_probe(struct platform_device *pdev)
int rval = -ENOMEM; int rval = -ENOMEM;
const char *parent_clk; const char *parent_clk;
struct device *parent = pdev->dev.parent; struct device *parent = pdev->dev.parent;
struct rohm_regmap_dev *mfd = dev_get_drvdata(parent);
struct clk_init_data init = { struct clk_init_data init = {
.name = "bd718xx-32k-out", .name = "bd718xx-32k-out",
.ops = &bd71837_clk_ops, .ops = &bd71837_clk_ops,
@ -93,6 +92,10 @@ static int bd71837_clk_probe(struct platform_device *pdev)
if (!c) if (!c)
return -ENOMEM; return -ENOMEM;
c->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!c->regmap)
return -ENODEV;
init.num_parents = 1; init.num_parents = 1;
parent_clk = of_clk_get_parent_name(parent->of_node, 0); 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"); dev_err(&pdev->dev, "Unknown clk chip\n");
return -EINVAL; return -EINVAL;
} }
c->mfd = mfd;
c->pdev = pdev; c->pdev = pdev;
c->hw.init = &init; c->hw.init = &init;

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright 2013 Freescale Semiconductor, Inc. * Copyright 2013 Freescale Semiconductor, Inc.
* Copyright 2021 NXP
* *
* clock driver for Freescale QorIQ SoCs. * clock driver for Freescale QorIQ SoCs.
*/ */
@ -564,7 +565,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 1, 1, 1, -1 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, .flags = CG_PLL_8BIT,
}, },
{ {
@ -580,7 +583,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 1, 1, 1, -1 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, .flags = CG_PLL_8BIT,
}, },
{ {
@ -591,7 +596,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, -1 0, -1
}, },
.pll_mask = 0x03, .pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
}, },
{ {
.compat = "fsl,ls1028a-clockgen", .compat = "fsl,ls1028a-clockgen",
@ -605,7 +611,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 0, 0, 0, -1 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, .flags = CG_VER3 | CG_LITTLE_ENDIAN,
}, },
{ {
@ -620,7 +627,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, -1 0, -1
}, },
.pll_mask = 0x07, .pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_PLL_8BIT, .flags = CG_PLL_8BIT,
}, },
{ {
@ -635,7 +643,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, -1 0, -1
}, },
.pll_mask = 0x07, .pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_PLL_8BIT, .flags = CG_PLL_8BIT,
}, },
{ {
@ -649,7 +658,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 0, -1 0, 0, -1
}, },
.pll_mask = 0x07, .pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_VER3 | CG_LITTLE_ENDIAN, .flags = CG_VER3 | CG_LITTLE_ENDIAN,
}, },
{ {
@ -660,7 +670,7 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, -1 0, -1
}, },
.pll_mask = 0x03, .pll_mask = BIT(PLATFORM_PLL) | BIT(CGA_PLL1),
}, },
{ {
.compat = "fsl,ls2080a-clockgen", .compat = "fsl,ls2080a-clockgen",
@ -670,7 +680,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 0, 1, 1, -1 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, .flags = CG_VER3 | CG_LITTLE_ENDIAN,
}, },
{ {
@ -681,7 +693,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 0, 0, 0, 1, 1, 1, 1, -1 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, .flags = CG_VER3 | CG_LITTLE_ENDIAN,
}, },
{ {
@ -694,7 +708,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 0, 1, 1, -1 0, 0, 1, 1, -1
}, },
.pll_mask = 0x07, .pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
}, },
{ {
.compat = "fsl,p3041-clockgen", .compat = "fsl,p3041-clockgen",
@ -706,7 +721,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 0, 1, 1, -1 0, 0, 1, 1, -1
}, },
.pll_mask = 0x07, .pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
}, },
{ {
.compat = "fsl,p4080-clockgen", .compat = "fsl,p4080-clockgen",
@ -718,7 +734,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 0, 0, 0, 1, 1, 1, 1, -1 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", .compat = "fsl,p5020-clockgen",
@ -730,7 +748,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 1, -1 0, 1, -1
}, },
.pll_mask = 0x07, .pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
}, },
{ {
.compat = "fsl,p5040-clockgen", .compat = "fsl,p5040-clockgen",
@ -742,7 +761,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 0, 1, 1, -1 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", .compat = "fsl,t1023-clockgen",
@ -757,7 +777,7 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 0, -1 0, 0, -1
}, },
.pll_mask = 0x03, .pll_mask = BIT(PLATFORM_PLL) | BIT(CGA_PLL1),
.flags = CG_PLL_8BIT, .flags = CG_PLL_8BIT,
}, },
{ {
@ -770,7 +790,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 0, 0, 0, -1 0, 0, 0, 0, -1
}, },
.pll_mask = 0x07, .pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_PLL_8BIT, .flags = CG_PLL_8BIT,
}, },
{ {
@ -786,7 +807,8 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, -1 0, -1
}, },
.pll_mask = 0x07, .pll_mask = BIT(PLATFORM_PLL) |
BIT(CGA_PLL1) | BIT(CGA_PLL2),
.flags = CG_PLL_8BIT, .flags = CG_PLL_8BIT,
}, },
{ {
@ -802,7 +824,9 @@ static const struct clockgen_chipinfo chipinfo[] = {
.cmux_to_group = { .cmux_to_group = {
0, 0, 1, -1 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, .flags = CG_PLL_8BIT,
}, },
{}, {},

View file

@ -4,7 +4,7 @@
* *
* Copyright (C) 2010, 2011 Ericsson AB. * Copyright (C) 2010, 2011 Ericsson AB.
* Copyright (C) 2011 Guenter Roeck. * Copyright (C) 2011 Guenter Roeck.
* Copyright (C) 2011 - 2013 Xilinx Inc. * Copyright (C) 2011 - 2021 Xilinx Inc.
* *
* Author: Guenter Roeck <guenter.roeck@ericsson.com> * Author: Guenter Roeck <guenter.roeck@ericsson.com>
* Sören Brinkmann <soren.brinkmann@xilinx.com> * Sören Brinkmann <soren.brinkmann@xilinx.com>
@ -123,14 +123,18 @@ static int si570_get_divs(struct clk_si570 *data, u64 *rfreq,
* si570_get_defaults() - Get default values * si570_get_defaults() - Get default values
* @data: Driver data structure * @data: Driver data structure
* @fout: Factory frequency output * @fout: Factory frequency output
* @skip_recall: If true, don't recall NVM into RAM
* Returns 0 on success, negative errno otherwise. * 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; int err;
u64 fdco; 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); err = si570_get_divs(data, &data->rfreq, &data->n1, &data->hs_div);
if (err) if (err)
@ -400,6 +404,7 @@ static int si570_probe(struct i2c_client *client,
struct clk_si570 *data; struct clk_si570 *data;
struct clk_init_data init; struct clk_init_data init;
u32 initial_fout, factory_fout, stability; u32 initial_fout, factory_fout, stability;
bool skip_recall;
int err; int err;
enum clk_si570_variant variant = id->driver_data; enum clk_si570_variant variant = id->driver_data;
@ -441,6 +446,9 @@ static int si570_probe(struct i2c_client *client,
return err; 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); data->regmap = devm_regmap_init_i2c(client, &si570_regmap_config);
if (IS_ERR(data->regmap)) { if (IS_ERR(data->regmap)) {
dev_err(&client->dev, "failed to allocate register map\n"); 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); i2c_set_clientdata(client, data);
err = si570_get_defaults(data, factory_fout); err = si570_get_defaults(data, factory_fout, skip_recall);
if (err) if (err)
return err; return err;

View file

@ -759,6 +759,63 @@ static int vc5_update_power(struct device_node *np_output,
return 0; 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, static int vc5_update_slew(struct device_node *np_output,
struct vc5_out_data *clk_out) 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; 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.name = kasprintf(GFP_KERNEL, "%pOFn.mux", client->dev.of_node);
init.ops = &vc5_mux_ops; init.ops = &vc5_mux_ops;
init.flags = 0; init.flags = 0;