Re: [PATCH v14 4/5] clk: sophgo: Add SG2042 clock driver
From: Stephen Boyd
Date: Mon Apr 22 2024 - 20:47:48 EST
Quoting Chen Wang (2024-04-15 00:23:27)
> diff --git a/drivers/clk/sophgo/clk-sophgo-sg2042.c b/drivers/clk/sophgo/clk-sophgo-sg2042.c
> new file mode 100644
> index 000000000000..0bcfaab52f51
> --- /dev/null
> +++ b/drivers/clk/sophgo/clk-sophgo-sg2042.c
> @@ -0,0 +1,1645 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Sophgo SG2042 Clock Generator Driver
> + *
> + * Copyright (C) 2024 Sophgo Technology Inc. All rights reserved.
> + */
> +
> +#include <asm/div64.h>
asm goes after linux includes...
> +#include <linux/array_size.h>
> +#include <linux/bits.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/platform_device.h>
here.
> +
> +/*
> + * The clock of SG2042 is composed of three parts.
> + * The registers of these three parts of the clock are scattered in three
> + * different memory address spaces:
> + * - pll clocks
> + * - gate clocks for RP subsystem
> + * - div/mux, and gate clocks working for other subsystem than RP subsystem
> + */
> +#include <dt-bindings/clock/sophgo,sg2042-pll.h>
> +#include <dt-bindings/clock/sophgo,sg2042-rpgate.h>
> +#include <dt-bindings/clock/sophgo,sg2042-clkgen.h>
> +
> +/* Registers defined in SYS_CTRL */
> +#define R_PLL_BEGIN 0xC0
[...]
> +
> +#define SG2042_PLL(_id, _name, _parent_name, _r_stat, _r_enable, _r_ctrl, _shift) \
> + { \
> + .hw.init = CLK_HW_INIT( \
> + _name, \
> + _parent_name, \
This still uses a string. Please convert all parents described by
strings to use clk_parent_data or clk_hw directly.
> + &sg2042_clk_pll_ops, \
> + CLK_GET_RATE_NOCACHE | CLK_GET_ACCURACY_NOCACHE),\
> + .id = _id, \
> + .offset_ctrl = _r_ctrl, \
> + .offset_status = _r_stat, \
> + .offset_enable = _r_enable, \
> + .shift_status_lock = 8 + (_shift), \
> + .shift_status_updating = _shift, \
[...]
> + * "clk_div_ddr01_1" is the name of Clock divider 1 control of DDR01, and
> + * "clk_gate_ddr01_div1" is the gate clock in front of the "clk_div_ddr01_1",
> + * they are both controlled by register CLKDIVREG28;
> + * While for register value of mux selection, use Clock Select for DDR01’s clock
> + * as example, see CLKSELREG0, bit[2].
> + * 1: Select in_dpll0_clk as clock source, correspondng to the parent input
> + * source from "clk_div_ddr01_0".
> + * 0: Select in_fpll_clk as clock source, corresponding to the parent input
> + * source from "clk_div_ddr01_1".
> + * So we need a table to define the array of register values corresponding to
> + * the parent index and tell CCF about this when registering mux clock.
> + */
> +static const u32 sg2042_mux_table[] = {1, 0};
> +
> +static const struct clk_parent_data clk_mux_ddr01_p[] = {
> + { .hw = &sg2042_div_clks[0].hw },
> + { .hw = &sg2042_div_clks[1].hw },
Just use struct clk_init_data::parent_hws for this if you only have a
clk_hw pointer for every element of the parent array.
> +};
> +
> +static const struct clk_parent_data clk_mux_ddr23_p[] = {
> + { .hw = &sg2042_div_clks[2].hw },
> + { .hw = &sg2042_div_clks[3].hw },
> +};
> +
[...]
> +
> +static int sg2042_pll_probe(struct platform_device *pdev)
> +{
> + struct sg2042_clk_data *clk_data = NULL;
> + int i, ret = 0;
> + int num_clks = 0;
> +
> + num_clks = ARRAY_SIZE(sg2042_pll_clks);
> +
> + ret = sg2042_init_clkdata(pdev, num_clks, &clk_data);
> + if (ret < 0)
> + goto error_out;
> +
> + ret = sg2042_clk_register_plls(&pdev->dev, clk_data, sg2042_pll_clks,
> + num_clks);
> + if (ret)
> + goto cleanup;
> +
> + return devm_of_clk_add_hw_provider(&pdev->dev,
> + of_clk_hw_onecell_get,
> + &clk_data->onecell_data);
> +
> +cleanup:
> + for (i = 0; i < num_clks; i++) {
> + if (clk_data->onecell_data.hws[i])
> + clk_hw_unregister(clk_data->onecell_data.hws[i]);
This should be unnecessary if devm is used throughout.
> + }
> +
> +error_out:
> + pr_err("%s failed error number %d\n", __func__, ret);
> + return ret;
Just do this part in the one place the goto is. These two comments apply
to all probes.