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
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

View File

@ -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 {

View File

@ -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);

View File

@ -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;

View File

@ -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,
},
{},

View File

@ -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 <guenter.roeck@ericsson.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
* @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;

View File

@ -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;