lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:   Tue, 12 Jan 2021 11:48:45 -0800
From:   Stephen Boyd <sboyd@...nel.org>
To:     dan.j.williams@...el.com, devicetree@...r.kernel.org,
        dmaengine@...r.kernel.org, gengdongjiu@...wei.com,
        linux-clk@...r.kernel.org, linux-kernel@...r.kernel.org,
        mturquette@...libre.com, p.zabel@...gutronix.de,
        robh+dt@...nel.org, vkoul@...nel.org
Subject: Re: [PATCH v7 2/4] clk: hisilicon: Add clock driver for hi3559A SoC

Quoting Dongjiu Geng (2020-12-15 03:09:45)
> diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile
> index b2441b99f3d5..bc101833b35e 100644
> --- a/drivers/clk/hisilicon/Makefile
> +++ b/drivers/clk/hisilicon/Makefile
> @@ -17,3 +17,4 @@ obj-$(CONFIG_COMMON_CLK_HI6220)       += clk-hi6220.o
>  obj-$(CONFIG_RESET_HISI)       += reset.o
>  obj-$(CONFIG_STUB_CLK_HI6220)  += clk-hi6220-stub.o
>  obj-$(CONFIG_STUB_CLK_HI3660)  += clk-hi3660-stub.o
> +obj-$(CONFIG_COMMON_CLK_HI3559A)       += clk-hi3559a.o

Can this file be sorted somehow?

> diff --git a/drivers/clk/hisilicon/clk-hi3559a.c b/drivers/clk/hisilicon/clk-hi3559a.c
> new file mode 100644
> index 000000000000..d7693e488006
> --- /dev/null
> +++ b/drivers/clk/hisilicon/clk-hi3559a.c
> @@ -0,0 +1,865 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Hisilicon Hi3559A clock driver
> + *
> + * Copyright (c) 2019-2020, Huawei Tech. Co., Ltd.
> + *
> + * Author: Dongjiu Geng <gengdongjiu@...wei.com>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +
> +#include <dt-bindings/clock/hi3559av100-clock.h>
> +
> +#include "clk.h"
> +#include "crg.h"
> +#include "reset.h"
> +
> +#define CRG_BASE_ADDR  0x18020000
> +
> +struct hi3559av100_pll_clock {
> +       u32     id;

unsigned int?

> +       const char  *name;
> +       const char  *parent_name;
> +       u32     ctrl_reg1;
> +       u8      frac_shift;
> +       u8      frac_width;
> +       u8      postdiv1_shift;
> +       u8      postdiv1_width;
> +       u8      postdiv2_shift;
> +       u8      postdiv2_width;
> +       u32     ctrl_reg2;
> +       u8      fbdiv_shift;
> +       u8      fbdiv_width;
> +       u8      refdiv_shift;
> +       u8      refdiv_width;
> +};
> +
> +struct hi3559av100_clk_pll {
> +       struct clk_hw   hw;
> +       u32     id;
> +       void __iomem    *ctrl_reg1;
> +       u8      frac_shift;
> +       u8      frac_width;
> +       u8      postdiv1_shift;
> +       u8      postdiv1_width;
> +       u8      postdiv2_shift;
> +       u8      postdiv2_width;
> +       void __iomem    *ctrl_reg2;
> +       u8      fbdiv_shift;
> +       u8      fbdiv_width;
> +       u8      refdiv_shift;
> +       u8      refdiv_width;
> +};
> +
> +/* soc clk config */
> +static const struct hisi_fixed_rate_clock hi3559av100_fixed_rate_clks_crg[] = {
> +       { HI3559AV100_FIXED_1188M, "1188m",   NULL, 0, 1188000000, },
> +       { HI3559AV100_FIXED_1000M, "1000m",   NULL, 0, 1000000000, },
> +       { HI3559AV100_FIXED_842M, "842m",    NULL, 0, 842000000, },
> +       { HI3559AV100_FIXED_792M, "792m",    NULL, 0, 792000000, },
> +       { HI3559AV100_FIXED_750M, "750m",    NULL, 0, 750000000, },
> +       { HI3559AV100_FIXED_710M, "710m",    NULL, 0, 710000000, },
> +       { HI3559AV100_FIXED_680M, "680m",    NULL, 0, 680000000, },
> +       { HI3559AV100_FIXED_667M, "667m",    NULL, 0, 667000000, },
> +       { HI3559AV100_FIXED_631M, "631m",    NULL, 0, 631000000, },
> +       { HI3559AV100_FIXED_600M, "600m",    NULL, 0, 600000000, },
> +       { HI3559AV100_FIXED_568M, "568m",    NULL, 0, 568000000, },
> +       { HI3559AV100_FIXED_500M, "500m",    NULL, 0, 500000000, },
> +       { HI3559AV100_FIXED_475M, "475m",    NULL, 0, 475000000, },
> +       { HI3559AV100_FIXED_428M, "428m",    NULL, 0, 428000000, },
> +       { HI3559AV100_FIXED_400M, "400m",    NULL, 0, 400000000, },
> +       { HI3559AV100_FIXED_396M, "396m",    NULL, 0, 396000000, },
> +       { HI3559AV100_FIXED_300M, "300m",    NULL, 0, 300000000, },
> +       { HI3559AV100_FIXED_250M, "250m",    NULL, 0, 250000000, },
> +       { HI3559AV100_FIXED_200M, "200m",    NULL, 0, 200000000, },
> +       { HI3559AV100_FIXED_198M, "198m",    NULL, 0, 198000000, },
> +       { HI3559AV100_FIXED_187p5M, "187p5m",  NULL, 0, 187500000, },
> +       { HI3559AV100_FIXED_150M, "150m",    NULL, 0, 150000000, },
> +       { HI3559AV100_FIXED_148p5M, "148p5m",  NULL, 0, 1485000000, },
> +       { HI3559AV100_FIXED_125M, "125m",    NULL, 0, 125000000, },
> +       { HI3559AV100_FIXED_107M, "107m",    NULL, 0, 107000000, },
> +       { HI3559AV100_FIXED_100M, "100m",    NULL, 0, 100000000, },
> +       { HI3559AV100_FIXED_99M, "99m",     NULL, 0, 99000000, },
> +       { HI3559AV100_FIXED_75M, "75m",  NULL, 0, 75000000, },
> +       { HI3559AV100_FIXED_74p25M, "74p25m",  NULL, 0, 74250000, },
> +       { HI3559AV100_FIXED_72M, "72m",     NULL, 0, 72000000, },
> +       { HI3559AV100_FIXED_60M, "60m",     NULL, 0, 60000000, },
> +       { HI3559AV100_FIXED_54M, "54m",     NULL, 0, 54000000, },
> +       { HI3559AV100_FIXED_50M, "50m",     NULL, 0, 50000000, },
> +       { HI3559AV100_FIXED_49p5M, "49p5m",   NULL, 0, 49500000, },
> +       { HI3559AV100_FIXED_37p125M, "37p125m", NULL, 0, 37125000, },
> +       { HI3559AV100_FIXED_36M, "36m",     NULL, 0, 36000000, },
> +       { HI3559AV100_FIXED_32p4M, "32p4m",   NULL, 0, 32400000, },
> +       { HI3559AV100_FIXED_27M, "27m",     NULL, 0, 27000000, },
> +       { HI3559AV100_FIXED_25M, "25m",     NULL, 0, 25000000, },
> +       { HI3559AV100_FIXED_24M, "24m",     NULL, 0, 24000000, },
> +       { HI3559AV100_FIXED_12M, "12m",     NULL, 0, 12000000, },
> +       { HI3559AV100_FIXED_3M,  "3m",      NULL, 0, 3000000, },
> +       { HI3559AV100_FIXED_1p6M, "1p6m",    NULL, 0, 1600000, },
> +       { HI3559AV100_FIXED_400K, "400k",    NULL, 0, 400000, },
> +       { HI3559AV100_FIXED_100K, "100k",    NULL, 0, 100000, },
> +};
> +
> +
> +static const char *fmc_mux_p[] __initconst = {
> +       "24m", "75m", "125m", "150m", "200m", "250m", "300m", "400m"
> +};
> +static u32 fmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7};

const?

> +
> +static const char *mmc_mux_p[] __initconst = {
> +       "100k", "25m", "49p5m", "99m", "187p5m", "150m", "198m", "400k"
> +};
> +static u32 mmc_mux_table[] = {0, 1, 2, 3, 4, 5, 6, 7};

const?

> +
> +static const char *sysapb_mux_p[] __initconst = {
> +       "24m", "50m",
> +};
> +static u32 sysapb_mux_table[] = {0, 1};

const?

> +
> +static const char *sysbus_mux_p[] __initconst = {
> +       "24m", "300m"
> +};
> +static u32 sysbus_mux_table[] = {0, 1};

const?

> +
> +static const char *uart_mux_p[] __initconst = {"50m", "24m", "3m"};
> +static u32 uart_mux_table[] = {0, 1, 2};

const?

> +
> +static const char *a73_clksel_mux_p[] __initconst = {
> +       "24m", "apll", "1000m"
> +};
> +static u32 a73_clksel_mux_table[] = {0, 1, 2};

const?

Please also add space after { and before }.

> +
> +static struct hisi_mux_clock hi3559av100_mux_clks_crg[] __initdata = {
> +       {
> +               HI3559AV100_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
> +               CLK_SET_RATE_PARENT, 0x170, 2, 3, 0, fmc_mux_table,
> +       },
> +       {
> +               HI3559AV100_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
> +               CLK_SET_RATE_PARENT, 0x1a8, 24, 3, 0, mmc_mux_table,
> +       },
> +       {
> +               HI3559AV100_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
> +               CLK_SET_RATE_PARENT, 0x1ec, 24, 3, 0, mmc_mux_table,
> +       },
> +
> +       {
> +               HI3559AV100_MMC2_MUX, "mmc2_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
> +               CLK_SET_RATE_PARENT, 0x214, 24, 3, 0, mmc_mux_table,
> +       },
> +
> +       {
> +               HI3559AV100_MMC3_MUX, "mmc3_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
> +               CLK_SET_RATE_PARENT, 0x23c, 24, 3, 0, mmc_mux_table,
> +       },
> +
> +       {
> +               HI3559AV100_SYSAPB_MUX, "sysapb_mux", sysapb_mux_p, ARRAY_SIZE(sysapb_mux_p),
> +               CLK_SET_RATE_PARENT, 0xe8, 3, 1, 0, sysapb_mux_table
> +       },
> +
> +       {
> +               HI3559AV100_SYSBUS_MUX, "sysbus_mux", sysbus_mux_p, ARRAY_SIZE(sysbus_mux_p),
> +               CLK_SET_RATE_PARENT, 0xe8, 0, 1, 0, sysbus_mux_table
> +       },
> +
> +       {
> +               HI3559AV100_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p),
> +               CLK_SET_RATE_PARENT, 0x198, 28, 2, 0, uart_mux_table
> +       },
> +
> +       {
> +               HI3559AV100_A73_MUX, "a73_mux", a73_clksel_mux_p, ARRAY_SIZE(a73_clksel_mux_p),
> +               CLK_SET_RATE_PARENT, 0xe4, 0, 2, 0, a73_clksel_mux_table
> +       },
> +};
> +
> +static struct hisi_fixed_factor_clock hi3559av100_fixed_factor_clks[] __initdata
> +       = {
> +};

This looks weird.

> +
> +static struct hisi_gate_clock hi3559av100_gate_clks[] __initdata = {
> +       {
> +               HI3559AV100_FMC_CLK, "clk_fmc", "fmc_mux",
> +               CLK_SET_RATE_PARENT, 0x170, 1, 0,
> +       },
> +       {
> +               HI3559AV100_MMC0_CLK, "clk_mmc0", "mmc0_mux",
> +               CLK_SET_RATE_PARENT, 0x1a8, 28, 0,
> +       },
> +       {
> +               HI3559AV100_MMC1_CLK, "clk_mmc1", "mmc1_mux",
> +               CLK_SET_RATE_PARENT, 0x1ec, 28, 0,
> +       },
> +       {
> +               HI3559AV100_MMC2_CLK, "clk_mmc2", "mmc2_mux",
> +               CLK_SET_RATE_PARENT, 0x214, 28, 0,
> +       },
> +       {
> +               HI3559AV100_MMC3_CLK, "clk_mmc3", "mmc3_mux",
> +               CLK_SET_RATE_PARENT, 0x23c, 28, 0,
> +       },
> +       {
> +               HI3559AV100_UART0_CLK, "clk_uart0", "uart_mux",
> +               CLK_SET_RATE_PARENT, 0x198, 23, 0,
> +       },
> +       {
> +               HI3559AV100_UART1_CLK, "clk_uart1", "uart_mux",
> +               CLK_SET_RATE_PARENT, 0x198, 24, 0,
> +       },
> +       {
> +               HI3559AV100_UART2_CLK, "clk_uart2", "uart_mux",
> +               CLK_SET_RATE_PARENT, 0x198, 25, 0,
> +       },
> +       {
> +               HI3559AV100_UART3_CLK, "clk_uart3", "uart_mux",
> +               CLK_SET_RATE_PARENT, 0x198, 26, 0,
> +       },
> +       {
> +               HI3559AV100_UART4_CLK, "clk_uart4", "uart_mux",
> +               CLK_SET_RATE_PARENT, 0x198, 27, 0,
> +       },
> +       {
> +               HI3559AV100_ETH_CLK, "clk_eth", NULL,
> +               CLK_SET_RATE_PARENT, 0x0174, 1, 0,
> +       },
> +       {
> +               HI3559AV100_ETH_MACIF_CLK, "clk_eth_macif", NULL,
> +               CLK_SET_RATE_PARENT, 0x0174, 5, 0,
> +       },
> +       {
> +               HI3559AV100_ETH1_CLK, "clk_eth1", NULL,
> +               CLK_SET_RATE_PARENT, 0x0174, 3, 0,
> +       },
> +       {
> +               HI3559AV100_ETH1_MACIF_CLK, "clk_eth1_macif", NULL,
> +               CLK_SET_RATE_PARENT, 0x0174, 7, 0,
> +       },
> +       {
> +               HI3559AV100_I2C0_CLK, "clk_i2c0", "50m",
> +               CLK_SET_RATE_PARENT, 0x01a0, 16, 0,
> +       },
> +       {
> +               HI3559AV100_I2C1_CLK, "clk_i2c1", "50m",
> +               CLK_SET_RATE_PARENT, 0x01a0, 17, 0,
> +       },
> +       {
> +               HI3559AV100_I2C2_CLK, "clk_i2c2", "50m",
> +               CLK_SET_RATE_PARENT, 0x01a0, 18, 0,
> +       },
> +       {
> +               HI3559AV100_I2C3_CLK, "clk_i2c3", "50m",
> +               CLK_SET_RATE_PARENT, 0x01a0, 19, 0,
> +       },
> +       {
> +               HI3559AV100_I2C4_CLK, "clk_i2c4", "50m",
> +               CLK_SET_RATE_PARENT, 0x01a0, 20, 0,
> +       },
> +       {
> +               HI3559AV100_I2C5_CLK, "clk_i2c5", "50m",
> +               CLK_SET_RATE_PARENT, 0x01a0, 21, 0,
> +       },
> +       {
> +               HI3559AV100_I2C6_CLK, "clk_i2c6", "50m",
> +               CLK_SET_RATE_PARENT, 0x01a0, 22, 0,
> +       },
> +       {
> +               HI3559AV100_I2C7_CLK, "clk_i2c7", "50m",
> +               CLK_SET_RATE_PARENT, 0x01a0, 23, 0,
> +       },
> +       {
> +               HI3559AV100_I2C8_CLK, "clk_i2c8", "50m",
> +               CLK_SET_RATE_PARENT, 0x01a0, 24, 0,
> +       },
> +       {
> +               HI3559AV100_I2C9_CLK, "clk_i2c9", "50m",
> +               CLK_SET_RATE_PARENT, 0x01a0, 25, 0,
> +       },
> +       {
> +               HI3559AV100_I2C10_CLK, "clk_i2c10", "50m",
> +               CLK_SET_RATE_PARENT, 0x01a0, 26, 0,
> +       },
> +       {
> +               HI3559AV100_I2C11_CLK, "clk_i2c11", "50m",
> +               CLK_SET_RATE_PARENT, 0x01a0, 27, 0,
> +       },
> +       {
> +               HI3559AV100_SPI0_CLK, "clk_spi0", "100m",
> +               CLK_SET_RATE_PARENT, 0x0198, 16, 0,
> +       },
> +       {
> +               HI3559AV100_SPI1_CLK, "clk_spi1", "100m",
> +               CLK_SET_RATE_PARENT, 0x0198, 17, 0,
> +       },
> +       {
> +               HI3559AV100_SPI2_CLK, "clk_spi2", "100m",
> +               CLK_SET_RATE_PARENT, 0x0198, 18, 0,
> +       },
> +       {
> +               HI3559AV100_SPI3_CLK, "clk_spi3", "100m",
> +               CLK_SET_RATE_PARENT, 0x0198, 19, 0,
> +       },
> +       {
> +               HI3559AV100_SPI4_CLK, "clk_spi4", "100m",
> +               CLK_SET_RATE_PARENT, 0x0198, 20, 0,
> +       },
> +       {
> +               HI3559AV100_SPI5_CLK, "clk_spi5", "100m",
> +               CLK_SET_RATE_PARENT, 0x0198, 21, 0,
> +       },
> +       {
> +               HI3559AV100_SPI6_CLK, "clk_spi6", "100m",
> +               CLK_SET_RATE_PARENT, 0x0198, 22, 0,
> +       },
> +       {
> +               HI3559AV100_EDMAC_AXICLK, "axi_clk_edmac", NULL,
> +               CLK_SET_RATE_PARENT, 0x16c, 6, 0,
> +       },
> +       {
> +               HI3559AV100_EDMAC_CLK, "clk_edmac", NULL,
> +               CLK_SET_RATE_PARENT, 0x16c, 5, 0,

Is the CLK_SET_RATE_PARENT flag necessary all the time? Do all of these
clks actually have parents that the rate should be set on?

> +       },
> +       {
> +               HI3559AV100_EDMAC1_AXICLK, "axi_clk_edmac1", NULL,
> +               CLK_SET_RATE_PARENT, 0x16c, 9, 0,
> +       },
> +       {
> +               HI3559AV100_EDMAC1_CLK, "clk_edmac1", NULL,
> +               CLK_SET_RATE_PARENT, 0x16c, 8, 0,
> +       },
> +       {
> +               HI3559AV100_VDMAC_CLK, "clk_vdmac", NULL,
> +               CLK_SET_RATE_PARENT, 0x14c, 5, 0,
> +       },
> +};
> +
> +static struct hi3559av100_pll_clock hi3559av100_pll_clks[] __initdata = {
> +       {
> +               HI3559AV100_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3,
> +               0x4, 0, 12, 12, 6
> +       },
> +       {
> +               HI3559AV100_GPLL_CLK, "gpll", NULL, 0x20, 0, 24, 24, 3, 28, 3,
> +               0x24, 0, 12, 12, 6
> +       },
> +};
> +
> +#define to_pll_clk(_hw) container_of(_hw, struct hi3559av100_clk_pll, hw)
> +static void hi3559av100_calc_pll(u32 *frac_val, u32 *postdiv1_val,
> +                                u32 *postdiv2_val,
> +                                u32 *fbdiv_val, u32 *refdiv_val, u64 rate)
> +{
> +       u64 rem;
> +
> +       *postdiv1_val = 2;
> +       *postdiv2_val = 1;
> +
> +       rate = rate * ((*postdiv1_val) * (*postdiv2_val));
> +
> +       *frac_val = 0;
> +       rem = do_div(rate, 1000000);
> +       rem = do_div(rate, 24);
> +       *fbdiv_val = rate;
> +       *refdiv_val = 1;
> +       rem = rem * (1 << 24);
> +       do_div(rem, 24);

What is the significance of 24? Is it a mask width? Please add a define
if so.

> +       *frac_val = rem;
> +}
> +
> +static int clk_pll_set_rate(struct clk_hw *hw,
> +                           unsigned long rate,
> +                           unsigned long parent_rate)
> +{
> +       struct hi3559av100_clk_pll *clk = to_pll_clk(hw);
> +       u32 frac_val, postdiv1_val, postdiv2_val, fbdiv_val, refdiv_val;
> +       u32 val;
> +
> +       postdiv1_val = postdiv2_val = 0;
> +
> +       hi3559av100_calc_pll(&frac_val, &postdiv1_val, &postdiv2_val,
> +                            &fbdiv_val, &refdiv_val, (u64)rate);
> +
> +       val = readl_relaxed(clk->ctrl_reg1);
> +       val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift);
> +       val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift);
> +       val &= ~(((1 << clk->postdiv2_width) - 1) << clk->postdiv2_shift);

Make local variables for these masks please.

> +
> +       val |= frac_val << clk->frac_shift;
> +       val |= postdiv1_val << clk->postdiv1_shift;
> +       val |= postdiv2_val << clk->postdiv2_shift;
> +       writel_relaxed(val, clk->ctrl_reg1);
> +
> +       val = readl_relaxed(clk->ctrl_reg2);
> +       val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift);
> +       val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift);
> +
> +       val |= fbdiv_val << clk->fbdiv_shift;
> +       val |= refdiv_val << clk->refdiv_shift;
> +       writel_relaxed(val, clk->ctrl_reg2);
> +
> +       return 0;
> +}
> +
> +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
> +               unsigned long parent_rate)
> +{
> +       struct hi3559av100_clk_pll *clk = to_pll_clk(hw);
> +       u64 frac_val, fbdiv_val, refdiv_val;
> +       u32 postdiv1_val, postdiv2_val;
> +       u32 val;
> +       u64 tmp, rate;
> +
> +       val = readl_relaxed(clk->ctrl_reg1);
> +       val = val >> clk->frac_shift;
> +       val &= ((1 << clk->frac_width) - 1);
> +       frac_val = val;
> +
> +       val = readl_relaxed(clk->ctrl_reg1);
> +       val = val >> clk->postdiv1_shift;
> +       val &= ((1 << clk->postdiv1_width) - 1);
> +       postdiv1_val = val;
> +
> +       val = readl_relaxed(clk->ctrl_reg1);
> +       val = val >> clk->postdiv2_shift;
> +       val &= ((1 << clk->postdiv2_width) - 1);
> +       postdiv2_val = val;
> +
> +       val = readl_relaxed(clk->ctrl_reg2);
> +       val = val >> clk->fbdiv_shift;
> +       val &= ((1 << clk->fbdiv_width) - 1);
> +       fbdiv_val = val;
> +
> +       val = readl_relaxed(clk->ctrl_reg2);
> +       val = val >> clk->refdiv_shift;
> +       val &= ((1 << clk->refdiv_width) - 1);
> +       refdiv_val = val;
> +
> +       /* rate = 24000000 * (fbdiv + frac / (1<<24) ) / refdiv  */
> +       rate = 0;
> +       tmp = 24000000 * fbdiv_val + (24000000 * frac_val) / (1 << 24);
> +       rate += tmp;
> +       do_div(rate, refdiv_val);
> +       do_div(rate, postdiv1_val * postdiv2_val);
> +
> +       return rate;
> +}
> +
> +static int clk_pll_determine_rate(struct clk_hw *hw,
> +                                 struct clk_rate_request *req)
> +{
> +       return req->rate;

That's not really how it's supposed to work. We should be calculating
the rate that can be achieved in the hardware instead of blindly telling
the framework that any rate is supported.

> +}
> +
> +static const struct clk_ops clk_pll_ops = {

Maybe hisi_clk_pll_ops? Or hi3559_pll_ops?

> +       .set_rate = clk_pll_set_rate,
> +       .determine_rate = clk_pll_determine_rate,
> +       .recalc_rate = clk_pll_recalc_rate,
> +};
> +
> +static void hisi_clk_register_pll(struct hi3559av100_pll_clock *clks,
> +                          int nums, struct hisi_clock_data *data)
> +{
> +       void __iomem *base = data->base;
> +       int i;
> +
> +       for (i = 0; i < nums; i++) {
> +               struct hi3559av100_clk_pll *p_clk = NULL;
> +               struct clk *clk = NULL;
> +               struct clk_init_data init;

Please move these local variables to the start of the function instead
of living in this loop scope.

> +
> +               p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL);

Any chance we can allocate an array of p_clk at the start instead of
many smaller ones?

> +               if (!p_clk)
> +                       return;
> +
> +               init.name = clks[i].name;
> +               init.flags = 0;
> +               init.parent_names =
> +                       (clks[i].parent_name ? &clks[i].parent_name : NULL);
> +               init.num_parents = (clks[i].parent_name ? 1 : 0);

Can we get the parent name from DT instead by using clk_parent_data
instead?

> +               init.ops = &clk_pll_ops;
> +
> +               p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1;
> +               p_clk->frac_shift = clks[i].frac_shift;
> +               p_clk->frac_width = clks[i].frac_width;
> +               p_clk->postdiv1_shift = clks[i].postdiv1_shift;
> +               p_clk->postdiv1_width = clks[i].postdiv1_width;
> +               p_clk->postdiv2_shift = clks[i].postdiv2_shift;
> +               p_clk->postdiv2_width = clks[i].postdiv2_width;
> +
> +               p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2;
> +               p_clk->fbdiv_shift = clks[i].fbdiv_shift;
> +               p_clk->fbdiv_width = clks[i].fbdiv_width;
> +               p_clk->refdiv_shift = clks[i].refdiv_shift;
> +               p_clk->refdiv_width = clks[i].refdiv_width;
> +               p_clk->hw.init = &init;
> +
> +               clk = clk_register(NULL, &p_clk->hw);

Please pass a device and consider using devm. Also, use clk_hw_register.

> +               if (IS_ERR(clk)) {
> +                       kfree(p_clk);
> +                       pr_err("%s: failed to register clock %s\n",

Use dev_err().

> +                              __func__, clks[i].name);
> +                       continue;
> +               }
> +
> +               data->clk_data.clks[clks[i].id] = clk;
> +       }
> +}
> +
> +static __init struct hisi_clock_data *hi3559av100_clk_register(
> +       struct platform_device *pdev)
> +{
> +       struct hisi_clock_data *clk_data;
> +       int ret;
> +
> +       clk_data = hisi_clk_alloc(pdev, HI3559AV100_CRG_NR_CLKS);
> +       if (!clk_data)
> +               return ERR_PTR(-ENOMEM);
> +
> +       ret = hisi_clk_register_fixed_rate(hi3559av100_fixed_rate_clks_crg,
> +                                          ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data);
> +       if (ret)
> +               return ERR_PTR(ret);
> +
> +       hisi_clk_register_pll(hi3559av100_pll_clks,
> +                             ARRAY_SIZE(hi3559av100_pll_clks), clk_data);
> +
> +       ret = hisi_clk_register_mux(hi3559av100_mux_clks_crg,
> +                                   ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data);
> +       if (ret)
> +               goto unregister_fixed_rate;
> +
> +       ret = hisi_clk_register_fixed_factor(hi3559av100_fixed_factor_clks,
> +                                            ARRAY_SIZE(hi3559av100_fixed_factor_clks), clk_data);
> +       if (ret)
> +               goto unregister_mux;
> +
> +       ret = hisi_clk_register_gate(hi3559av100_gate_clks,
> +                                    ARRAY_SIZE(hi3559av100_gate_clks), clk_data);
> +       if (ret)
> +               goto unregister_factor;
> +
> +       ret = of_clk_add_provider(pdev->dev.of_node,
> +                                 of_clk_src_onecell_get, &clk_data->clk_data);
> +       if (ret)
> +               goto unregister_gate;
> +
> +       return clk_data;
> +
> +unregister_gate:
> +       hisi_clk_unregister_gate(hi3559av100_gate_clks,
> +                                ARRAY_SIZE(hi3559av100_gate_clks), clk_data);
> +unregister_factor:
> +       hisi_clk_unregister_fixed_factor(hi3559av100_fixed_factor_clks,
> +                                        ARRAY_SIZE(hi3559av100_fixed_factor_clks), clk_data);
> +unregister_mux:
> +       hisi_clk_unregister_mux(hi3559av100_mux_clks_crg,
> +                               ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data);
> +unregister_fixed_rate:
> +       hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg,
> +                                      ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data);
> +       return ERR_PTR(ret);
> +}
> +
> +static __init void hi3559av100_clk_unregister(struct platform_device *pdev)

Why is this marked __init?

> +{
> +       struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
> +
> +       of_clk_del_provider(pdev->dev.of_node);
> +
> +       hisi_clk_unregister_gate(hi3559av100_gate_clks,
> +                                ARRAY_SIZE(hi3559av100_gate_clks), crg->clk_data);
> +       hisi_clk_unregister_mux(hi3559av100_mux_clks_crg,
> +                               ARRAY_SIZE(hi3559av100_mux_clks_crg), crg->clk_data);
> +       hisi_clk_unregister_fixed_factor(hi3559av100_fixed_factor_clks,
> +                                        ARRAY_SIZE(hi3559av100_fixed_factor_clks), crg->clk_data);
> +       hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg,
> +                                      ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), crg->clk_data);
> +}
> +
> +static const struct hisi_crg_funcs hi3559av100_crg_funcs = {
> +       .register_clks = hi3559av100_clk_register,
> +       .unregister_clks = hi3559av100_clk_unregister,
> +};
> +
> +static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[]
> +       __initdata = {
> +       { HI3559AV100_SHUB_SOURCE_SOC_24M, "clk_source_24M", NULL, 0, 24000000UL, },
> +       { HI3559AV100_SHUB_SOURCE_SOC_200M, "clk_source_200M", NULL, 0, 200000000UL, },
> +       { HI3559AV100_SHUB_SOURCE_SOC_300M, "clk_source_300M", NULL, 0, 300000000UL, },
> +       { HI3559AV100_SHUB_SOURCE_PLL, "clk_source_PLL", NULL, 0, 192000000UL, },
> +       { HI3559AV100_SHUB_I2C0_CLK, "clk_shub_i2c0", NULL, 0, 48000000UL, },
> +       { HI3559AV100_SHUB_I2C1_CLK, "clk_shub_i2c1", NULL, 0, 48000000UL, },
> +       { HI3559AV100_SHUB_I2C2_CLK, "clk_shub_i2c2", NULL, 0, 48000000UL, },
> +       { HI3559AV100_SHUB_I2C3_CLK, "clk_shub_i2c3", NULL, 0, 48000000UL, },
> +       { HI3559AV100_SHUB_I2C4_CLK, "clk_shub_i2c4", NULL, 0, 48000000UL, },
> +       { HI3559AV100_SHUB_I2C5_CLK, "clk_shub_i2c5", NULL, 0, 48000000UL, },
> +       { HI3559AV100_SHUB_I2C6_CLK, "clk_shub_i2c6", NULL, 0, 48000000UL, },
> +       { HI3559AV100_SHUB_I2C7_CLK, "clk_shub_i2c7", NULL, 0, 48000000UL, },
> +       { HI3559AV100_SHUB_UART_CLK_32K, "clk_uart_32K", NULL, 0, 32000UL, },
> +};
> +
> +/* shub mux clk */
> +static u32 shub_source_clk_mux_table[] = {0, 1, 2, 3};
> +static const char *shub_source_clk_mux_p[] __initconst = {
> +       "clk_source_24M", "clk_source_200M", "clk_source_300M", "clk_source_PLL"
> +};
> +
> +static u32 shub_uart_source_clk_mux_table[] = {0, 1, 2, 3};
> +static const char *shub_uart_source_clk_mux_p[] __initconst = {
> +       "clk_uart_32K", "clk_uart_div_clk", "clk_uart_div_clk", "clk_source_24M"
> +};
> +
> +static struct hisi_mux_clock hi3559av100_shub_mux_clks[] __initdata = {
> +       {
> +               HI3559AV100_SHUB_SOURCE_CLK, "shub_clk", shub_source_clk_mux_p,
> +               ARRAY_SIZE(shub_source_clk_mux_p),
> +               0, 0x0, 0, 2, 0, shub_source_clk_mux_table,
> +       },
> +
> +       {
> +               HI3559AV100_SHUB_UART_SOURCE_CLK, "shub_uart_source_clk",
> +               shub_uart_source_clk_mux_p, ARRAY_SIZE(shub_uart_source_clk_mux_p),
> +               0, 0x1c, 28, 2, 0, shub_uart_source_clk_mux_table,
> +       },
> +};
> +
> +
> +/* shub div clk */
> +struct clk_div_table shub_spi_clk_table[] = {{0, 8}, {1, 4}, {2, 2}};
> +struct clk_div_table shub_spi4_clk_table[] = {{0, 8}, {1, 4}, {2, 2}, {3, 1}};
> +struct clk_div_table shub_uart_div_clk_table[] = {{1, 8}, {2, 4}};
> +
> +struct hisi_divider_clock hi3559av100_shub_div_clks[] __initdata = {
> +       { HI3559AV100_SHUB_SPI_SOURCE_CLK, "clk_spi_clk", "shub_clk", 0, 0x20, 24, 2,
> +         CLK_DIVIDER_ALLOW_ZERO, shub_spi_clk_table,
> +       },
> +       { HI3559AV100_SHUB_UART_DIV_CLK, "clk_uart_div_clk", "shub_clk", 0, 0x1c, 28, 2,
> +         CLK_DIVIDER_ALLOW_ZERO, shub_uart_div_clk_table,
> +       },
> +};
> +
> +/* shub gate clk */
> +static struct hisi_gate_clock hi3559av100_shub_gate_clks[] __initdata = {
> +       {
> +               HI3559AV100_SHUB_SPI0_CLK, "clk_shub_spi0", "clk_spi_clk",
> +               0, 0x20, 1, 0,
> +       },
> +       {
> +               HI3559AV100_SHUB_SPI1_CLK, "clk_shub_spi1", "clk_spi_clk",
> +               0, 0x20, 5, 0,
> +       },
> +       {
> +               HI3559AV100_SHUB_SPI2_CLK, "clk_shub_spi2", "clk_spi_clk",
> +               0, 0x20, 9, 0,
> +       },
> +
> +       {
> +               HI3559AV100_SHUB_UART0_CLK, "clk_shub_uart0", "shub_uart_source_clk",
> +               0, 0x1c, 1, 0,
> +       },
> +       {
> +               HI3559AV100_SHUB_UART1_CLK, "clk_shub_uart1", "shub_uart_source_clk",
> +               0, 0x1c, 5, 0,
> +       },
> +       {
> +               HI3559AV100_SHUB_UART2_CLK, "clk_shub_uart2", "shub_uart_source_clk",
> +               0, 0x1c, 9, 0,
> +       },
> +       {
> +               HI3559AV100_SHUB_UART3_CLK, "clk_shub_uart3", "shub_uart_source_clk",
> +               0, 0x1c, 13, 0,
> +       },
> +       {
> +               HI3559AV100_SHUB_UART4_CLK, "clk_shub_uart4", "shub_uart_source_clk",
> +               0, 0x1c, 17, 0,
> +       },
> +       {
> +               HI3559AV100_SHUB_UART5_CLK, "clk_shub_uart5", "shub_uart_source_clk",
> +               0, 0x1c, 21, 0,
> +       },
> +       {
> +               HI3559AV100_SHUB_UART6_CLK, "clk_shub_uart6", "shub_uart_source_clk",
> +               0, 0x1c, 25, 0,
> +       },
> +
> +       {
> +               HI3559AV100_SHUB_EDMAC_CLK, "clk_shub_dmac", "shub_clk",
> +               0, 0x24, 4, 0,
> +       },
> +};
> +
> +static int hi3559av100_shub_default_clk_set(void)
> +{
> +       void *crg_base;
> +       unsigned int val;
> +
> +       crg_base = ioremap(CRG_BASE_ADDR, SZ_4K);
> +
> +       /* SSP: 192M/2 */
> +       val = readl_relaxed(crg_base + 0x20);
> +       val |= (0x2 << 24);
> +       writel_relaxed(val, crg_base + 0x20);
> +
> +       /* UART: 192M/8 */
> +       val = readl_relaxed(crg_base + 0x1C);
> +       val |= (0x1 << 28);
> +       writel_relaxed(val, crg_base + 0x1C);
> +
> +       iounmap(crg_base);
> +       crg_base = NULL;
> +
> +       return 0;
> +}
> +
> +static __init struct hisi_clock_data *hi3559av100_shub_clk_register(
> +       struct platform_device *pdev)

We have a platform device here.

> +{
> +       struct hisi_clock_data *clk_data = NULL;
> +       int ret;
> +
> +       hi3559av100_shub_default_clk_set();
> +
> +       clk_data = hisi_clk_alloc(pdev, HI3559AV100_SHUB_NR_CLKS);
> +       if (!clk_data)
> +               return ERR_PTR(-ENOMEM);
> +
> +       ret = hisi_clk_register_fixed_rate(hi3559av100_shub_fixed_rate_clks,
> +                                          ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data);
> +       if (ret)
> +               return ERR_PTR(ret);
> +
> +       ret = hisi_clk_register_mux(hi3559av100_shub_mux_clks,
> +                                   ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data);
> +       if (ret)
> +               goto unregister_fixed_rate;
> +
> +       ret = hisi_clk_register_divider(hi3559av100_shub_div_clks,
> +                                       ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data);
> +       if (ret)
> +               goto unregister_mux;
> +
> +       ret = hisi_clk_register_gate(hi3559av100_shub_gate_clks,
> +                                    ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data);
> +       if (ret)
> +               goto unregister_factor;
> +
> +       ret = of_clk_add_provider(pdev->dev.of_node,

But we're not using devm? Why?

> +                                 of_clk_src_onecell_get, &clk_data->clk_data);
> +       if (ret)
> +               goto unregister_gate;
> +
> +       return clk_data;
> +
> +unregister_gate:
> +       hisi_clk_unregister_gate(hi3559av100_shub_gate_clks,
> +                                ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data);
> +unregister_factor:
> +       hisi_clk_unregister_divider(hi3559av100_shub_div_clks,
> +                                   ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data);
> +unregister_mux:
> +       hisi_clk_unregister_mux(hi3559av100_shub_mux_clks,
> +                               ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data);
> +unregister_fixed_rate:
> +       hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks,
> +                                      ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data);
> +       return ERR_PTR(ret);
> +}
> +
> +static __init void hi3559av100_shub_clk_unregister(struct platform_device *pdev)
> +{
> +       struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
> +
> +       of_clk_del_provider(pdev->dev.of_node);
> +
> +       hisi_clk_unregister_gate(hi3559av100_shub_gate_clks,
> +                                ARRAY_SIZE(hi3559av100_shub_gate_clks), crg->clk_data);
> +       hisi_clk_unregister_divider(hi3559av100_shub_div_clks,
> +                                   ARRAY_SIZE(hi3559av100_shub_div_clks), crg->clk_data);
> +       hisi_clk_unregister_mux(hi3559av100_shub_mux_clks,
> +                               ARRAY_SIZE(hi3559av100_shub_mux_clks), crg->clk_data);
> +       hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks,
> +                                      ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), crg->clk_data);
> +}
> +
> +static const struct hisi_crg_funcs hi3559av100_shub_crg_funcs = {
> +       .register_clks = hi3559av100_shub_clk_register,
> +       .unregister_clks = hi3559av100_shub_clk_unregister,
> +};
> +

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ