Skip to content

Commit

Permalink
Merge tag 'clk-meson-v6.13-1' of https://github.com/BayLibre/clk-meson
Browse files Browse the repository at this point in the history
…into clk-amlogic

Pull Amlogic clk driver updates from Jerome Brunet:

 - Fix hifi_pll rate calculation on Amlogic s4 and c3
 - Move audio reset implementation from the Amlogic axg-audio clock
   controller driver to the reset directory, using the auxiliary device
   bus
 - Remove the unnecessary spinlock in the Amlogic mpll driver
 - Fix Amlogic meson8 clock controller DT bindings

* tag 'clk-meson-v6.13-1' of https://github.com/BayLibre/clk-meson:
  clk: amlogic: axg-audio: use the auxiliary reset driver
  reset: amlogic: Fix small whitespace issue
  reset: amlogic: add auxiliary reset driver support
  reset: amlogic: split the device core and platform probe
  reset: amlogic: move drivers to a dedicated directory
  reset: amlogic: add reset status support
  reset: amlogic: use reset number instead of register count
  reset: amlogic: add driver parameters
  reset: amlogic: make parameters unsigned
  reset: amlogic: use generic data matching function
  reset: amlogic: convert driver to regmap
  dt-bindings: clock: convert amlogic,meson8b-clkc.txt to dtschema
  clk: meson: meson8b: remove spinlock
  clk: meson: mpll: Delete a useless spinlock from the MPLL
  clk: meson: s4: pll: fix frac maximum value for hifi_pll
  clk: meson: c3: pll: fix frac maximum value for hifi_pll
  clk: meson: Support PLL with fixed fractional denominators
  clk: meson: s4: pll: hifi_pll support fractional multiplier
  • Loading branch information
bebarino committed Nov 6, 2024
2 parents 9852d85 + 664988e commit c601478
Show file tree
Hide file tree
Showing 25 changed files with 535 additions and 376 deletions.
45 changes: 45 additions & 0 deletions Documentation/devicetree/bindings/clock/amlogic,meson8-clkc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/amlogic,meson8-clkc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Amlogic Meson8, Meson8b and Meson8m2 Clock and Reset Controller

maintainers:
- Neil Armstrong <[email protected]>

properties:
compatible:
oneOf:
- enum:
- amlogic,meson8-clkc
- amlogic,meson8b-clkc
- items:
- const: amlogic,meson8m2-clkc
- const: amlogic,meson8-clkc

clocks:
minItems: 2
maxItems: 3

clock-names:
minItems: 2
items:
- const: xtal
- const: ddr_pll
- const: clk_32k

'#clock-cells':
const: 1

'#reset-cells':
const: 1

required:
- compatible
- clocks
- clock-names
- '#reset-cells'

additionalProperties: false
51 changes: 0 additions & 51 deletions Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt

This file was deleted.

1 change: 1 addition & 0 deletions drivers/clk/meson/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ config COMMON_CLK_AXG_AUDIO
select COMMON_CLK_MESON_SCLK_DIV
select COMMON_CLK_MESON_CLKC_UTILS
select REGMAP_MMIO
imply RESET_MESON_AUX
help
Support for the audio clock controller on AmLogic A113D devices,
aka axg, Say Y if you want audio subsystem to work.
Expand Down
109 changes: 9 additions & 100 deletions drivers/clk/meson/axg-audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <linux/reset-controller.h>
#include <linux/slab.h>

#include <soc/amlogic/reset-meson-aux.h>

#include "meson-clkc-utils.h"
#include "axg-audio.h"
#include "clk-regmap.h"
Expand Down Expand Up @@ -1678,84 +1680,6 @@ static struct clk_regmap *const sm1_clk_regmaps[] = {
&sm1_earcrx_dmac_clk,
};

struct axg_audio_reset_data {
struct reset_controller_dev rstc;
struct regmap *map;
unsigned int offset;
};

static void axg_audio_reset_reg_and_bit(struct axg_audio_reset_data *rst,
unsigned long id,
unsigned int *reg,
unsigned int *bit)
{
unsigned int stride = regmap_get_reg_stride(rst->map);

*reg = (id / (stride * BITS_PER_BYTE)) * stride;
*reg += rst->offset;
*bit = id % (stride * BITS_PER_BYTE);
}

static int axg_audio_reset_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct axg_audio_reset_data *rst =
container_of(rcdev, struct axg_audio_reset_data, rstc);
unsigned int offset, bit;

axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);

regmap_update_bits(rst->map, offset, BIT(bit),
assert ? BIT(bit) : 0);

return 0;
}

static int axg_audio_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct axg_audio_reset_data *rst =
container_of(rcdev, struct axg_audio_reset_data, rstc);
unsigned int val, offset, bit;

axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);

regmap_read(rst->map, offset, &val);

return !!(val & BIT(bit));
}

static int axg_audio_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return axg_audio_reset_update(rcdev, id, true);
}

static int axg_audio_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return axg_audio_reset_update(rcdev, id, false);
}

static int axg_audio_reset_toggle(struct reset_controller_dev *rcdev,
unsigned long id)
{
int ret;

ret = axg_audio_reset_assert(rcdev, id);
if (ret)
return ret;

return axg_audio_reset_deassert(rcdev, id);
}

static const struct reset_control_ops axg_audio_rstc_ops = {
.assert = axg_audio_reset_assert,
.deassert = axg_audio_reset_deassert,
.reset = axg_audio_reset_toggle,
.status = axg_audio_reset_status,
};

static struct regmap_config axg_audio_regmap_cfg = {
.reg_bits = 32,
.val_bits = 32,
Expand All @@ -1766,16 +1690,14 @@ struct audioclk_data {
struct clk_regmap *const *regmap_clks;
unsigned int regmap_clk_num;
struct meson_clk_hw_data hw_clks;
unsigned int reset_offset;
unsigned int reset_num;
unsigned int max_register;
const char *rst_drvname;
};

static int axg_audio_clkc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct audioclk_data *data;
struct axg_audio_reset_data *rst;
struct regmap *map;
void __iomem *regs;
struct clk_hw *hw;
Expand Down Expand Up @@ -1834,22 +1756,11 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
if (ret)
return ret;

/* Stop here if there is no reset */
if (!data->reset_num)
return 0;

rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
if (!rst)
return -ENOMEM;

rst->map = map;
rst->offset = data->reset_offset;
rst->rstc.nr_resets = data->reset_num;
rst->rstc.ops = &axg_audio_rstc_ops;
rst->rstc.of_node = dev->of_node;
rst->rstc.owner = THIS_MODULE;
/* Register auxiliary reset driver when applicable */
if (data->rst_drvname)
ret = devm_meson_rst_aux_register(dev, map, data->rst_drvname);

return devm_reset_controller_register(dev, &rst->rstc);
return ret;
}

static const struct audioclk_data axg_audioclk_data = {
Expand All @@ -1869,9 +1780,8 @@ static const struct audioclk_data g12a_audioclk_data = {
.hws = g12a_audio_hw_clks,
.num = ARRAY_SIZE(g12a_audio_hw_clks),
},
.reset_offset = AUDIO_SW_RESET,
.reset_num = 26,
.max_register = AUDIO_CLK_SPDIFOUT_B_CTRL,
.rst_drvname = "rst-g12a",
};

static const struct audioclk_data sm1_audioclk_data = {
Expand All @@ -1881,9 +1791,8 @@ static const struct audioclk_data sm1_audioclk_data = {
.hws = sm1_audio_hw_clks,
.num = ARRAY_SIZE(sm1_audio_hw_clks),
},
.reset_offset = AUDIO_SM1_SW_RESET0,
.reset_num = 39,
.max_register = AUDIO_EARCRX_DMAC_CLK_CTRL,
.rst_drvname = "rst-sm1",
};

static const struct of_device_id clkc_match_table[] = {
Expand Down
6 changes: 0 additions & 6 deletions drivers/clk/meson/axg.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@

#include <dt-bindings/clock/axg-clkc.h>

static DEFINE_SPINLOCK(meson_clk_lock);

static struct clk_regmap axg_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
Expand Down Expand Up @@ -506,7 +504,6 @@ static struct clk_regmap axg_mpll0_div = {
.shift = 0,
.width = 1,
},
.lock = &meson_clk_lock,
.flags = CLK_MESON_MPLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
Expand Down Expand Up @@ -557,7 +554,6 @@ static struct clk_regmap axg_mpll1_div = {
.shift = 1,
.width = 1,
},
.lock = &meson_clk_lock,
.flags = CLK_MESON_MPLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
Expand Down Expand Up @@ -613,7 +609,6 @@ static struct clk_regmap axg_mpll2_div = {
.shift = 2,
.width = 1,
},
.lock = &meson_clk_lock,
.flags = CLK_MESON_MPLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
Expand Down Expand Up @@ -664,7 +659,6 @@ static struct clk_regmap axg_mpll3_div = {
.shift = 3,
.width = 1,
},
.lock = &meson_clk_lock,
.flags = CLK_MESON_MPLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
Expand Down
1 change: 1 addition & 0 deletions drivers/clk/meson/c3-pll.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ static struct clk_regmap hifi_pll_dco = {
.range = &c3_gp0_pll_mult_range,
.init_regs = c3_hifi_init_regs,
.init_count = ARRAY_SIZE(c3_hifi_init_regs),
.frac_max = 100000,
},
.hw.init = &(struct clk_init_data) {
.name = "hifi_pll_dco",
Expand Down
11 changes: 0 additions & 11 deletions drivers/clk/meson/clk-mpll.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,26 +112,15 @@ static int mpll_set_rate(struct clk_hw *hw,
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk);
unsigned int sdm, n2;
unsigned long flags = 0;

params_from_rate(rate, parent_rate, &sdm, &n2, mpll->flags);

if (mpll->lock)
spin_lock_irqsave(mpll->lock, flags);
else
__acquire(mpll->lock);

/* Set the fractional part */
meson_parm_write(clk->map, &mpll->sdm, sdm);

/* Set the integer divider part */
meson_parm_write(clk->map, &mpll->n2, n2);

if (mpll->lock)
spin_unlock_irqrestore(mpll->lock, flags);
else
__release(mpll->lock);

return 0;
}

Expand Down
1 change: 0 additions & 1 deletion drivers/clk/meson/clk-mpll.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ struct meson_clk_mpll_data {
struct parm misc;
const struct reg_sequence *init_regs;
unsigned int init_count;
spinlock_t *lock;
u8 flags;
};

Expand Down
8 changes: 5 additions & 3 deletions drivers/clk/meson/clk-pll.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,13 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
struct meson_clk_pll_data *pll)
{
u64 rate = (u64)parent_rate * m;
unsigned int frac_max = pll->frac_max ? pll->frac_max :
(1 << pll->frac.width);

if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
u64 frac_rate = (u64)parent_rate * frac;

rate += DIV_ROUND_UP_ULL(frac_rate,
(1 << pll->frac.width));
rate += DIV_ROUND_UP_ULL(frac_rate, frac_max);
}

return DIV_ROUND_UP_ULL(rate, n);
Expand Down Expand Up @@ -100,7 +101,8 @@ static unsigned int __pll_params_with_frac(unsigned long rate,
unsigned int n,
struct meson_clk_pll_data *pll)
{
unsigned int frac_max = (1 << pll->frac.width);
unsigned int frac_max = pll->frac_max ? pll->frac_max :
(1 << pll->frac.width);
u64 val = (u64)rate * n;

/* Bail out if we are already over the requested rate */
Expand Down
1 change: 1 addition & 0 deletions drivers/clk/meson/clk-pll.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ struct meson_clk_pll_data {
unsigned int init_count;
const struct pll_params_table *table;
const struct pll_mult_range *range;
unsigned int frac_max;
u8 flags;
};

Expand Down
Loading

0 comments on commit c601478

Please sign in to comment.