Commit b6c444de authored by Stephen Boyd's avatar Stephen Boyd

Merge branches 'clk-cdce-regulator', 'clk-bcm', 'clk-evict-parent-cache' and...

Merge branches 'clk-cdce-regulator', 'clk-bcm', 'clk-evict-parent-cache' and 'clk-actions' into clk-next

 - Add regulator support to the cdce925 clk driver
 - Add support for Raspberry Pi 4 bcm2711 SoCs
 - Evict parents from parent cache when they're unregistered

* clk-cdce-regulator:
  clk: clk-cdce925: Add regulator support
  dt-bindings: clock: cdce925: Add regulator documentation

* clk-bcm:
  clk: bcm2835: Mark PLLD_PER as CRITICAL
  clk: bcm2835: Add BCM2711_CLOCK_EMMC2 support
  clk: bcm2835: Introduce SoC specific clock registration
  dt-bindings: bcm2835-cprman: Add bcm2711 support

* clk-evict-parent-cache:
  clk: Evict unregistered clks from parent caches

* clk-actions:
  clk: actions: Fix factor clk struct member access
...@@ -12,7 +12,9 @@ clock generators, but a few (like the ARM or HDMI) will source from ...@@ -12,7 +12,9 @@ clock generators, but a few (like the ARM or HDMI) will source from
the PLL dividers directly. the PLL dividers directly.
Required properties: Required properties:
- compatible: Should be "brcm,bcm2835-cprman" - compatible: should be one of the following,
"brcm,bcm2711-cprman"
"brcm,bcm2835-cprman"
- #clock-cells: Should be <1>. The permitted clock-specifier values can be - #clock-cells: Should be <1>. The permitted clock-specifier values can be
found in include/dt-bindings/clock/bcm2835.h found in include/dt-bindings/clock/bcm2835.h
- reg: Specifies base physical address and size of the registers - reg: Specifies base physical address and size of the registers
......
...@@ -24,6 +24,8 @@ Required properties: ...@@ -24,6 +24,8 @@ Required properties:
Optional properties: Optional properties:
- xtal-load-pf: Crystal load-capacitor value to fine-tune performance on a - xtal-load-pf: Crystal load-capacitor value to fine-tune performance on a
board, or to compensate for external influences. board, or to compensate for external influences.
- vdd-supply: A regulator node for Vdd
- vddout-supply: A regulator node for Vddout
For all PLL1, PLL2, ... an optional child node can be used to specify spread For all PLL1, PLL2, ... an optional child node can be used to specify spread
spectrum clocking parameters for a board. spectrum clocking parameters for a board.
...@@ -41,6 +43,8 @@ Example: ...@@ -41,6 +43,8 @@ Example:
clocks = <&xtal_27Mhz>; clocks = <&xtal_27Mhz>;
#clock-cells = <1>; #clock-cells = <1>;
xtal-load-pf = <5>; xtal-load-pf = <5>;
vdd-supply = <&1v8-reg>;
vddout-supply = <&3v3-reg>;
/* PLL options to get SSC 1% centered */ /* PLL options to get SSC 1% centered */
PLL2 { PLL2 {
spread-spectrum = <4>; spread-spectrum = <4>;
......
...@@ -64,11 +64,10 @@ static unsigned int _get_table_val(const struct clk_factor_table *table, ...@@ -64,11 +64,10 @@ static unsigned int _get_table_val(const struct clk_factor_table *table,
return val; return val;
} }
static int clk_val_best(struct clk_hw *hw, unsigned long rate, static int owl_clk_val_best(const struct owl_factor_hw *factor_hw,
struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate) unsigned long *best_parent_rate)
{ {
struct owl_factor *factor = hw_to_owl_factor(hw);
struct owl_factor_hw *factor_hw = &factor->factor_hw;
const struct clk_factor_table *clkt = factor_hw->table; const struct clk_factor_table *clkt = factor_hw->table;
unsigned long parent_rate, try_parent_rate, best = 0, cur_rate; unsigned long parent_rate, try_parent_rate, best = 0, cur_rate;
unsigned long parent_rate_saved = *best_parent_rate; unsigned long parent_rate_saved = *best_parent_rate;
...@@ -126,7 +125,7 @@ long owl_factor_helper_round_rate(struct owl_clk_common *common, ...@@ -126,7 +125,7 @@ long owl_factor_helper_round_rate(struct owl_clk_common *common,
const struct clk_factor_table *clkt = factor_hw->table; const struct clk_factor_table *clkt = factor_hw->table;
unsigned int val, mul = 0, div = 1; unsigned int val, mul = 0, div = 1;
val = clk_val_best(&common->hw, rate, parent_rate); val = owl_clk_val_best(factor_hw, &common->hw, rate, parent_rate);
_get_table_div_mul(clkt, val, &mul, &div); _get_table_div_mul(clkt, val, &mul, &div);
return *parent_rate * mul / div; return *parent_rate * mul / div;
......
This diff is collapsed.
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/gcd.h> #include <linux/gcd.h>
...@@ -602,6 +603,30 @@ of_clk_cdce925_get(struct of_phandle_args *clkspec, void *_data) ...@@ -602,6 +603,30 @@ of_clk_cdce925_get(struct of_phandle_args *clkspec, void *_data)
return &data->clk[idx].hw; return &data->clk[idx].hw;
} }
static void cdce925_regulator_disable(void *regulator)
{
regulator_disable(regulator);
}
static int cdce925_regulator_enable(struct device *dev, const char *name)
{
struct regulator *regulator;
int err;
regulator = devm_regulator_get(dev, name);
if (IS_ERR(regulator))
return PTR_ERR(regulator);
err = regulator_enable(regulator);
if (err) {
dev_err(dev, "Failed to enable %s: %d\n", name, err);
return err;
}
return devm_add_action_or_reset(dev, cdce925_regulator_disable,
regulator);
}
/* The CDCE925 uses a funky way to read/write registers. Bulk mode is /* The CDCE925 uses a funky way to read/write registers. Bulk mode is
* just weird, so just use the single byte mode exclusively. */ * just weird, so just use the single byte mode exclusively. */
static struct regmap_bus regmap_cdce925_bus = { static struct regmap_bus regmap_cdce925_bus = {
...@@ -630,6 +655,15 @@ static int cdce925_probe(struct i2c_client *client, ...@@ -630,6 +655,15 @@ static int cdce925_probe(struct i2c_client *client,
}; };
dev_dbg(&client->dev, "%s\n", __func__); dev_dbg(&client->dev, "%s\n", __func__);
err = cdce925_regulator_enable(&client->dev, "vdd");
if (err)
return err;
err = cdce925_regulator_enable(&client->dev, "vddout");
if (err)
return err;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
......
...@@ -37,6 +37,12 @@ static HLIST_HEAD(clk_root_list); ...@@ -37,6 +37,12 @@ static HLIST_HEAD(clk_root_list);
static HLIST_HEAD(clk_orphan_list); static HLIST_HEAD(clk_orphan_list);
static LIST_HEAD(clk_notifier_list); static LIST_HEAD(clk_notifier_list);
static struct hlist_head *all_lists[] = {
&clk_root_list,
&clk_orphan_list,
NULL,
};
/*** private data structures ***/ /*** private data structures ***/
struct clk_parent_map { struct clk_parent_map {
...@@ -2841,12 +2847,6 @@ static int inited = 0; ...@@ -2841,12 +2847,6 @@ static int inited = 0;
static DEFINE_MUTEX(clk_debug_lock); static DEFINE_MUTEX(clk_debug_lock);
static HLIST_HEAD(clk_debug_list); static HLIST_HEAD(clk_debug_list);
static struct hlist_head *all_lists[] = {
&clk_root_list,
&clk_orphan_list,
NULL,
};
static struct hlist_head *orphan_list[] = { static struct hlist_head *orphan_list[] = {
&clk_orphan_list, &clk_orphan_list,
NULL, NULL,
...@@ -3777,6 +3777,34 @@ static const struct clk_ops clk_nodrv_ops = { ...@@ -3777,6 +3777,34 @@ static const struct clk_ops clk_nodrv_ops = {
.set_parent = clk_nodrv_set_parent, .set_parent = clk_nodrv_set_parent,
}; };
static void clk_core_evict_parent_cache_subtree(struct clk_core *root,
struct clk_core *target)
{
int i;
struct clk_core *child;
for (i = 0; i < root->num_parents; i++)
if (root->parents[i].core == target)
root->parents[i].core = NULL;
hlist_for_each_entry(child, &root->children, child_node)
clk_core_evict_parent_cache_subtree(child, target);
}
/* Remove this clk from all parent caches */
static void clk_core_evict_parent_cache(struct clk_core *core)
{
struct hlist_head **lists;
struct clk_core *root;
lockdep_assert_held(&prepare_lock);
for (lists = all_lists; *lists; lists++)
hlist_for_each_entry(root, *lists, child_node)
clk_core_evict_parent_cache_subtree(root, core);
}
/** /**
* clk_unregister - unregister a currently registered clock * clk_unregister - unregister a currently registered clock
* @clk: clock to unregister * @clk: clock to unregister
...@@ -3815,6 +3843,8 @@ void clk_unregister(struct clk *clk) ...@@ -3815,6 +3843,8 @@ void clk_unregister(struct clk *clk)
clk_core_set_parent_nolock(child, NULL); clk_core_set_parent_nolock(child, NULL);
} }
clk_core_evict_parent_cache(clk->core);
hlist_del_init(&clk->core->child_node); hlist_del_init(&clk->core->child_node);
if (clk->core->prepare_count) if (clk->core->prepare_count)
......
...@@ -58,3 +58,5 @@ ...@@ -58,3 +58,5 @@
#define BCM2835_CLOCK_DSI1E 48 #define BCM2835_CLOCK_DSI1E 48
#define BCM2835_CLOCK_DSI0P 49 #define BCM2835_CLOCK_DSI0P 49
#define BCM2835_CLOCK_DSI1P 50 #define BCM2835_CLOCK_DSI1P 50
#define BCM2711_CLOCK_EMMC2 51
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment