Re: [PATCH v10 08/13] drivers: memory: add DMC driver for Exynos5422

From: Krzysztof Kozlowski
Date: Fri Jun 14 2019 - 09:55:25 EST


On Fri, 14 Jun 2019 at 11:53, Lukasz Luba <l.luba@xxxxxxxxxxxxxxxxxxx> wrote:
>
> This patch adds driver for Exynos5422 Dynamic Memory Controller.
> The driver provides support for dynamic frequency and voltage scaling for
> DMC and DRAM. It supports changing timings of DRAM running with different
> frequency. There is also an algorithm to calculate timigns based on
> memory description provided in DT.
> The patch also contains needed MAINTAINERS file update.
>
> Signed-off-by: Lukasz Luba <l.luba@xxxxxxxxxxxxxxxxxxx>
> ---
> MAINTAINERS | 8 +
> drivers/memory/samsung/Kconfig | 17 +
> drivers/memory/samsung/Makefile | 1 +
> drivers/memory/samsung/exynos5422-dmc.c | 1262 +++++++++++++++++++++++
> 4 files changed, 1288 insertions(+)
> create mode 100644 drivers/memory/samsung/exynos5422-dmc.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 57f496cff999..6ffccfd95351 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -3470,6 +3470,14 @@ S: Maintained
> F: drivers/devfreq/exynos-bus.c
> F: Documentation/devicetree/bindings/devfreq/exynos-bus.txt
>
> +DMC FREQUENCY DRIVER FOR SAMSUNG EXYNOS5422
> +M: Lukasz Luba <l.luba@xxxxxxxxxxxxxxxxxxx>
> +L: linux-pm@xxxxxxxxxxxxxxx
> +L: linux-samsung-soc@xxxxxxxxxxxxxxx
> +S: Maintained
> +F: drivers/memory/samsung/exynos5422-dmc.c
> +F: Documentation/devicetree/bindings/memory-controllers/exynos5422-dmc.txt
> +
> BUSLOGIC SCSI DRIVER
> M: Khalid Aziz <khalid@xxxxxxxxxxxxxx>
> L: linux-scsi@xxxxxxxxxxxxxxx
> diff --git a/drivers/memory/samsung/Kconfig b/drivers/memory/samsung/Kconfig
> index 79ce7ea58903..c93baa029654 100644
> --- a/drivers/memory/samsung/Kconfig
> +++ b/drivers/memory/samsung/Kconfig
> @@ -5,6 +5,23 @@ config SAMSUNG_MC
> Support for the Memory Controller (MC) devices found on
> Samsung Exynos SoCs.
>
> +config ARM_EXYNOS5422_DMC
> + tristate "ARM EXYNOS5422 Dynamic Memory Controller driver"
> + depends on ARCH_EXYNOS
> + select DDR
> + select PM_DEVFREQ
> + select DEVFREQ_GOV_SIMPLE_ONDEMAND
> + select DEVFREQ_GOV_USERSPACE
> + select PM_DEVFREQ_EVENT
> + select PM_OPP
> + help
> + This adds driver for Exynos5422 DMC (Dynamic Memory Controller).
> + The driver provides support for Dynamic Voltage and Frequency Scaling in
> + DMC and DRAM. It also supports changing timings of DRAM running with
> + different frequency. The timings are calculated based on DT memory
> + information.
> +
> +
> if SAMSUNG_MC
>
> config EXYNOS_SROM
> diff --git a/drivers/memory/samsung/Makefile b/drivers/memory/samsung/Makefile
> index 00587be66211..4f6e4383bab7 100644
> --- a/drivers/memory/samsung/Makefile
> +++ b/drivers/memory/samsung/Makefile
> @@ -1,2 +1,3 @@
> # SPDX-License-Identifier: GPL-2.0
> +obj-$(CONFIG_ARM_EXYNOS5422_DMC) += exynos5422-dmc.o
> obj-$(CONFIG_EXYNOS_SROM) += exynos-srom.o
> diff --git a/drivers/memory/samsung/exynos5422-dmc.c b/drivers/memory/samsung/exynos5422-dmc.c
> new file mode 100644
> index 000000000000..b397efe0da57
> --- /dev/null
> +++ b/drivers/memory/samsung/exynos5422-dmc.c
> @@ -0,0 +1,1262 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2019 Samsung Electronics Co., Ltd.
> + * Author: Lukasz Luba <l.luba@xxxxxxxxxxxxxxxxxxx>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/devfreq.h>
> +#include <linux/devfreq-event.h>
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/pm_opp.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/slab.h>
> +#include <memory/jedec_ddr.h>
> +#include "../of_memory.h"
> +
> +#define EXYNOS5_DREXI_TIMINGAREF (0x0030)
> +#define EXYNOS5_DREXI_TIMINGROW0 (0x0034)
> +#define EXYNOS5_DREXI_TIMINGDATA0 (0x0038)
> +#define EXYNOS5_DREXI_TIMINGPOWER0 (0x003C)
> +#define EXYNOS5_DREXI_TIMINGROW1 (0x00E4)
> +#define EXYNOS5_DREXI_TIMINGDATA1 (0x00E8)
> +#define EXYNOS5_DREXI_TIMINGPOWER1 (0x00EC)
> +#define CDREX_PAUSE (0x2091c)
> +#define CDREX_LPDDR3PHY_CON3 (0x20a20)
> +#define EXYNOS5_TIMING_SET_SWI (1UL << 28)
> +#define USE_MX_MSPLL_TIMINGS (1)
> +#define USE_BPLL_TIMINGS (0)
> +#define EXYNOS5_AREF_NORMAL (0x2e)
> +
> +/**
> + * struct dmc_opp_table - Operating level desciption
> + *
> + * Covers frequency and voltage settings of the DMC operating mode.
> + */
> +struct dmc_opp_table {
> + u32 freq_hz;
> + u32 volt_uv;
> +};
> +
> +/**
> + * struct exynos5_dmc - main structure describing DMC device
> + *
> + * The main structure for the Dynamic Memory Controller which covers clocks,
> + * memory regions, HW information, parameters and current operating mode.
> + */
> +struct exynos5_dmc {
> + struct device *dev;
> + struct devfreq *df;
> + struct devfreq_simple_ondemand_data gov_data;
> + void __iomem *base_drexi0;
> + void __iomem *base_drexi1;
> + struct regmap *clk_regmap;
> + struct mutex lock;
> + unsigned long curr_rate;
> + unsigned long curr_volt;
> + unsigned long bypass_rate;
> + struct dmc_opp_table *opp;
> + struct dmc_opp_table opp_bypass;
> + int opp_count;
> + u32 timings_arr_size;
> + u32 *timing_row;
> + u32 *timing_data;
> + u32 *timing_power;
> + const struct lpddr3_timings *timings;
> + const struct lpddr3_min_tck *min_tck;
> + u32 bypass_timing_row;
> + u32 bypass_timing_data;
> + u32 bypass_timing_power;
> + struct regulator *vdd_mif;
> + struct clk *fout_spll;
> + struct clk *fout_bpll;
> + struct clk *mout_spll;
> + struct clk *mout_bpll;
> + struct clk *mout_mclk_cdrex;
> + struct clk *mout_mx_mspll_ccore;
> + struct clk *mx_mspll_ccore_phy;
> + struct clk *mout_mx_mspll_ccore_phy;
> + struct devfreq_event_dev **counter;
> + int num_counters;
> +};
> +
> +#define TIMING_FIELD(t_name, t_bit_beg, t_bit_end) \
> + { .name = t_name, .bit_beg = t_bit_beg, .bit_end = t_bit_end }
> +
> +#define TIMING_VAL(timing_array, id, t_val) \
> +({ \
> + u32 __val; \
> + __val = t_val << timing_array[id].bit_beg; \
> + __val; \
> +})
> +
> +#define TIMING_VAL2REG(timing, t_val) \
> +({ \
> + u32 __val; \
> + __val = t_val << timing->bit_beg; \
> + __val; \
> +})
> +
> +#define TIMING_REG2VAL(reg, timing) \

It seems that only some of these defines are used. Please clean them up.
You have also a lot of checkpatch --strict suggestions:
CHECK: Macro argument 'reg' may be better as '(reg)' to avoid
precedence issues
which seems to be valid.

While at it please also fix few other --strict errors:
CHECK: Please don't use multiple blank lines
CHECK: Alignment should match open parenthesis
CHECK: Prefer using the BIT macro
CHECK: struct mutex definition without comment

Best regards,
Krzysztof