diff options
Diffstat (limited to 'drivers')
48 files changed, 1763 insertions, 1041 deletions
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 791e10ea99..7b1bdde1ce 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -20,6 +20,7 @@ #include <linux/clk.h> #include <linux/err.h> #include <linux/log2.h> +#include <asm-generic/div64.h> #define div_mask(d) ((1 << ((d)->width)) - 1) @@ -56,17 +57,17 @@ static unsigned int _get_table_div(const struct clk_div_table *table, return 0; } -static unsigned int _get_div(struct clk_divider *divider, unsigned int val) +static unsigned int _get_div(const struct clk_div_table *table, + unsigned int val, unsigned long flags, u8 width) { - if (divider->flags & CLK_DIVIDER_ONE_BASED) + if (flags & CLK_DIVIDER_ONE_BASED) return val; - if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + if (flags & CLK_DIVIDER_POWER_OF_TWO) return 1 << val; - if (divider->table) - return _get_table_div(divider->table, val); + if (table) + return _get_table_div(table, val); return val + 1; } - static unsigned int _get_table_val(const struct clk_div_table *table, unsigned int div) { @@ -89,6 +90,18 @@ static unsigned int _get_val(struct clk_divider *divider, unsigned int div) return div - 1; } +unsigned long divider_recalc_rate(struct clk *clk, unsigned long parent_rate, + unsigned int val, + const struct clk_div_table *table, + unsigned long flags, unsigned long width) +{ + unsigned int div; + + div = _get_div(table, val, flags, width); + + return DIV_ROUND_UP_ULL((u64)parent_rate, div); +} + static unsigned long clk_divider_recalc_rate(struct clk *clk, unsigned long parent_rate) { @@ -98,9 +111,10 @@ static unsigned long clk_divider_recalc_rate(struct clk *clk, val = readl(divider->reg) >> divider->shift; val &= div_mask(divider); - div = _get_div(divider, val); + div = _get_div(divider->table, val, divider->flags, divider->width); - return parent_rate / div; + return divider_recalc_rate(clk, parent_rate, val, divider->table, + divider->flags, divider->width); } /* diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 695e19ab54..89240ff794 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -20,16 +20,6 @@ #include <linux/clk.h> #include <linux/err.h> -struct clk_gate { - struct clk clk; - void __iomem *reg; - int shift; - const char *parent; - unsigned flags; -}; - -#define to_clk_gate(_clk) container_of(_clk, struct clk_gate, clk) - static void clk_gate_endisable(struct clk *clk, int enable) { struct clk_gate *gate = container_of(clk, struct clk_gate, clk); @@ -79,7 +69,7 @@ static int clk_gate_is_enabled(struct clk *clk) return g->flags & CLK_GATE_INVERTED ? 1 : 0; } -static struct clk_ops clk_gate_ops = { +struct clk_ops clk_gate_ops = { .set_rate = clk_parent_set_rate, .round_rate = clk_parent_round_rate, .enable = clk_gate_enable, diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 22e131faae..d5fe640dce 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -20,15 +20,6 @@ #include <linux/clk.h> #include <linux/err.h> -struct clk_mux { - struct clk clk; - void __iomem *reg; - int shift; - int width; -}; - -#define to_clk_mux(_clk) container_of(_clk, struct clk_mux, clk) - static int clk_mux_get_parent(struct clk *clk) { struct clk_mux *m = container_of(clk, struct clk_mux, clk); @@ -53,7 +44,7 @@ static int clk_mux_set_parent(struct clk *clk, u8 idx) return 0; } -static struct clk_ops clk_mux_ops = { +struct clk_ops clk_mux_ops = { .set_rate = clk_parent_set_rate, .round_rate = clk_parent_round_rate, .get_parent = clk_mux_get_parent, diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 8f441a97e7..97ae97a2a9 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_COMMON_CLK) += \ + clk-composite-8m.o \ clk-pllv1.o \ clk-pllv2.o \ clk-pllv3.o \ diff --git a/drivers/clk/imx/clk-composite-8m.c b/drivers/clk/imx/clk-composite-8m.c new file mode 100644 index 0000000000..0cd52b5b46 --- /dev/null +++ b/drivers/clk/imx/clk-composite-8m.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2018 NXP + */ + +#include <common.h> +#include <errno.h> +#include <linux/slab.h> +#include <linux/clk.h> + +#include "clk.h" + +#define PCG_PREDIV_SHIFT 16 +#define PCG_PREDIV_WIDTH 3 +#define PCG_PREDIV_MAX 8 + +#define PCG_DIV_SHIFT 0 +#define PCG_DIV_WIDTH 6 +#define PCG_DIV_MAX 64 + +#define PCG_PCS_SHIFT 24 +#define PCG_PCS_WIDTH 3 + +#define PCG_CGC_SHIFT 28 + +#define clk_div_mask(width) ((1 << (width)) - 1) + +static unsigned long imx8m_clk_composite_divider_recalc_rate(struct clk *clk, + unsigned long parent_rate) +{ + struct clk_divider *divider = container_of(clk, struct clk_divider, clk); + unsigned long prediv_rate; + unsigned int prediv_value; + unsigned int div_value; + + prediv_value = readl(divider->reg) >> divider->shift; + prediv_value &= clk_div_mask(divider->width); + + prediv_rate = divider_recalc_rate(clk, parent_rate, prediv_value, + NULL, divider->flags, + divider->width); + + div_value = readl(divider->reg) >> PCG_DIV_SHIFT; + div_value &= clk_div_mask(PCG_DIV_WIDTH); + + return divider_recalc_rate(clk, prediv_rate, div_value, NULL, + divider->flags, PCG_DIV_WIDTH); +} + +static int imx8m_clk_composite_compute_dividers(unsigned long rate, + unsigned long parent_rate, + int *prediv, int *postdiv) +{ + int div1, div2; + int error = INT_MAX; + int ret = -EINVAL; + + *prediv = 1; + *postdiv = 1; + + for (div1 = 1; div1 <= PCG_PREDIV_MAX; div1++) { + for (div2 = 1; div2 <= PCG_DIV_MAX; div2++) { + int new_error = ((parent_rate / div1) / div2) - rate; + + if (abs(new_error) < abs(error)) { + *prediv = div1; + *postdiv = div2; + error = new_error; + ret = 0; + } + } + } + return ret; +} + +static long imx8m_clk_composite_divider_round_rate(struct clk *clk, + unsigned long rate, + unsigned long *prate) +{ + int prediv_value; + int div_value; + + imx8m_clk_composite_compute_dividers(rate, *prate, + &prediv_value, &div_value); + rate = DIV_ROUND_UP(*prate, prediv_value); + + return DIV_ROUND_UP(rate, div_value); + +} + +static int imx8m_clk_composite_divider_set_rate(struct clk *clk, + unsigned long rate, + unsigned long parent_rate) +{ + struct clk_divider *divider = container_of(clk, struct clk_divider, clk); + int prediv_value; + int div_value; + int ret; + u32 val; + + ret = imx8m_clk_composite_compute_dividers(rate, parent_rate, + &prediv_value, &div_value); + if (ret) + return -EINVAL; + + val = readl(divider->reg); + val &= ~((clk_div_mask(divider->width) << divider->shift) | + (clk_div_mask(PCG_DIV_WIDTH) << PCG_DIV_SHIFT)); + + val |= (u32)(prediv_value - 1) << divider->shift; + val |= (u32)(div_value - 1) << PCG_DIV_SHIFT; + writel(val, divider->reg); + + return ret; +} + +static const struct clk_ops imx8m_clk_composite_divider_ops = { + .recalc_rate = imx8m_clk_composite_divider_recalc_rate, + .round_rate = imx8m_clk_composite_divider_round_rate, + .set_rate = imx8m_clk_composite_divider_set_rate, +}; + +struct clk *imx8m_clk_composite_flags(const char *name, + const char **parent_names, + int num_parents, void __iomem *reg, + unsigned long flags) +{ + struct clk *comp = ERR_PTR(-ENOMEM); + struct clk_divider *div = NULL; + struct clk_gate *gate = NULL; + struct clk_mux *mux = NULL; + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + goto fail; + + mux->reg = reg; + mux->shift = PCG_PCS_SHIFT; + mux->width = PCG_PCS_WIDTH; + mux->clk.ops = &clk_mux_ops; + + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) + goto fail; + + div->reg = reg; + div->shift = PCG_PREDIV_SHIFT; + div->width = PCG_PREDIV_WIDTH; + div->clk.ops = &imx8m_clk_composite_divider_ops; + + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + goto fail; + + gate->reg = reg; + gate->shift = PCG_CGC_SHIFT; + gate->clk.ops = &clk_gate_ops; + + comp = clk_register_composite(name, parent_names, num_parents, + &mux->clk, &div->clk, &gate->clk, flags); + if (IS_ERR(comp)) + goto fail; + + return comp; + +fail: + kfree(gate); + kfree(div); + kfree(mux); + return ERR_CAST(comp); +} diff --git a/drivers/clk/imx/clk-imx5.c b/drivers/clk/imx/clk-imx5.c index f59a41b001..69ac2f5e3e 100644 --- a/drivers/clk/imx/clk-imx5.c +++ b/drivers/clk/imx/clk-imx5.c @@ -271,6 +271,7 @@ static void mx5_clocks_mx51_mx53_init(void __iomem *base) clks[IMX5_CLK_USBOH3_PODF] = imx_clk_divider("usboh3_podf", "usboh3_pred", base + CCM_CSCDR1, 6, 2); clks[IMX5_CLK_USB_PHY_PRED] = imx_clk_divider("usb_phy_pred", "pll3_sw", base + CCM_CDCDR, 3, 3); clks[IMX5_CLK_USB_PHY_PODF] = imx_clk_divider("usb_phy_podf", "usb_phy_pred", base + CCM_CDCDR, 0, 3); + clks[IMX5_CLK_DI_PRED] = imx_clk_divider_np("di_pred", "pll3_sw", base + CCM_CDCDR, 6, 3); clks[IMX5_CLK_USB_PHY_SEL] = imx_clk_mux("usb_phy_sel", base + CCM_CSCMR1, 26, 1, usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str)); } @@ -362,6 +363,8 @@ static void mx51_clocks_ipu_init(void __iomem *regs) mx5_clocks_ipu_init(regs); + clk_set_rate(clks[IMX5_CLK_DI_PRED], clk_get_rate(clks[IMX5_CLK_PLL3_SW])); + clkdev_add_physbase(clks[IMX5_CLK_IPU_SEL], MX51_IPU_BASE_ADDR, "bus"); clkdev_add_physbase(clks[IMX5_CLK_IPU_DI0_SEL], MX51_IPU_BASE_ADDR, "di0"); clkdev_add_physbase(clks[IMX5_CLK_IPU_DI1_SEL], MX51_IPU_BASE_ADDR, "di1"); diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index 0431f61f09..016d405e90 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -1,25 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * Copyright 2017 NXP. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * Copyright 2018 NXP. + * Copyright (C) 2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> */ -#include <common.h> -#include <init.h> -#include <driver.h> -#include <linux/clk.h> +#include <dt-bindings/clock/imx8mq-clock.h> #include <io.h> -#include <of.h> -#include <of_address.h> -#include <linux/clkdev.h> +#include <linux/clk.h> #include <linux/err.h> -#include <mach/revision.h> -#include <dt-bindings/clock/imx8mq-clock.h> +#include <linux/types.h> +#include <of_address.h> #include "clk.h" @@ -37,18 +27,25 @@ static const char *sys1_pll1_out_sels[] = {"sys1_pll1", "sys1_pll1_ref_sel", }; static const char *sys2_pll1_out_sels[] = {"sys2_pll1", "sys1_pll1_ref_sel", }; static const char *sys3_pll1_out_sels[] = {"sys3_pll1", "sys3_pll1_ref_sel", }; static const char *dram_pll1_out_sels[] = {"dram_pll1", "dram_pll1_ref_sel", }; -static const char *video2_pll1_out_sels[] = {"video2_pll1", "video2_pll1_ref_sel", }; static const char *sys1_pll2_out_sels[] = {"sys1_pll2_div", "sys1_pll1_ref_sel", }; static const char *sys2_pll2_out_sels[] = {"sys2_pll2_div", "sys2_pll1_ref_sel", }; static const char *sys3_pll2_out_sels[] = {"sys3_pll2_div", "sys2_pll1_ref_sel", }; static const char *dram_pll2_out_sels[] = {"dram_pll2_div", "dram_pll1_ref_sel", }; -static const char *video2_pll2_out_sels[] = {"video2_pll2_div", "video2_pll1_ref_sel", }; /* CCM ROOT */ static const char *imx8mq_a53_sels[] = {"osc_25m", "arm_pll_out", "sys2_pll_500m", "sys2_pll_1000m", "sys1_pll_800m", "sys1_pll_400m", "audio_pll1_out", "sys3_pll2_out", }; +static const char *imx8mq_vpu_sels[] = {"osc_25m", "arm_pll_out", "sys2_pll_500m", "sys2_pll_1000m", + "sys1_pll_800m", "sys1_pll_400m", "audio_pll1_out", "vpu_pll_out", }; + +static const char *imx8mq_gpu_core_sels[] = {"osc_25m", "gpu_pll_out", "sys1_pll_800m", "sys3_pll2_out", + "sys2_pll_1000m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", }; + +static const char *imx8mq_gpu_shader_sels[] = {"osc_25m", "gpu_pll_out", "sys1_pll_800m", "sys3_pll2_out", + "sys2_pll_1000m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", }; + static const char *imx8mq_main_axi_sels[] = {"osc_25m", "sys2_pll_333m", "sys1_pll_800m", "sys2_pll_250m", "sys2_pll_1000m", "audio_pll1_out", "video_pll1_out", "sys1_pll_100m",}; @@ -58,9 +55,25 @@ static const char *imx8mq_enet_axi_sels[] = {"osc_25m", "sys1_pll_266m", "sys1_p static const char *imx8mq_nand_usdhc_sels[] = {"osc_25m", "sys1_pll_266m", "sys1_pll_800m", "sys2_pll_200m", "sys1_pll_133m", "sys3_pll2_out", "sys2_pll_250m", "audio_pll1_out", }; +static const char *imx8mq_vpu_bus_sels[] = {"osc_25m", "sys1_pll_800m", "vpu_pll_out", "audio_pll2_out", "sys3_pll2_out", "sys2_pll_1000m", "sys2_pll_200m", "sys1_pll_100m", }; + +static const char *imx8mq_disp_axi_sels[] = {"osc_25m", "sys2_pll_125m", "sys1_pll_800m", "sys3_pll2_out", "sys1_pll_400m", "audio_pll2_out", "clk_ext1", "clk_ext4", }; + +static const char *imx8mq_disp_apb_sels[] = {"osc_25m", "sys2_pll_125m", "sys1_pll_800m", "sys3_pll2_out", + "sys1_pll_40m", "audio_pll2_out", "clk_ext1", "clk_ext3", }; + +static const char *imx8mq_disp_rtrm_sels[] = {"osc_25m", "sys1_pll_800m", "sys2_pll_200m", "sys1_pll_400m", + "audio_pll1_out", "video_pll1_out", "clk_ext2", "clk_ext3", }; + static const char *imx8mq_usb_bus_sels[] = {"osc_25m", "sys2_pll_500m", "sys1_pll_800m", "sys2_pll_100m", "sys2_pll_200m", "clk_ext2", "clk_ext4", "audio_pll2_out", }; +static const char *imx8mq_gpu_axi_sels[] = {"osc_25m", "sys1_pll_800m", "gpu_pll_out", "sys3_pll2_out", "sys2_pll_1000m", + "audio_pll1_out", "video_pll1_out", "audio_pll2_out", }; + +static const char *imx8mq_gpu_ahb_sels[] = {"osc_25m", "sys1_pll_800m", "gpu_pll_out", "sys3_pll2_out", "sys2_pll_1000m", + "audio_pll1_out", "video_pll1_out", "audio_pll2_out", }; + static const char *imx8mq_noc_sels[] = {"osc_25m", "sys1_pll_800m", "sys3_pll2_out", "sys2_pll_1000m", "sys2_pll_500m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", }; @@ -70,11 +83,25 @@ static const char *imx8mq_noc_apb_sels[] = {"osc_25m", "sys1_pll_400m", "sys3_pl static const char *imx8mq_ahb_sels[] = {"osc_25m", "sys1_pll_133m", "sys1_pll_800m", "sys1_pll_400m", "sys2_pll_125m", "sys3_pll2_out", "audio_pll1_out", "video_pll1_out", }; +static const char *imx8mq_audio_ahb_sels[] = {"osc_25m", "sys2_pll_500m", "sys1_pll_800m", "sys2_pll_1000m", + "sys2_pll_166m", "sys3_pll2_out", "audio_pll1_out", "video_pll1_out", }; + +static const char *imx8mq_dsi_ahb_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m", + "sys2_pll_1000m", "sys3_pll2_out", "clk_ext3", "audio_pll2_out"}; + static const char *imx8mq_dram_alt_sels[] = {"osc_25m", "sys1_pll_800m", "sys1_pll_100m", "sys2_pll_500m", - "sys2_pll_250m", "sys1_pll_400m", "audio_pll1_out", "sys1_pll_266m", }; + "sys2_pll_250m", "sys1_pll_400m", "audio_pll1_out", "sys1_pll_266m", }; static const char *imx8mq_dram_apb_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_40m", "sys1_pll_160m", - "sys1_pll_800m", "sys3_pll2_out", "sys2_pll_250m", "audio_pll2_out", }; + "sys1_pll_800m", "sys3_pll2_out", "sys2_pll_250m", "audio_pll2_out", }; + +static const char *imx8mq_vpu_g1_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_100m", "sys2_pll_125m", "sys3_pll2_out", "audio_pll1_out", }; + +static const char *imx8mq_vpu_g2_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_100m", "sys2_pll_125m", "sys3_pll2_out", "audio_pll1_out", }; + +static const char *imx8mq_disp_dtrc_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_160m", "sys2_pll_100m", "sys3_pll2_out", "audio_pll2_out", }; + +static const char *imx8mq_disp_dc8000_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_160m", "sys2_pll_100m", "sys3_pll2_out", "audio_pll2_out", }; static const char *imx8mq_pcie1_ctrl_sels[] = {"osc_25m", "sys2_pll_250m", "sys2_pll_200m", "sys1_pll_266m", "sys1_pll_800m", "sys2_pll_500m", "sys2_pll_250m", "sys3_pll2_out", }; @@ -89,6 +116,22 @@ static const char *imx8mq_dc_pixel_sels[] = {"osc_25m", "video_pll1_out", "audio static const char *imx8mq_lcdif_pixel_sels[] = {"osc_25m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out", "sys1_pll_800m", "sys2_pll_1000m", "sys3_pll2_out", "clk_ext4", }; +static const char *imx8mq_sai1_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext1", "clk_ext2", }; + +static const char *imx8mq_sai2_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext2", "clk_ext3", }; + +static const char *imx8mq_sai3_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext3", "clk_ext4", }; + +static const char *imx8mq_sai4_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext1", "clk_ext2", }; + +static const char *imx8mq_sai5_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext2", "clk_ext3", }; + +static const char *imx8mq_sai6_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext3", "clk_ext4", }; + +static const char *imx8mq_spdif1_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext2", "clk_ext3", }; + +static const char *imx8mq_spdif2_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext3", "clk_ext4", }; + static const char *imx8mq_enet_ref_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_500m", "sys2_pll_100m", "sys1_pll_160m", "audio_pll1_out", "video_pll1_out", "clk_ext4", }; @@ -167,6 +210,36 @@ static const char *imx8mq_wdog_sels[] = {"osc_25m", "sys1_pll_133m", "sys1_pll_1 static const char *imx8mq_wrclk_sels[] = {"osc_25m", "sys1_pll_40m", "vpu_pll_out", "sys3_pll2_out", "sys2_pll_200m", "sys1_pll_266m", "sys2_pll_500m", "sys1_pll_100m", }; +static const char *imx8mq_dsi_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m", + "sys2_pll_1000m", "sys3_pll2_out", "audio_pll2_out", "video_pll1_out", }; + +static const char *imx8mq_dsi_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m", + "sys2_pll_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", }; + +static const char *imx8mq_dsi_dbi_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_100m", "sys1_pll_800m", + "sys2_pll_1000m", "sys3_pll2_out", "audio_pll2_out", "video_pll1_out", }; + +static const char *imx8mq_dsi_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m", + "sys2_pll_1000m", "sys3_pll2_out", "clk_ext3", "audio_pll2_out", }; + +static const char *imx8mq_csi1_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m", + "sys2_pll_1000m", "sys3_pll2_out", "audio_pll2_out", "video_pll1_out", }; + +static const char *imx8mq_csi1_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m", + "sys2_pll_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", }; + +static const char *imx8mq_csi1_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m", + "sys2_pll_1000m", "sys3_pll2_out", "clk_ext3", "audio_pll2_out", }; + +static const char *imx8mq_csi2_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m", + "sys2_pll_1000m", "sys3_pll2_out", "audio_pll2_out", "video_pll1_out", }; + +static const char *imx8mq_csi2_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m", + "sys2_pll_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", }; + +static const char *imx8mq_csi2_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m", + "sys2_pll_1000m", "sys3_pll2_out", "clk_ext3", "audio_pll2_out", }; + static const char *imx8mq_pcie2_ctrl_sels[] = {"osc_25m", "sys2_pll_250m", "sys2_pll_200m", "sys1_pll_266m", "sys1_pll_800m", "sys2_pll_500m", "sys2_pll_333m", "sys3_pll2_out", }; @@ -186,18 +259,19 @@ static const char *imx8mq_clko2_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_ static struct clk_onecell_data clk_data; static int const clks_init_on[] = { - IMX8MQ_CLK_DRAM_CORE, IMX8MQ_CLK_AHB_CG, - IMX8MQ_CLK_NOC_DIV, IMX8MQ_CLK_NOC_APB_DIV, - IMX8MQ_CLK_NAND_USDHC_BUS_SRC, - IMX8MQ_CLK_MAIN_AXI_SRC, IMX8MQ_CLK_A53_CG, - IMX8MQ_CLK_AUDIO_AHB_DIV, IMX8MQ_CLK_TMU_ROOT, - IMX8MQ_CLK_DRAM_APB_SRC, + IMX8MQ_CLK_A53_CG, + IMX8MQ_CLK_DRAM_CORE, + IMX8MQ_CLK_TMU_ROOT, + IMX8MQ_CLK_MAIN_AXI, + IMX8MQ_CLK_NOC, + IMX8MQ_CLK_NOC_APB, + IMX8MQ_CLK_DRAM_APB }; - -static void __init imx8mq_clocks_init(struct device_node *ccm_node) +static int imx8mq_clocks_init(struct device_node *ccm_node) { struct device_node *np; void __iomem *base; + int err; int i; clks[IMX8MQ_CLK_DUMMY] = clk_fixed("dummy", 0); @@ -211,7 +285,8 @@ static void __init imx8mq_clocks_init(struct device_node *ccm_node) np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-anatop"); base = of_iomap(np, 0); - WARN_ON(!base); + if (WARN_ON(!base)) + return -ENOMEM; clks[IMX8MQ_ARM_PLL_REF_SEL] = imx_clk_mux("arm_pll_ref_sel", base + 0x28, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); clks[IMX8MQ_GPU_PLL_REF_SEL] = imx_clk_mux("gpu_pll_ref_sel", base + 0x18, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); @@ -223,7 +298,6 @@ static void __init imx8mq_clocks_init(struct device_node *ccm_node) clks[IMX8MQ_SYS2_PLL1_REF_SEL] = imx_clk_mux("sys2_pll1_ref_sel", base + 0x3c, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); clks[IMX8MQ_SYS3_PLL1_REF_SEL] = imx_clk_mux("sys3_pll1_ref_sel", base + 0x48, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); clks[IMX8MQ_DRAM_PLL1_REF_SEL] = imx_clk_mux("dram_pll1_ref_sel", base + 0x60, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); - clks[IMX8MQ_VIDEO2_PLL1_REF_SEL] = imx_clk_mux("video2_pll1_ref_sel", base + 0x54, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); clks[IMX8MQ_ARM_PLL_REF_DIV] = imx_clk_divider("arm_pll_ref_div", "arm_pll_ref_sel", base + 0x28, 5, 6); clks[IMX8MQ_GPU_PLL_REF_DIV] = imx_clk_divider("gpu_pll_ref_div", "gpu_pll_ref_sel", base + 0x18, 5, 6); @@ -235,7 +309,6 @@ static void __init imx8mq_clocks_init(struct device_node *ccm_node) clks[IMX8MQ_SYS2_PLL1_REF_DIV] = imx_clk_divider("sys2_pll1_ref_div", "sys2_pll1_ref_sel", base + 0x44, 25, 3); clks[IMX8MQ_SYS3_PLL1_REF_DIV] = imx_clk_divider("sys3_pll1_ref_div", "sys3_pll1_ref_sel", base + 0x50, 25, 3); clks[IMX8MQ_DRAM_PLL1_REF_DIV] = imx_clk_divider("dram_pll1_ref_div", "dram_pll1_ref_sel", base + 0x68, 25, 3); - clks[IMX8MQ_VIDEO2_PLL1_REF_DIV] = imx_clk_divider("video2_pll1_ref_div", "video2_pll1_ref_sel", base + 0x5c, 25, 3); clks[IMX8MQ_ARM_PLL] = imx_clk_frac_pll("arm_pll", "arm_pll_ref_div", base + 0x28); clks[IMX8MQ_GPU_PLL] = imx_clk_frac_pll("gpu_pll", "gpu_pll_ref_div", base + 0x18); @@ -247,25 +320,21 @@ static void __init imx8mq_clocks_init(struct device_node *ccm_node) clks[IMX8MQ_SYS2_PLL1] = imx_clk_sccg_pll("sys2_pll1", "sys2_pll1_ref_div", base + 0x3c, SCCG_PLL1); clks[IMX8MQ_SYS3_PLL1] = imx_clk_sccg_pll("sys3_pll1", "sys3_pll1_ref_div", base + 0x48, SCCG_PLL1); clks[IMX8MQ_DRAM_PLL1] = imx_clk_sccg_pll("dram_pll1", "dram_pll1_ref_div", base + 0x60, SCCG_PLL1); - clks[IMX8MQ_VIDEO2_PLL1] = imx_clk_sccg_pll("video2_pll1", "video2_pll1_ref_div", base + 0x5c, SCCG_PLL1); clks[IMX8MQ_SYS1_PLL2] = imx_clk_sccg_pll("sys1_pll2", "sys1_pll1_out_div", base + 0x30, SCCG_PLL2); clks[IMX8MQ_SYS2_PLL2] = imx_clk_sccg_pll("sys2_pll2", "sys2_pll1_out_div", base + 0x3c, SCCG_PLL2); clks[IMX8MQ_SYS3_PLL2] = imx_clk_sccg_pll("sys3_pll2", "sys3_pll1_out_div", base + 0x48, SCCG_PLL2); clks[IMX8MQ_DRAM_PLL2] = imx_clk_sccg_pll("dram_pll2", "dram_pll1_out_div", base + 0x60, SCCG_PLL2); - clks[IMX8MQ_VIDEO2_PLL2] = imx_clk_sccg_pll("video2_pll2", "video2_pll1_out_div", base + 0x54, SCCG_PLL2); /* PLL divs */ clks[IMX8MQ_SYS1_PLL1_OUT_DIV] = imx_clk_divider("sys1_pll1_out_div", "sys1_pll1_out", base + 0x38, 19, 6); clks[IMX8MQ_SYS2_PLL1_OUT_DIV] = imx_clk_divider("sys2_pll1_out_div", "sys2_pll1_out", base + 0x44, 19, 6); clks[IMX8MQ_SYS3_PLL1_OUT_DIV] = imx_clk_divider("sys3_pll1_out_div", "sys3_pll1_out", base + 0x50, 19, 6); clks[IMX8MQ_DRAM_PLL1_OUT_DIV] = imx_clk_divider("dram_pll1_out_div", "dram_pll1_out", base + 0x68, 19, 6); - clks[IMX8MQ_VIDEO2_PLL1_OUT_DIV] = imx_clk_divider("video2_pll1_out_div", "video2_pll1_out", base + 0x5c, 19, 6); clks[IMX8MQ_SYS1_PLL2_DIV] = imx_clk_divider("sys1_pll2_div", "sys1_pll2", base + 0x38, 1, 6); clks[IMX8MQ_SYS2_PLL2_DIV] = imx_clk_divider("sys2_pll2_div", "sys2_pll2", base + 0x44, 1, 6); clks[IMX8MQ_SYS3_PLL2_DIV] = imx_clk_divider("sys3_pll2_div", "sys3_pll2", base + 0x50, 1, 6); clks[IMX8MQ_DRAM_PLL2_DIV] = imx_clk_divider("dram_pll2_div", "dram_pll2", base + 0x68, 1, 6); - clks[IMX8MQ_VIDEO2_PLL2_DIV] = imx_clk_divider("video2_pll2_div", "video2_pll2", base + 0x5c, 1, 6); /* PLL bypass out */ clks[IMX8MQ_ARM_PLL_BYPASS] = imx_clk_mux("arm_pll_bypass", base + 0x28, 14, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels)); @@ -279,21 +348,10 @@ static void __init imx8mq_clocks_init(struct device_node *ccm_node) clks[IMX8MQ_SYS2_PLL1_OUT] = imx_clk_mux("sys2_pll1_out", base + 0x3c, 5, 1, sys2_pll1_out_sels, ARRAY_SIZE(sys2_pll1_out_sels)); clks[IMX8MQ_SYS3_PLL1_OUT] = imx_clk_mux("sys3_pll1_out", base + 0x48, 5, 1, sys3_pll1_out_sels, ARRAY_SIZE(sys3_pll1_out_sels)); clks[IMX8MQ_DRAM_PLL1_OUT] = imx_clk_mux("dram_pll1_out", base + 0x60, 5, 1, dram_pll1_out_sels, ARRAY_SIZE(dram_pll1_out_sels)); - clks[IMX8MQ_VIDEO2_PLL1_OUT] = imx_clk_mux("video2_pll1_out", base + 0x54, 5, 1, video2_pll1_out_sels, ARRAY_SIZE(video2_pll1_out_sels)); clks[IMX8MQ_SYS1_PLL2_OUT] = imx_clk_mux("sys1_pll2_out", base + 0x30, 4, 1, sys1_pll2_out_sels, ARRAY_SIZE(sys1_pll2_out_sels)); clks[IMX8MQ_SYS2_PLL2_OUT] = imx_clk_mux("sys2_pll2_out", base + 0x3c, 4, 1, sys2_pll2_out_sels, ARRAY_SIZE(sys2_pll2_out_sels)); clks[IMX8MQ_SYS3_PLL2_OUT] = imx_clk_mux("sys3_pll2_out", base + 0x48, 4, 1, sys3_pll2_out_sels, ARRAY_SIZE(sys3_pll2_out_sels)); clks[IMX8MQ_DRAM_PLL2_OUT] = imx_clk_mux("dram_pll2_out", base + 0x60, 4, 1, dram_pll2_out_sels, ARRAY_SIZE(dram_pll2_out_sels)); - clks[IMX8MQ_VIDEO2_PLL2_OUT] = imx_clk_mux("video2_pll2_out", base + 0x54, 4, 1, video2_pll2_out_sels, ARRAY_SIZE(video2_pll2_out_sels)); - - /* unbypass all the plls */ - clk_set_parent(clks[IMX8MQ_GPU_PLL_BYPASS], clks[IMX8MQ_GPU_PLL]); - clk_set_parent(clks[IMX8MQ_VPU_PLL_BYPASS], clks[IMX8MQ_VPU_PLL]); - clk_set_parent(clks[IMX8MQ_AUDIO_PLL1_BYPASS], clks[IMX8MQ_AUDIO_PLL1]); - clk_set_parent(clks[IMX8MQ_AUDIO_PLL2_BYPASS], clks[IMX8MQ_AUDIO_PLL2]); - clk_set_parent(clks[IMX8MQ_VIDEO_PLL1_BYPASS], clks[IMX8MQ_VIDEO_PLL1]); - clk_set_parent(clks[IMX8MQ_SYS3_PLL1_OUT], clks[IMX8MQ_SYS3_PLL1]); - clk_set_parent(clks[IMX8MQ_SYS3_PLL2_OUT], clks[IMX8MQ_SYS3_PLL2_DIV]); /* PLL OUT GATE */ clks[IMX8MQ_ARM_PLL_OUT] = imx_clk_gate("arm_pll_out", "arm_pll_bypass", base + 0x28, 21); @@ -306,7 +364,6 @@ static void __init imx8mq_clocks_init(struct device_node *ccm_node) clks[IMX8MQ_SYS2_PLL_OUT] = imx_clk_gate("sys2_pll_out", "sys2_pll2_out", base + 0x3c, 9); clks[IMX8MQ_SYS3_PLL_OUT] = imx_clk_gate("sys3_pll_out", "sys3_pll2_out", base + 0x48, 9); clks[IMX8MQ_DRAM_PLL_OUT] = imx_clk_gate("dram_pll_out", "dram_pll2_out", base + 0x60, 9); - clks[IMX8MQ_VIDEO2_PLL_OUT] = imx_clk_gate("video2_pll_out", "video2_pll2_out", base + 0x54, 9); /* SYS PLL fixed output */ clks[IMX8MQ_SYS1_PLL_40M] = imx_clk_fixed_factor("sys1_pll_40m", "sys1_pll_out", 1, 20); @@ -331,251 +388,172 @@ static void __init imx8mq_clocks_init(struct device_node *ccm_node) np = ccm_node; base = of_iomap(np, 0); - WARN_ON(!base); + if (WARN_ON(!base)) + return -ENOMEM; + /* CORE */ clks[IMX8MQ_CLK_A53_SRC] = imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mq_a53_sels, ARRAY_SIZE(imx8mq_a53_sels)); + clks[IMX8MQ_CLK_VPU_SRC] = imx_clk_mux2("vpu_src", base + 0x8100, 24, 3, imx8mq_vpu_sels, ARRAY_SIZE(imx8mq_vpu_sels)); + clks[IMX8MQ_CLK_GPU_CORE_SRC] = imx_clk_mux2("gpu_core_src", base + 0x8180, 24, 3, imx8mq_gpu_core_sels, ARRAY_SIZE(imx8mq_gpu_core_sels)); + clks[IMX8MQ_CLK_GPU_SHADER_SRC] = imx_clk_mux2("gpu_shader_src", base + 0x8200, 24, 3, imx8mq_gpu_shader_sels, ARRAY_SIZE(imx8mq_gpu_shader_sels)); clks[IMX8MQ_CLK_A53_CG] = imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28); + clks[IMX8MQ_CLK_VPU_CG] = imx_clk_gate3("vpu_cg", "vpu_src", base + 0x8100, 28); + clks[IMX8MQ_CLK_GPU_CORE_CG] = imx_clk_gate3("gpu_core_cg", "gpu_core_src", base + 0x8180, 28); + clks[IMX8MQ_CLK_GPU_SHADER_CG] = imx_clk_gate3("gpu_shader_cg", "gpu_shader_src", base + 0x8200, 28); + clks[IMX8MQ_CLK_A53_DIV] = imx_clk_divider2("arm_a53_div", "arm_a53_cg", base + 0x8000, 0, 3); + clks[IMX8MQ_CLK_VPU_DIV] = imx_clk_divider2("vpu_div", "vpu_cg", base + 0x8100, 0, 3); + clks[IMX8MQ_CLK_GPU_CORE_DIV] = imx_clk_divider2("gpu_core_div", "gpu_core_cg", base + 0x8180, 0, 3); + clks[IMX8MQ_CLK_GPU_SHADER_DIV] = imx_clk_divider2("gpu_shader_div", "gpu_shader_cg", base + 0x8200, 0, 3); /* BUS */ - clks[IMX8MQ_CLK_MAIN_AXI_SRC] = imx_clk_mux2("main_axi_src", base + 0x8800, 24, 3, imx8mq_main_axi_sels, ARRAY_SIZE(imx8mq_main_axi_sels)); - clks[IMX8MQ_CLK_ENET_AXI_SRC] = imx_clk_mux2("enet_axi_src", base + 0x8880, 24, 3, imx8mq_enet_axi_sels, ARRAY_SIZE(imx8mq_enet_axi_sels)); - clks[IMX8MQ_CLK_NAND_USDHC_BUS_SRC] = imx_clk_mux2("nand_usdhc_bus_src", base + 0x8900, 24, 3, imx8mq_nand_usdhc_sels, ARRAY_SIZE(imx8mq_nand_usdhc_sels)); - clks[IMX8MQ_CLK_USB_BUS_SRC] = imx_clk_mux2("usb_bus_src", base + 0x8b80, 24, 3, imx8mq_usb_bus_sels, ARRAY_SIZE(imx8mq_usb_bus_sels)); - clks[IMX8MQ_CLK_NOC_SRC] = imx_clk_mux2("noc_src", base + 0x8d00, 24, 3, imx8mq_noc_sels, ARRAY_SIZE(imx8mq_noc_sels)); - clks[IMX8MQ_CLK_NOC_APB_SRC] = imx_clk_mux2("noc_apb_src", base + 0x8d80, 24, 3, imx8mq_noc_apb_sels, ARRAY_SIZE(imx8mq_noc_apb_sels)); - - clks[IMX8MQ_CLK_MAIN_AXI_CG] = imx_clk_gate3("main_axi_cg", "main_axi_src", base + 0x8800, 28); - clks[IMX8MQ_CLK_ENET_AXI_CG] = imx_clk_gate3("enet_axi_cg", "enet_axi_src", base + 0x8880, 28); - clks[IMX8MQ_CLK_NAND_USDHC_BUS_CG] = imx_clk_gate3("nand_usdhc_bus_cg", "nand_usdhc_bus_src", base + 0x8900, 28); - clks[IMX8MQ_CLK_USB_BUS_CG] = imx_clk_gate3("usb_bus_cg", "usb_bus_src", base + 0x8b80, 28); - clks[IMX8MQ_CLK_NOC_CG] = imx_clk_gate3("noc_cg", "noc_src", base + 0x8d00, 28); - clks[IMX8MQ_CLK_NOC_APB_CG] = imx_clk_gate3("noc_apb_cg", "noc_apb_src", base + 0x8d80, 28); - - clks[IMX8MQ_CLK_MAIN_AXI_PRE_DIV] = imx_clk_divider2("main_axi_pre_div", "main_axi_cg", base + 0x8800, 16, 3); - clks[IMX8MQ_CLK_ENET_AXI_PRE_DIV] = imx_clk_divider2("enet_axi_pre_div", "enet_axi_cg", base + 0x8880, 16, 3); - clks[IMX8MQ_CLK_NAND_USDHC_BUS_PRE_DIV] = imx_clk_divider2("nand_usdhc_bus_pre_div", "nand_usdhc_bus_cg", base + 0x8900, 16, 3); - clks[IMX8MQ_CLK_DISP_AXI_PRE_DIV] = imx_clk_divider2("disp_axi_pre_div", "disp_axi_cg", base + 0x8a00, 16, 3); - clks[IMX8MQ_CLK_DISP_APB_PRE_DIV] = imx_clk_divider2("disp_apb_pre_div", "disp_apb_cg", base + 0x8a80, 16, 3); - clks[IMX8MQ_CLK_DISP_RTRM_PRE_DIV] = imx_clk_divider2("disp_rtrm_pre_div", "disp_rtrm_cg", base + 0x8b00, 16, 3); - clks[IMX8MQ_CLK_USB_BUS_PRE_DIV] = imx_clk_divider2("usb_bus_pre_div", "usb_bus_cg", base + 0x8b80, 16, 3); - clks[IMX8MQ_CLK_GPU_AXI_PRE_DIV] = imx_clk_divider2("gpu_axi_pre_div", "gpu_axi_cg", base + 0x8c00, 16, 3); - clks[IMX8MQ_CLK_GPU_AHB_PRE_DIV] = imx_clk_divider2("gpu_ahb_pre_div", "gpu_ahb_cg", base + 0x8c80, 16, 3); - clks[IMX8MQ_CLK_NOC_PRE_DIV] = imx_clk_divider2("noc_pre_div", "noc_cg", base + 0x8d00, 16, 3); - clks[IMX8MQ_CLK_NOC_APB_PRE_DIV] = imx_clk_divider2("noc_apb_pre_div", "noc_apb_cg", base + 0x8d80, 16, 3); - - clks[IMX8MQ_CLK_MAIN_AXI_DIV] = imx_clk_divider2("main_axi_div", "main_axi_pre_div", base + 0x8800, 0, 6); - clks[IMX8MQ_CLK_ENET_AXI_DIV] = imx_clk_divider2("enet_axi_div", "enet_axi_pre_div", base + 0x8880, 0, 6); - clks[IMX8MQ_CLK_NAND_USDHC_BUS_DIV] = imx_clk_divider2("nand_usdhc_bus_div", "nand_usdhc_bus_pre_div", base + 0x8900, 0, 6); - clks[IMX8MQ_CLK_USB_BUS_DIV] = imx_clk_divider2("usb_bus_div", "usb_bus_pre_div", base + 0x8b80, 0, 6); - clks[IMX8MQ_CLK_NOC_DIV] = imx_clk_divider2("noc_div", "noc_pre_div", base + 0x8d00, 0, 6); - clks[IMX8MQ_CLK_NOC_APB_DIV] = imx_clk_divider2("noc_apb_div", "noc_apb_pre_div", base + 0x8d80, 0, 6); + clks[IMX8MQ_CLK_MAIN_AXI] = imx8m_clk_composite("main_axi", imx8mq_main_axi_sels, base + 0x8800); + clks[IMX8MQ_CLK_ENET_AXI] = imx8m_clk_composite("enet_axi", imx8mq_enet_axi_sels, base + 0x8880); + clks[IMX8MQ_CLK_NAND_USDHC_BUS] = imx8m_clk_composite("nand_usdhc_bus", imx8mq_nand_usdhc_sels, base + 0x8900); + clks[IMX8MQ_CLK_VPU_BUS] = imx8m_clk_composite("vpu_bus", imx8mq_vpu_bus_sels, base + 0x8980); + clks[IMX8MQ_CLK_DISP_AXI] = imx8m_clk_composite("disp_axi", imx8mq_disp_axi_sels, base + 0x8a00); + clks[IMX8MQ_CLK_DISP_APB] = imx8m_clk_composite("disp_apb", imx8mq_disp_apb_sels, base + 0x8a80); + clks[IMX8MQ_CLK_DISP_RTRM] = imx8m_clk_composite("disp_rtrm", imx8mq_disp_rtrm_sels, base + 0x8b00); + clks[IMX8MQ_CLK_USB_BUS] = imx8m_clk_composite("usb_bus", imx8mq_usb_bus_sels, base + 0x8b80); + clks[IMX8MQ_CLK_GPU_AXI] = imx8m_clk_composite("gpu_axi", imx8mq_gpu_axi_sels, base + 0x8c00); + clks[IMX8MQ_CLK_GPU_AHB] = imx8m_clk_composite("gpu_ahb", imx8mq_gpu_ahb_sels, base + 0x8c80); + clks[IMX8MQ_CLK_NOC] = imx8m_clk_composite("noc", imx8mq_noc_sels, base + 0x8d00); + clks[IMX8MQ_CLK_NOC_APB] = imx8m_clk_composite("noc_apb", imx8mq_noc_apb_sels, base + 0x8d80); /* AHB */ - clks[IMX8MQ_CLK_AHB_SRC] = imx_clk_mux2("ahb_src", base + 0x9000, 24, 3, imx8mq_ahb_sels, ARRAY_SIZE(imx8mq_ahb_sels)); - clks[IMX8MQ_CLK_AHB_CG] = imx_clk_gate3("ahb_cg", "ahb_src", base + 0x9000, 28); - clks[IMX8MQ_CLK_AHB_PRE_DIV] = imx_clk_divider2("ahb_pre_div", "ahb_cg", base + 0x9000, 16, 3); - clks[IMX8MQ_CLK_AHB_DIV] = imx_clk_divider_flags("ahb_div", "ahb_pre_div", base + 0x9000, 0, 6, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE); + clks[IMX8MQ_CLK_AHB] = imx8m_clk_composite("ahb", imx8mq_ahb_sels, base + 0x9000); + clks[IMX8MQ_CLK_AUDIO_AHB] = imx8m_clk_composite("audio_ahb", imx8mq_audio_ahb_sels, base + 0x9100); /* IPG */ - clks[IMX8MQ_CLK_IPG_ROOT] = imx_clk_divider2("ipg_root", "ahb_div", base + 0x9080, 0, 1); + clks[IMX8MQ_CLK_IPG_ROOT] = imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1); + clks[IMX8MQ_CLK_IPG_AUDIO_ROOT] = imx_clk_divider2("ipg_audio_root", "audio_ahb", base + 0x9180, 0, 1); /* IP */ - clks[IMX8MQ_CLK_DRAM_ALT_SRC] = imx_clk_mux2("dram_alt_src", base + 0xa000, 24, 3, imx8mq_dram_alt_sels, ARRAY_SIZE(imx8mq_dram_alt_sels)); clks[IMX8MQ_CLK_DRAM_CORE] = imx_clk_mux2("dram_core_clk", base + 0x9800, 24, 1, imx8mq_dram_core_sels, ARRAY_SIZE(imx8mq_dram_core_sels)); - clks[IMX8MQ_CLK_DRAM_APB_SRC] = imx_clk_mux2("dram_apb_src", base + 0xa080, 24, 3, imx8mq_dram_apb_sels, ARRAY_SIZE(imx8mq_dram_apb_sels)); - clks[IMX8MQ_CLK_PCIE1_CTRL_SRC] = imx_clk_mux2("pcie1_ctrl_src", base + 0xa300, 24, 3, imx8mq_pcie1_ctrl_sels, ARRAY_SIZE(imx8mq_pcie1_ctrl_sels)); - clks[IMX8MQ_CLK_PCIE1_PHY_SRC] = imx_clk_mux2("pcie1_phy_src", base + 0xa380, 24, 3, imx8mq_pcie1_phy_sels, ARRAY_SIZE(imx8mq_pcie1_phy_sels)); - clks[IMX8MQ_CLK_PCIE1_AUX_SRC] = imx_clk_mux2("pcie1_aux_src", base + 0xa400, 24, 3, imx8mq_pcie1_aux_sels, ARRAY_SIZE(imx8mq_pcie1_aux_sels)); - clks[IMX8MQ_CLK_DC_PIXEL_SRC] = imx_clk_mux2("dc_pixel_src", base + 0xa480, 24, 3, imx8mq_dc_pixel_sels, ARRAY_SIZE(imx8mq_dc_pixel_sels)); - clks[IMX8MQ_CLK_LCDIF_PIXEL_SRC] = imx_clk_mux2("lcdif_pixel_src", base + 0xa500, 24, 3, imx8mq_lcdif_pixel_sels, ARRAY_SIZE(imx8mq_lcdif_pixel_sels)); - clks[IMX8MQ_CLK_ENET_REF_SRC] = imx_clk_mux2("enet_ref_src", base + 0xa980, 24, 3, imx8mq_enet_ref_sels, ARRAY_SIZE(imx8mq_enet_ref_sels)); - clks[IMX8MQ_CLK_ENET_TIMER_SRC] = imx_clk_mux2("enet_timer_src", base + 0xaa00, 24, 3, imx8mq_enet_timer_sels, ARRAY_SIZE(imx8mq_enet_timer_sels)); - clks[IMX8MQ_CLK_ENET_PHY_REF_SRC] = imx_clk_mux2("enet_phy_src", base + 0xaa80, 24, 3, imx8mq_enet_phy_sels, ARRAY_SIZE(imx8mq_enet_phy_sels)); - clks[IMX8MQ_CLK_NAND_SRC] = imx_clk_mux2("nand_src", base + 0xab00, 24, 3, imx8mq_nand_sels, ARRAY_SIZE(imx8mq_nand_sels)); - clks[IMX8MQ_CLK_QSPI_SRC] = imx_clk_mux2("qspi_src", base + 0xab80, 24, 3, imx8mq_qspi_sels, ARRAY_SIZE(imx8mq_qspi_sels)); - clks[IMX8MQ_CLK_USDHC1_SRC] = imx_clk_mux2("usdhc1_src", base + 0xac00, 24, 3, imx8mq_usdhc1_sels, ARRAY_SIZE(imx8mq_usdhc1_sels)); - clks[IMX8MQ_CLK_USDHC2_SRC] = imx_clk_mux2("usdhc2_src", base + 0xac80, 24, 3, imx8mq_usdhc2_sels, ARRAY_SIZE(imx8mq_usdhc2_sels)); - clks[IMX8MQ_CLK_I2C1_SRC] = imx_clk_mux2("i2c1_src", base + 0xad00, 24, 3, imx8mq_i2c1_sels, ARRAY_SIZE(imx8mq_i2c1_sels)); - clks[IMX8MQ_CLK_I2C2_SRC] = imx_clk_mux2("i2c2_src", base + 0xad80, 24, 3, imx8mq_i2c2_sels, ARRAY_SIZE(imx8mq_i2c2_sels)); - clks[IMX8MQ_CLK_I2C3_SRC] = imx_clk_mux2("i2c3_src", base + 0xae00, 24, 3, imx8mq_i2c3_sels, ARRAY_SIZE(imx8mq_i2c3_sels)); - clks[IMX8MQ_CLK_I2C4_SRC] = imx_clk_mux2("i2c4_src", base + 0xae80, 24, 3, imx8mq_i2c4_sels, ARRAY_SIZE(imx8mq_i2c4_sels)); - clks[IMX8MQ_CLK_UART1_SRC] = imx_clk_mux2("uart1_src", base + 0xaf00, 24, 3, imx8mq_uart1_sels, ARRAY_SIZE(imx8mq_uart1_sels)); - clks[IMX8MQ_CLK_UART2_SRC] = imx_clk_mux2("uart2_src", base + 0xaf80, 24, 3, imx8mq_uart2_sels, ARRAY_SIZE(imx8mq_uart2_sels)); - clks[IMX8MQ_CLK_UART3_SRC] = imx_clk_mux2("uart3_src", base + 0xb000, 24, 3, imx8mq_uart3_sels, ARRAY_SIZE(imx8mq_uart3_sels)); - clks[IMX8MQ_CLK_UART4_SRC] = imx_clk_mux2("uart4_src", base + 0xb080, 24, 3, imx8mq_uart4_sels, ARRAY_SIZE(imx8mq_uart4_sels)); - clks[IMX8MQ_CLK_USB_CORE_REF_SRC] = imx_clk_mux2("usb_core_ref_src", base + 0xb100, 24, 3, imx8mq_usb_core_sels, ARRAY_SIZE(imx8mq_usb_core_sels)); - clks[IMX8MQ_CLK_USB_PHY_REF_SRC] = imx_clk_mux2("usb_phy_ref_src", base + 0xb180, 24, 3, imx8mq_usb_phy_sels, ARRAY_SIZE(imx8mq_usb_phy_sels)); - clks[IMX8MQ_CLK_ECSPI1_SRC] = imx_clk_mux2("ecspi1_src", base + 0xb280, 24, 3, imx8mq_ecspi1_sels, ARRAY_SIZE(imx8mq_ecspi1_sels)); - clks[IMX8MQ_CLK_ECSPI2_SRC] = imx_clk_mux2("ecspi2_src", base + 0xb300, 24, 3, imx8mq_ecspi2_sels, ARRAY_SIZE(imx8mq_ecspi2_sels)); - clks[IMX8MQ_CLK_PWM1_SRC] = imx_clk_mux2("pwm1_src", base + 0xb380, 24, 3, imx8mq_pwm1_sels, ARRAY_SIZE(imx8mq_pwm1_sels)); - clks[IMX8MQ_CLK_PWM2_SRC] = imx_clk_mux2("pwm2_src", base + 0xb400, 24, 3, imx8mq_pwm2_sels, ARRAY_SIZE(imx8mq_pwm2_sels)); - clks[IMX8MQ_CLK_PWM3_SRC] = imx_clk_mux2("pwm3_src", base + 0xb480, 24, 3, imx8mq_pwm3_sels, ARRAY_SIZE(imx8mq_pwm3_sels)); - clks[IMX8MQ_CLK_PWM4_SRC] = imx_clk_mux2("pwm4_src", base + 0xb500, 24, 3, imx8mq_pwm4_sels, ARRAY_SIZE(imx8mq_pwm4_sels)); - clks[IMX8MQ_CLK_GPT1_SRC] = imx_clk_mux2("gpt1_src", base + 0xb580, 24, 3, imx8mq_gpt1_sels, ARRAY_SIZE(imx8mq_gpt1_sels)); - clks[IMX8MQ_CLK_WDOG_SRC] = imx_clk_mux2("wdog_src", base + 0xb900, 24, 3, imx8mq_wdog_sels, ARRAY_SIZE(imx8mq_wdog_sels)); - clks[IMX8MQ_CLK_WRCLK_SRC] = imx_clk_mux2("wrclk_src", base + 0xb980, 24, 3, imx8mq_wrclk_sels, ARRAY_SIZE(imx8mq_wrclk_sels)); - clks[IMX8MQ_CLK_CLKO2_SRC] = imx_clk_mux2("clko2_src", base + 0xba80, 24, 3, imx8mq_clko2_sels, ARRAY_SIZE(imx8mq_clko2_sels)); - clks[IMX8MQ_CLK_PCIE2_CTRL_SRC] = imx_clk_mux2("pcie2_ctrl_src", base + 0xc000, 24, 3, imx8mq_pcie2_ctrl_sels, ARRAY_SIZE(imx8mq_pcie2_ctrl_sels)); - clks[IMX8MQ_CLK_PCIE2_PHY_SRC] = imx_clk_mux2("pcie2_phy_src", base + 0xc080, 24, 3, imx8mq_pcie2_phy_sels, ARRAY_SIZE(imx8mq_pcie2_phy_sels)); - clks[IMX8MQ_CLK_PCIE2_AUX_SRC] = imx_clk_mux2("pcie2_aux_src", base + 0xc100, 24, 3, imx8mq_pcie2_aux_sels, ARRAY_SIZE(imx8mq_pcie2_aux_sels)); - clks[IMX8MQ_CLK_ECSPI3_SRC] = imx_clk_mux2("ecspi3_src", base + 0xc180, 24, 3, imx8mq_ecspi3_sels, ARRAY_SIZE(imx8mq_ecspi3_sels)); - - clks[IMX8MQ_CLK_DRAM_ALT_CG] = imx_clk_gate3("dram_alt_cg", "dram_alt_src", base + 0xa000, 28); - clks[IMX8MQ_CLK_DRAM_APB_CG] = imx_clk_gate3("dram_apb_cg", "dram_apb_src", base + 0xa080, 28); - clks[IMX8MQ_CLK_PCIE1_CTRL_CG] = imx_clk_gate3("pcie1_ctrl_cg", "pcie1_ctrl_src", base + 0xa300, 28); - clks[IMX8MQ_CLK_PCIE1_PHY_CG] = imx_clk_gate3("pcie1_phy_cg", "pcie1_phy_src", base + 0xa380, 28); - clks[IMX8MQ_CLK_PCIE1_AUX_CG] = imx_clk_gate3("pcie1_aux_cg", "pcie1_aux_src", base + 0xa400, 28); - clks[IMX8MQ_CLK_ENET_REF_CG] = imx_clk_gate3("enet_ref_cg", "enet_ref_src", base + 0xa980, 28); - clks[IMX8MQ_CLK_ENET_TIMER_CG] = imx_clk_gate3("enet_timer_cg", "enet_timer_src", base + 0xaa00, 28); - clks[IMX8MQ_CLK_ENET_PHY_REF_CG] = imx_clk_gate3("enet_phy_cg", "enet_phy_src", base + 0xaa80, 28); - clks[IMX8MQ_CLK_NAND_CG] = imx_clk_gate3("nand_cg", "nand_src", base + 0xab00, 28); - clks[IMX8MQ_CLK_QSPI_CG] = imx_clk_gate3("qspi_cg", "qspi_src", base + 0xab80, 28); - clks[IMX8MQ_CLK_USDHC1_CG] = imx_clk_gate3("usdhc1_cg", "usdhc1_src", base + 0xac00, 28); - clks[IMX8MQ_CLK_USDHC2_CG] = imx_clk_gate3("usdhc2_cg", "usdhc2_src", base + 0xac80, 28); - clks[IMX8MQ_CLK_I2C1_CG] = imx_clk_gate3("i2c1_cg", "i2c1_src", base + 0xad00, 28); - clks[IMX8MQ_CLK_I2C2_CG] = imx_clk_gate3("i2c2_cg", "i2c2_src", base + 0xad80, 28); - clks[IMX8MQ_CLK_I2C3_CG] = imx_clk_gate3("i2c3_cg", "i2c3_src", base + 0xae00, 28); - clks[IMX8MQ_CLK_I2C4_CG] = imx_clk_gate3("i2c4_cg", "i2c4_src", base + 0xae80, 28); - clks[IMX8MQ_CLK_UART1_CG] = imx_clk_gate3("uart1_cg", "uart1_src", base + 0xaf00, 28); - clks[IMX8MQ_CLK_UART2_CG] = imx_clk_gate3("uart2_cg", "uart2_src", base + 0xaf80, 28); - clks[IMX8MQ_CLK_UART3_CG] = imx_clk_gate3("uart3_cg", "uart3_src", base + 0xb000, 28); - clks[IMX8MQ_CLK_UART4_CG] = imx_clk_gate3("uart4_cg", "uart4_src", base + 0xb080, 28); - clks[IMX8MQ_CLK_USB_CORE_REF_CG] = imx_clk_gate3("usb_core_ref_cg", "usb_core_ref_src", base + 0xb100, 28); - clks[IMX8MQ_CLK_USB_PHY_REF_CG] = imx_clk_gate3("usb_phy_ref_cg", "usb_phy_ref_src", base + 0xb180, 28); - clks[IMX8MQ_CLK_ECSPI1_CG] = imx_clk_gate3("ecspi1_cg", "ecspi1_src", base + 0xb280, 28); - clks[IMX8MQ_CLK_ECSPI2_CG] = imx_clk_gate3("ecspi2_cg", "ecspi2_src", base + 0xb300, 28); - clks[IMX8MQ_CLK_PWM1_CG] = imx_clk_gate3("pwm1_cg", "pwm1_src", base + 0xb380, 28); - clks[IMX8MQ_CLK_PWM2_CG] = imx_clk_gate3("pwm2_cg", "pwm2_src", base + 0xb400, 28); - clks[IMX8MQ_CLK_PWM3_CG] = imx_clk_gate3("pwm3_cg", "pwm3_src", base + 0xb480, 28); - clks[IMX8MQ_CLK_PWM4_CG] = imx_clk_gate3("pwm4_cg", "pwm4_src", base + 0xb500, 28); - clks[IMX8MQ_CLK_GPT1_CG] = imx_clk_gate3("gpt1_cg", "gpt1_src", base + 0xb580, 28); - clks[IMX8MQ_CLK_WDOG_CG] = imx_clk_gate3("wdog_cg", "wdog_src", base + 0xb900, 28); - clks[IMX8MQ_CLK_WRCLK_CG] = imx_clk_gate3("wrclk_cg", "wrclk_src", base + 0xb980, 28); - clks[IMX8MQ_CLK_CLKO2_CG] = imx_clk_gate3("clko2_cg", "clko2_src", base + 0xba80, 28); - clks[IMX8MQ_CLK_PCIE2_CTRL_CG] = imx_clk_gate3("pcie2_ctrl_cg", "pcie2_ctrl_src", base + 0xc000, 28); - clks[IMX8MQ_CLK_PCIE2_PHY_CG] = imx_clk_gate3("pcie2_phy_cg", "pcie2_phy_src", base + 0xc080, 28); - clks[IMX8MQ_CLK_PCIE2_AUX_CG] = imx_clk_gate3("pcie2_aux_cg", "pcie2_aux_src", base + 0xc100, 28); - clks[IMX8MQ_CLK_ECSPI3_CG] = imx_clk_gate3("ecspi3_cg", "ecspi3_src", base + 0xc180, 28); - - clks[IMX8MQ_CLK_DRAM_ALT_PRE_DIV] = imx_clk_divider2("dram_alt_pre_div", "dram_alt_cg", base + 0xa000, 16, 3); - clks[IMX8MQ_CLK_DRAM_APB_PRE_DIV] = imx_clk_divider_flags("dram_apb_pre_div", "dram_apb_cg", base + 0xa080, 16, 3, CLK_OPS_PARENT_ENABLE); - clks[IMX8MQ_CLK_PCIE1_CTRL_PRE_DIV] = imx_clk_divider2("pcie1_ctrl_pre_div", "pcie1_ctrl_cg", base + 0xa300, 16, 3); - clks[IMX8MQ_CLK_PCIE1_PHY_PRE_DIV] = imx_clk_divider2("pcie1_phy_pre_div", "pcie1_phy_cg", base + 0xa380, 16, 3); - clks[IMX8MQ_CLK_PCIE1_AUX_PRE_DIV] = imx_clk_divider2("pcie1_aux_pre_div", "pcie1_aux_cg", base + 0xa400, 16, 3); - clks[IMX8MQ_CLK_DC_PIXEL_PRE_DIV] = imx_clk_divider2("dc_pixel_pre_div", "dc_pixel_cg", base + 0xa480, 16, 3); - clks[IMX8MQ_CLK_LCDIF_PIXEL_PRE_DIV] = imx_clk_divider2("lcdif_pixel_pre_div", "lcdif_pixel_cg", base + 0xa500, 16, 3); - clks[IMX8MQ_CLK_SPDIF1_PRE_DIV] = imx_clk_divider2("spdif1_pre_div", "spdif1_cg", base + 0xa880, 16, 3); - clks[IMX8MQ_CLK_SPDIF2_PRE_DIV] = imx_clk_divider2("spdif2_pre_div", "spdif2_cg", base + 0xa900, 16, 3); - clks[IMX8MQ_CLK_ENET_REF_PRE_DIV] = imx_clk_divider2("enet_ref_pre_div", "enet_ref_cg", base + 0xa980, 16, 3); - clks[IMX8MQ_CLK_ENET_TIMER_PRE_DIV] = imx_clk_divider2("enet_timer_pre_div", "enet_timer_cg", base + 0xaa00, 16, 3); - clks[IMX8MQ_CLK_ENET_PHY_REF_PRE_DIV] = imx_clk_divider2("enet_phy_pre_div", "enet_phy_cg", base + 0xaa80, 16, 3); - clks[IMX8MQ_CLK_NAND_PRE_DIV] = imx_clk_divider2("nand_pre_div", "nand_cg", base + 0xab00, 16, 3); - clks[IMX8MQ_CLK_QSPI_PRE_DIV] = imx_clk_divider2("qspi_pre_div", "qspi_cg", base + 0xab80, 16, 3); - clks[IMX8MQ_CLK_USDHC1_PRE_DIV] = imx_clk_divider2("usdhc1_pre_div", "usdhc1_cg", base + 0xac00, 16, 3); - clks[IMX8MQ_CLK_USDHC2_PRE_DIV] = imx_clk_divider2("usdhc2_pre_div", "usdhc2_cg", base + 0xac80, 16, 3); - clks[IMX8MQ_CLK_I2C1_PRE_DIV] = imx_clk_divider2("i2c1_pre_div", "i2c1_cg", base + 0xad00, 16, 3); - clks[IMX8MQ_CLK_I2C2_PRE_DIV] = imx_clk_divider2("i2c2_pre_div", "i2c2_cg", base + 0xad80, 16, 3); - clks[IMX8MQ_CLK_I2C3_PRE_DIV] = imx_clk_divider2("i2c3_pre_div", "i2c3_cg", base + 0xae00, 16, 3); - clks[IMX8MQ_CLK_I2C4_PRE_DIV] = imx_clk_divider2("i2c4_pre_div", "i2c4_cg", base + 0xae80, 16, 3); - clks[IMX8MQ_CLK_UART1_PRE_DIV] = imx_clk_divider2("uart1_pre_div", "uart1_cg", base + 0xaf00, 16, 3); - clks[IMX8MQ_CLK_UART2_PRE_DIV] = imx_clk_divider2("uart2_pre_div", "uart2_cg", base + 0xaf80, 16, 3); - clks[IMX8MQ_CLK_UART3_PRE_DIV] = imx_clk_divider2("uart3_pre_div", "uart3_cg", base + 0xb000, 16, 3); - clks[IMX8MQ_CLK_UART4_PRE_DIV] = imx_clk_divider2("uart4_pre_div", "uart4_cg", base + 0xb080, 16, 3); - clks[IMX8MQ_CLK_USB_CORE_REF_PRE_DIV] = imx_clk_divider2("usb_core_ref_pre_div", "usb_core_ref_cg", base + 0xb100, 16, 3); - clks[IMX8MQ_CLK_USB_PHY_REF_PRE_DIV] = imx_clk_divider2("usb_phy_ref_pre_div", "usb_phy_ref_cg", base + 0xb180, 16, 3); - clks[IMX8MQ_CLK_ECSPI1_PRE_DIV] = imx_clk_divider2("ecspi1_pre_div", "ecspi1_cg", base + 0xb280, 16, 3); - clks[IMX8MQ_CLK_ECSPI2_PRE_DIV] = imx_clk_divider2("ecspi2_pre_div", "ecspi2_cg", base + 0xb300, 16, 3); - clks[IMX8MQ_CLK_PWM1_PRE_DIV] = imx_clk_divider2("pwm1_pre_div", "pwm1_cg", base + 0xb380, 16, 3); - clks[IMX8MQ_CLK_PWM2_PRE_DIV] = imx_clk_divider2("pwm2_pre_div", "pwm2_cg", base + 0xb400, 16, 3); - clks[IMX8MQ_CLK_PWM3_PRE_DIV] = imx_clk_divider2("pwm3_pre_div", "pwm3_cg", base + 0xb480, 16, 3); - clks[IMX8MQ_CLK_PWM4_PRE_DIV] = imx_clk_divider2("pwm4_pre_div", "pwm4_cg", base + 0xb500, 16, 3); - clks[IMX8MQ_CLK_GPT1_PRE_DIV] = imx_clk_divider2("gpt1_pre_div", "gpt1_cg", base + 0xb580, 16, 3); - clks[IMX8MQ_CLK_WDOG_PRE_DIV] = imx_clk_divider2("wdog_pre_div", "wdog_cg", base + 0xb900, 16, 3); - clks[IMX8MQ_CLK_WRCLK_PRE_DIV] = imx_clk_divider2("wrclk_pre_div", "wrclk_cg", base + 0xb980, 16, 3); - clks[IMX8MQ_CLK_CLKO2_PRE_DIV] = imx_clk_divider2("clko2_pre_div", "clko2_cg", base + 0xba80, 16, 3); - clks[IMX8MQ_CLK_PCIE2_CTRL_PRE_DIV] = imx_clk_divider2("pcie2_ctrl_pre_div", "pcie2_ctrl_cg", base + 0xc000, 16, 3); - clks[IMX8MQ_CLK_PCIE2_PHY_PRE_DIV] = imx_clk_divider2("pcie2_phy_pre_div", "pcie2_phy_cg", base + 0xc080, 16, 3); - clks[IMX8MQ_CLK_PCIE2_AUX_PRE_DIV] = imx_clk_divider2("pcie2_aux_pre_div", "pcie2_aux_cg", base + 0xc100, 16, 3); - clks[IMX8MQ_CLK_ECSPI3_PRE_DIV] = imx_clk_divider2("ecspi3_pre_div", "ecspi3_cg", base + 0xc180, 16, 3); - - clks[IMX8MQ_CLK_DRAM_ALT_DIV] = imx_clk_divider2("dram_alt_div", "dram_alt_pre_div", base + 0xa000, 0, 6); - clks[IMX8MQ_CLK_DRAM_APB_DIV] = imx_clk_divider2("dram_apb_div", "dram_apb_pre_div", base + 0xa080, 0, 6); - clks[IMX8MQ_CLK_PCIE1_CTRL_DIV] = imx_clk_divider2("pcie1_ctrl_div", "pcie1_ctrl_pre_div", base + 0xa300, 0, 6); - clks[IMX8MQ_CLK_PCIE1_PHY_DIV] = imx_clk_divider2("pcie1_phy_div", "pcie1_phy_pre_div", base + 0xa380, 0, 6); - clks[IMX8MQ_CLK_PCIE1_AUX_DIV] = imx_clk_divider2("pcie1_aux_div", "pcie1_aux_pre_div", base + 0xa400, 0, 6); - clks[IMX8MQ_CLK_DC_PIXEL_DIV] = imx_clk_divider2("dc_pixel_div", "dc_pixel_pre_div", base + 0xa480, 0, 6); - clks[IMX8MQ_CLK_LCDIF_PIXEL_DIV] = imx_clk_divider2("lcdif_pixel_div", "lcdif_pixel_pre_div", base + 0xa500, 0, 6); - clks[IMX8MQ_CLK_ENET_REF_DIV] = imx_clk_divider2("enet_ref_div", "enet_ref_pre_div", base + 0xa980, 0, 6); - clks[IMX8MQ_CLK_ENET_TIMER_DIV] = imx_clk_divider2("enet_timer_div", "enet_timer_pre_div", base + 0xaa00, 0, 6); - clks[IMX8MQ_CLK_ENET_PHY_REF_DIV] = imx_clk_divider2("enet_phy_div", "enet_phy_pre_div", base + 0xaa80, 0, 6); - clks[IMX8MQ_CLK_NAND_DIV] = imx_clk_divider2("nand_div", "nand_pre_div", base + 0xab00, 0, 6); - clks[IMX8MQ_CLK_QSPI_DIV] = imx_clk_divider2("qspi_div", "qspi_pre_div", base + 0xab80, 0, 6); - clks[IMX8MQ_CLK_USDHC1_DIV] = imx_clk_divider2("usdhc1_div", "usdhc1_pre_div", base + 0xac00, 0, 6); - clks[IMX8MQ_CLK_USDHC2_DIV] = imx_clk_divider2("usdhc2_div", "usdhc2_pre_div", base + 0xac80, 0, 6); - clks[IMX8MQ_CLK_I2C1_DIV] = imx_clk_divider2("i2c1_div", "i2c1_pre_div", base + 0xad00, 0, 6); - clks[IMX8MQ_CLK_I2C2_DIV] = imx_clk_divider2("i2c2_div", "i2c2_pre_div", base + 0xad80, 0, 6); - clks[IMX8MQ_CLK_I2C3_DIV] = imx_clk_divider2("i2c3_div", "i2c3_pre_div", base + 0xae00, 0, 6); - clks[IMX8MQ_CLK_I2C4_DIV] = imx_clk_divider2("i2c4_div", "i2c4_pre_div", base + 0xae80, 0, 6); - clks[IMX8MQ_CLK_UART1_DIV] = imx_clk_divider2("uart1_div", "uart1_pre_div", base + 0xaf00, 0, 6); - clks[IMX8MQ_CLK_UART2_DIV] = imx_clk_divider2("uart2_div", "uart2_pre_div", base + 0xaf80, 0, 6); - clks[IMX8MQ_CLK_UART3_DIV] = imx_clk_divider2("uart3_div", "uart3_pre_div", base + 0xb000, 0, 6); - clks[IMX8MQ_CLK_UART4_DIV] = imx_clk_divider2("uart4_div", "uart4_pre_div", base + 0xb080, 0, 6); - clks[IMX8MQ_CLK_USB_CORE_REF_DIV] = imx_clk_divider2("usb_core_ref_div", "usb_core_ref_pre_div", base + 0xb100, 0, 6); - clks[IMX8MQ_CLK_USB_PHY_REF_DIV] = imx_clk_divider2("usb_phy_ref_div", "usb_phy_ref_pre_div", base + 0xb180, 0, 6); - clks[IMX8MQ_CLK_ECSPI1_DIV] = imx_clk_divider2("ecspi1_div", "ecspi1_pre_div", base + 0xb280, 0, 6); - clks[IMX8MQ_CLK_ECSPI2_DIV] = imx_clk_divider2("ecspi2_div", "ecspi2_pre_div", base + 0xb300, 0, 6); - clks[IMX8MQ_CLK_PWM1_DIV] = imx_clk_divider2("pwm1_div", "pwm1_pre_div", base + 0xb380, 0, 6); - clks[IMX8MQ_CLK_PWM2_DIV] = imx_clk_divider2("pwm2_div", "pwm2_pre_div", base + 0xb400, 0, 6); - clks[IMX8MQ_CLK_PWM3_DIV] = imx_clk_divider2("pwm3_div", "pwm3_pre_div", base + 0xb480, 0, 6); - clks[IMX8MQ_CLK_PWM4_DIV] = imx_clk_divider2("pwm4_div", "pwm4_pre_div", base + 0xb500, 0, 6); - clks[IMX8MQ_CLK_GPT1_DIV] = imx_clk_divider2("gpt1_div", "gpt1_pre_div", base + 0xb580, 0, 6); - clks[IMX8MQ_CLK_WDOG_DIV] = imx_clk_divider2("wdog_div", "wdog_pre_div", base + 0xb900, 0, 6); - clks[IMX8MQ_CLK_WRCLK_DIV] = imx_clk_divider2("wrclk_div", "wrclk_pre_div", base + 0xb980, 0, 6); - clks[IMX8MQ_CLK_CLKO2_DIV] = imx_clk_divider2("clko2_div", "clko2_pre_div", base + 0xba80, 0, 6); - clks[IMX8MQ_CLK_PCIE2_CTRL_DIV] = imx_clk_divider2("pcie2_ctrl_div", "pcie2_ctrl_pre_div", base + 0xc000, 0, 6); - clks[IMX8MQ_CLK_PCIE2_PHY_DIV] = imx_clk_divider2("pcie2_phy_div", "pcie2_phy_pre_div", base + 0xc080, 0, 6); - clks[IMX8MQ_CLK_PCIE2_AUX_DIV] = imx_clk_divider2("pcie2_aux_div", "pcie2_aux_pre_div", base + 0xc100, 0, 6); - clks[IMX8MQ_CLK_ECSPI3_DIV] = imx_clk_divider2("ecspi3_div", "ecspi3_pre_div", base + 0xc180, 0, 6); - - /*FIXME, the doc is not ready now */ - clks[IMX8MQ_CLK_ECSPI1_ROOT] = imx_clk_gate4("ecspi1_root_clk", "ecspi1_div", base + 0x4070, 0); - clks[IMX8MQ_CLK_ECSPI2_ROOT] = imx_clk_gate4("ecspi2_root_clk", "ecspi2_div", base + 0x4080, 0); - clks[IMX8MQ_CLK_ECSPI3_ROOT] = imx_clk_gate4("ecspi3_root_clk", "ecspi3_div", base + 0x4090, 0); - clks[IMX8MQ_CLK_ENET1_ROOT] = imx_clk_gate4("enet1_root_clk", "enet_axi_div", base + 0x40a0, 0); - clks[IMX8MQ_CLK_GPT1_ROOT] = imx_clk_gate4("gpt1_root_clk", "gpt1_div", base + 0x4100, 0); - clks[IMX8MQ_CLK_I2C1_ROOT] = imx_clk_gate4("i2c1_root_clk", "i2c1_div", base + 0x4170, 0); - clks[IMX8MQ_CLK_I2C2_ROOT] = imx_clk_gate4("i2c2_root_clk", "i2c2_div", base + 0x4180, 0); - clks[IMX8MQ_CLK_I2C3_ROOT] = imx_clk_gate4("i2c3_root_clk", "i2c3_div", base + 0x4190, 0); - clks[IMX8MQ_CLK_I2C4_ROOT] = imx_clk_gate4("i2c4_root_clk", "i2c4_div", base + 0x41a0, 0); + + clks[IMX8MQ_CLK_DRAM_ALT] = imx8m_clk_composite("dram_alt", imx8mq_dram_alt_sels, base + 0xa000); + clks[IMX8MQ_CLK_DRAM_APB] = imx8m_clk_composite("dram_apb", imx8mq_dram_apb_sels, base + 0xa080); + clks[IMX8MQ_CLK_VPU_G1] = imx8m_clk_composite("vpu_g1", imx8mq_vpu_g1_sels, base + 0xa100); + clks[IMX8MQ_CLK_VPU_G2] = imx8m_clk_composite("vpu_g2", imx8mq_vpu_g2_sels, base + 0xa180); + clks[IMX8MQ_CLK_DISP_DTRC] = imx8m_clk_composite("disp_dtrc", imx8mq_disp_dtrc_sels, base + 0xa200); + clks[IMX8MQ_CLK_DISP_DC8000] = imx8m_clk_composite("disp_dc8000", imx8mq_disp_dc8000_sels, base + 0xa280); + clks[IMX8MQ_CLK_PCIE1_CTRL] = imx8m_clk_composite("pcie1_ctrl", imx8mq_pcie1_ctrl_sels, base + 0xa300); + clks[IMX8MQ_CLK_PCIE1_PHY] = imx8m_clk_composite("pcie1_phy", imx8mq_pcie1_phy_sels, base + 0xa380); + clks[IMX8MQ_CLK_PCIE1_AUX] = imx8m_clk_composite("pcie1_aux", imx8mq_pcie1_aux_sels, base + 0xa400); + clks[IMX8MQ_CLK_DC_PIXEL] = imx8m_clk_composite("dc_pixel", imx8mq_dc_pixel_sels, base + 0xa480); + clks[IMX8MQ_CLK_LCDIF_PIXEL] = imx8m_clk_composite("lcdif_pixel", imx8mq_lcdif_pixel_sels, base + 0xa500); + clks[IMX8MQ_CLK_SAI1] = imx8m_clk_composite("sai1", imx8mq_sai1_sels, base + 0xa580); + clks[IMX8MQ_CLK_SAI2] = imx8m_clk_composite("sai2", imx8mq_sai2_sels, base + 0xa600); + clks[IMX8MQ_CLK_SAI3] = imx8m_clk_composite("sai3", imx8mq_sai3_sels, base + 0xa680); + clks[IMX8MQ_CLK_SAI4] = imx8m_clk_composite("sai4", imx8mq_sai4_sels, base + 0xa700); + clks[IMX8MQ_CLK_SAI5] = imx8m_clk_composite("sai5", imx8mq_sai5_sels, base + 0xa780); + clks[IMX8MQ_CLK_SAI6] = imx8m_clk_composite("sai6", imx8mq_sai6_sels, base + 0xa800); + clks[IMX8MQ_CLK_SPDIF1] = imx8m_clk_composite("spdif1", imx8mq_spdif1_sels, base + 0xa880); + clks[IMX8MQ_CLK_SPDIF2] = imx8m_clk_composite("spdif2", imx8mq_spdif2_sels, base + 0xa900); + clks[IMX8MQ_CLK_ENET_REF] = imx8m_clk_composite("enet_ref", imx8mq_enet_ref_sels, base + 0xa980); + clks[IMX8MQ_CLK_ENET_TIMER] = imx8m_clk_composite("enet_timer", imx8mq_enet_timer_sels, base + 0xaa00); + clks[IMX8MQ_CLK_ENET_PHY_REF] = imx8m_clk_composite("enet_phy", imx8mq_enet_phy_sels, base + 0xaa80); + clks[IMX8MQ_CLK_NAND] = imx8m_clk_composite("nand", imx8mq_nand_sels, base + 0xab00); + clks[IMX8MQ_CLK_QSPI] = imx8m_clk_composite("qspi", imx8mq_qspi_sels, base + 0xab80); + clks[IMX8MQ_CLK_USDHC1] = imx8m_clk_composite("usdhc1", imx8mq_usdhc1_sels, base + 0xac00); + clks[IMX8MQ_CLK_USDHC2] = imx8m_clk_composite("usdhc2", imx8mq_usdhc2_sels, base + 0xac80); + clks[IMX8MQ_CLK_I2C1] = imx8m_clk_composite("i2c1", imx8mq_i2c1_sels, base + 0xad00); + clks[IMX8MQ_CLK_I2C2] = imx8m_clk_composite("i2c2", imx8mq_i2c2_sels, base + 0xad80); + clks[IMX8MQ_CLK_I2C3] = imx8m_clk_composite("i2c3", imx8mq_i2c3_sels, base + 0xae00); + clks[IMX8MQ_CLK_I2C4] = imx8m_clk_composite("i2c4", imx8mq_i2c4_sels, base + 0xae80); + clks[IMX8MQ_CLK_UART1] = imx8m_clk_composite("uart1", imx8mq_uart1_sels, base + 0xaf00); + clks[IMX8MQ_CLK_UART2] = imx8m_clk_composite("uart2", imx8mq_uart2_sels, base + 0xaf80); + clks[IMX8MQ_CLK_UART3] = imx8m_clk_composite("uart3", imx8mq_uart3_sels, base + 0xb000); + clks[IMX8MQ_CLK_UART4] = imx8m_clk_composite("uart4", imx8mq_uart4_sels, base + 0xb080); + clks[IMX8MQ_CLK_USB_CORE_REF] = imx8m_clk_composite("usb_core_ref", imx8mq_usb_core_sels, base + 0xb100); + clks[IMX8MQ_CLK_USB_PHY_REF] = imx8m_clk_composite("usb_phy_ref", imx8mq_usb_phy_sels, base + 0xb180); + clks[IMX8MQ_CLK_ECSPI1] = imx8m_clk_composite("ecspi1", imx8mq_ecspi1_sels, base + 0xb280); + clks[IMX8MQ_CLK_ECSPI2] = imx8m_clk_composite("ecspi2", imx8mq_ecspi2_sels, base + 0xb300); + clks[IMX8MQ_CLK_PWM1] = imx8m_clk_composite("pwm1", imx8mq_pwm1_sels, base + 0xb380); + clks[IMX8MQ_CLK_PWM2] = imx8m_clk_composite("pwm2", imx8mq_pwm2_sels, base + 0xb400); + clks[IMX8MQ_CLK_PWM3] = imx8m_clk_composite("pwm3", imx8mq_pwm3_sels, base + 0xb480); + clks[IMX8MQ_CLK_PWM4] = imx8m_clk_composite("pwm4", imx8mq_pwm4_sels, base + 0xb500); + clks[IMX8MQ_CLK_GPT1] = imx8m_clk_composite("gpt1", imx8mq_gpt1_sels, base + 0xb580); + clks[IMX8MQ_CLK_WDOG] = imx8m_clk_composite("wdog", imx8mq_wdog_sels, base + 0xb900); + clks[IMX8MQ_CLK_WRCLK] = imx8m_clk_composite("wrclk", imx8mq_wrclk_sels, base + 0xb980); + clks[IMX8MQ_CLK_CLKO2] = imx8m_clk_composite("clko2", imx8mq_clko2_sels, base + 0xba80); + clks[IMX8MQ_CLK_DSI_CORE] = imx8m_clk_composite("dsi_core", imx8mq_dsi_core_sels, base + 0xbb00); + clks[IMX8MQ_CLK_DSI_PHY_REF] = imx8m_clk_composite("dsi_phy_ref", imx8mq_dsi_phy_sels, base + 0xbb80); + clks[IMX8MQ_CLK_DSI_DBI] = imx8m_clk_composite("dsi_dbi", imx8mq_dsi_dbi_sels, base + 0xbc00); + clks[IMX8MQ_CLK_DSI_ESC] = imx8m_clk_composite("dsi_esc", imx8mq_dsi_esc_sels, base + 0xbc80); + clks[IMX8MQ_CLK_DSI_AHB] = imx8m_clk_composite("dsi_ahb", imx8mq_dsi_ahb_sels, base + 0x9200); + clks[IMX8MQ_CLK_CSI1_CORE] = imx8m_clk_composite("csi1_core", imx8mq_csi1_core_sels, base + 0xbd00); + clks[IMX8MQ_CLK_CSI1_PHY_REF] = imx8m_clk_composite("csi1_phy_ref", imx8mq_csi1_phy_sels, base + 0xbd80); + clks[IMX8MQ_CLK_CSI1_ESC] = imx8m_clk_composite("csi1_esc", imx8mq_csi1_esc_sels, base + 0xbe00); + clks[IMX8MQ_CLK_CSI2_CORE] = imx8m_clk_composite("csi2_core", imx8mq_csi2_core_sels, base + 0xbe80); + clks[IMX8MQ_CLK_CSI2_PHY_REF] = imx8m_clk_composite("csi2_phy_ref", imx8mq_csi2_phy_sels, base + 0xbf00); + clks[IMX8MQ_CLK_CSI2_ESC] = imx8m_clk_composite("csi2_esc", imx8mq_csi2_esc_sels, base + 0xbf80); + clks[IMX8MQ_CLK_PCIE2_CTRL] = imx8m_clk_composite("pcie2_ctrl", imx8mq_pcie2_ctrl_sels, base + 0xc000); + clks[IMX8MQ_CLK_PCIE2_PHY] = imx8m_clk_composite("pcie2_phy", imx8mq_pcie2_phy_sels, base + 0xc080); + clks[IMX8MQ_CLK_PCIE2_AUX] = imx8m_clk_composite("pcie2_aux", imx8mq_pcie2_aux_sels, base + 0xc100); + clks[IMX8MQ_CLK_ECSPI3] = imx8m_clk_composite("ecspi3", imx8mq_ecspi3_sels, base + 0xc180); + + clks[IMX8MQ_CLK_ECSPI1_ROOT] = imx_clk_gate4("ecspi1_root_clk", "ecspi1", base + 0x4070, 0); + clks[IMX8MQ_CLK_ECSPI2_ROOT] = imx_clk_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080, 0); + clks[IMX8MQ_CLK_ECSPI3_ROOT] = imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0); + clks[IMX8MQ_CLK_ENET1_ROOT] = imx_clk_gate4("enet1_root_clk", "enet_axi", base + 0x40a0, 0); + clks[IMX8MQ_CLK_GPT1_ROOT] = imx_clk_gate4("gpt1_root_clk", "gpt1", base + 0x4100, 0); + clks[IMX8MQ_CLK_I2C1_ROOT] = imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0); + clks[IMX8MQ_CLK_I2C2_ROOT] = imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0); + clks[IMX8MQ_CLK_I2C3_ROOT] = imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0); + clks[IMX8MQ_CLK_I2C4_ROOT] = imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0); clks[IMX8MQ_CLK_MU_ROOT] = imx_clk_gate4("mu_root_clk", "ipg_root", base + 0x4210, 0); clks[IMX8MQ_CLK_OCOTP_ROOT] = imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0); - clks[IMX8MQ_CLK_PCIE1_ROOT] = imx_clk_gate4("pcie1_root_clk", "pcie1_ctrl_div", base + 0x4250, 0); - clks[IMX8MQ_CLK_PCIE2_ROOT] = imx_clk_gate4("pcie2_root_clk", "pcie2_ctrl_div", base + 0x4640, 0); - clks[IMX8MQ_CLK_PWM1_ROOT] = imx_clk_gate4("pwm1_root_clk", "pwm1_div", base + 0x4280, 0); - clks[IMX8MQ_CLK_PWM2_ROOT] = imx_clk_gate4("pwm2_root_clk", "pwm2_div", base + 0x4290, 0); - clks[IMX8MQ_CLK_PWM3_ROOT] = imx_clk_gate4("pwm3_root_clk", "pwm3_div", base + 0x42a0, 0); - clks[IMX8MQ_CLK_PWM4_ROOT] = imx_clk_gate4("pwm4_root_clk", "pwm4_div", base + 0x42b0, 0); - clks[IMX8MQ_CLK_QSPI_ROOT] = imx_clk_gate4("qspi_root_clk", "qspi_div", base + 0x42f0, 0); - clks[IMX8MQ_CLK_RAWNAND_ROOT] = imx_clk_gate4("nand_root_clk", "nand_div", base + 0x4300, 0); - clks[IMX8MQ_CLK_NAND_USDHC_BUS_RAWNAND_CLK] = imx_clk_gate_shared("nand_usdhc_rawnand_clk", "nand_usdhc_bus_div", "nand_root_clk"); - clks[IMX8MQ_CLK_UART1_ROOT] = imx_clk_gate4("uart1_root_clk", "uart1_div", base + 0x4490, 0); - clks[IMX8MQ_CLK_UART2_ROOT] = imx_clk_gate4("uart2_root_clk", "uart2_div", base + 0x44a0, 0); - clks[IMX8MQ_CLK_UART3_ROOT] = imx_clk_gate4("uart3_root_clk", "uart3_div", base + 0x44b0, 0); - clks[IMX8MQ_CLK_UART4_ROOT] = imx_clk_gate4("uart4_root_clk", "uart4_div", base + 0x44c0, 0); - clks[IMX8MQ_CLK_USB1_CTRL_ROOT] = imx_clk_gate4("usb1_ctrl_root_clk", "usb_core_ref_div", base + 0x44d0, 0); - clks[IMX8MQ_CLK_USB2_CTRL_ROOT] = imx_clk_gate4("usb2_ctrl_root_clk", "usb_core_ref_div", base + 0x44e0, 0); - clks[IMX8MQ_CLK_USB1_PHY_ROOT] = imx_clk_gate4("usb1_phy_root_clk", "usb_phy_ref_div", base + 0x44f0, 0); - clks[IMX8MQ_CLK_USB2_PHY_ROOT] = imx_clk_gate4("usb2_phy_root_clk", "usb_phy_ref_div", base + 0x4500, 0); - clks[IMX8MQ_CLK_USDHC1_ROOT] = imx_clk_gate4("usdhc1_root_clk", "usdhc1_div", base + 0x4510, 0); - clks[IMX8MQ_CLK_USDHC2_ROOT] = imx_clk_gate4("usdhc2_root_clk", "usdhc2_div", base + 0x4520, 0); - clks[IMX8MQ_CLK_WDOG1_ROOT] = imx_clk_gate4("wdog1_root_clk", "wdog_div", base + 0x4530, 0); - clks[IMX8MQ_CLK_WDOG2_ROOT] = imx_clk_gate4("wdog2_root_clk", "wdog_div", base + 0x4540, 0); - clks[IMX8MQ_CLK_WDOG3_ROOT] = imx_clk_gate4("wdog3_root_clk", "wdog_div", base + 0x4550, 0); + clks[IMX8MQ_CLK_PCIE1_ROOT] = imx_clk_gate4("pcie1_root_clk", "pcie1_ctrl", base + 0x4250, 0); + clks[IMX8MQ_CLK_PCIE2_ROOT] = imx_clk_gate4("pcie2_root_clk", "pcie2_ctrl", base + 0x4640, 0); + clks[IMX8MQ_CLK_PWM1_ROOT] = imx_clk_gate4("pwm1_root_clk", "pwm1", base + 0x4280, 0); + clks[IMX8MQ_CLK_PWM2_ROOT] = imx_clk_gate4("pwm2_root_clk", "pwm2", base + 0x4290, 0); + clks[IMX8MQ_CLK_PWM3_ROOT] = imx_clk_gate4("pwm3_root_clk", "pwm3", base + 0x42a0, 0); + clks[IMX8MQ_CLK_PWM4_ROOT] = imx_clk_gate4("pwm4_root_clk", "pwm4", base + 0x42b0, 0); + clks[IMX8MQ_CLK_QSPI_ROOT] = imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0); + clks[IMX8MQ_CLK_RAWNAND_ROOT] = imx_clk_gate2_shared2("nand_root_clk", "nand", base + 0x4300, 0); + clks[IMX8MQ_CLK_NAND_USDHC_BUS_RAWNAND_CLK] = imx_clk_gate2_shared2("nand_usdhc_rawnand_clk", "nand_usdhc_bus", base + 0x4300, 0); + clks[IMX8MQ_CLK_SAI1_ROOT] = imx_clk_gate2_shared2("sai1_root_clk", "sai1", base + 0x4330, 0); + clks[IMX8MQ_CLK_SAI1_IPG] = imx_clk_gate2_shared2("sai1_ipg_clk", "ipg_audio_root", base + 0x4330, 0); + clks[IMX8MQ_CLK_SAI2_ROOT] = imx_clk_gate2_shared2("sai2_root_clk", "sai2", base + 0x4340, 0); + clks[IMX8MQ_CLK_SAI2_IPG] = imx_clk_gate2_shared2("sai2_ipg_clk", "ipg_root", base + 0x4340, 0); + clks[IMX8MQ_CLK_SAI3_ROOT] = imx_clk_gate2_shared2("sai3_root_clk", "sai3", base + 0x4350, 0); + clks[IMX8MQ_CLK_SAI3_IPG] = imx_clk_gate2_shared2("sai3_ipg_clk", "ipg_root", base + 0x4350, 0); + clks[IMX8MQ_CLK_SAI4_ROOT] = imx_clk_gate2_shared2("sai4_root_clk", "sai4", base + 0x4360, 0); + clks[IMX8MQ_CLK_SAI4_IPG] = imx_clk_gate2_shared2("sai4_ipg_clk", "ipg_audio_root", base + 0x4360, 0); + clks[IMX8MQ_CLK_SAI5_ROOT] = imx_clk_gate2_shared2("sai5_root_clk", "sai5", base + 0x4370, 0); + clks[IMX8MQ_CLK_SAI5_IPG] = imx_clk_gate2_shared2("sai5_ipg_clk", "ipg_audio_root", base + 0x4370, 0); + clks[IMX8MQ_CLK_SAI6_ROOT] = imx_clk_gate2_shared2("sai6_root_clk", "sai6", base + 0x4380, 0); + clks[IMX8MQ_CLK_SAI6_IPG] = imx_clk_gate2_shared2("sai6_ipg_clk", "ipg_audio_root", base + 0x4380, 0); + clks[IMX8MQ_CLK_UART1_ROOT] = imx_clk_gate4("uart1_root_clk", "uart1", base + 0x4490, 0); + clks[IMX8MQ_CLK_UART2_ROOT] = imx_clk_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0); + clks[IMX8MQ_CLK_UART3_ROOT] = imx_clk_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0); + clks[IMX8MQ_CLK_UART4_ROOT] = imx_clk_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0); + clks[IMX8MQ_CLK_USB1_CTRL_ROOT] = imx_clk_gate4("usb1_ctrl_root_clk", "usb_core_ref", base + 0x44d0, 0); + clks[IMX8MQ_CLK_USB2_CTRL_ROOT] = imx_clk_gate4("usb2_ctrl_root_clk", "usb_core_ref", base + 0x44e0, 0); + clks[IMX8MQ_CLK_USB1_PHY_ROOT] = imx_clk_gate4("usb1_phy_root_clk", "usb_phy_ref", base + 0x44f0, 0); + clks[IMX8MQ_CLK_USB2_PHY_ROOT] = imx_clk_gate4("usb2_phy_root_clk", "usb_phy_ref", base + 0x4500, 0); + clks[IMX8MQ_CLK_USDHC1_ROOT] = imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0); + clks[IMX8MQ_CLK_USDHC2_ROOT] = imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0); + clks[IMX8MQ_CLK_WDOG1_ROOT] = imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0); + clks[IMX8MQ_CLK_WDOG2_ROOT] = imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0); + clks[IMX8MQ_CLK_WDOG3_ROOT] = imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0); + clks[IMX8MQ_CLK_VPU_G1_ROOT] = imx_clk_gate2_flags("vpu_g1_root_clk", "vpu_g1", base + 0x4560, 0, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE); + clks[IMX8MQ_CLK_GPU_ROOT] = imx_clk_gate4("gpu_root_clk", "gpu_core_div", base + 0x4570, 0); + clks[IMX8MQ_CLK_VPU_G2_ROOT] = imx_clk_gate2_flags("vpu_g2_root_clk", "vpu_g2", base + 0x45a0, 0, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE); + clks[IMX8MQ_CLK_DISP_ROOT] = imx_clk_gate2_shared2("disp_root_clk", "disp_dc8000", base + 0x45d0, 0); + clks[IMX8MQ_CLK_DISP_AXI_ROOT] = imx_clk_gate2_shared2("disp_axi_root_clk", "disp_axi", base + 0x45d0, 0); + clks[IMX8MQ_CLK_DISP_APB_ROOT] = imx_clk_gate2_shared2("disp_apb_root_clk", "disp_apb", base + 0x45d0, 0); + clks[IMX8MQ_CLK_DISP_RTRM_ROOT] = imx_clk_gate2_shared2("disp_rtrm_root_clk", "disp_rtrm", base + 0x45d0, 0); clks[IMX8MQ_CLK_TMU_ROOT] = imx_clk_gate4("tmu_root_clk", "ipg_root", base + 0x4620, 0); + clks[IMX8MQ_CLK_VPU_DEC_ROOT] = imx_clk_gate2_flags("vpu_dec_root_clk", "vpu_bus", base + 0x4630, 0, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE); + clks[IMX8MQ_CLK_CSI1_ROOT] = imx_clk_gate4("csi1_root_clk", "csi1_core", base + 0x4650, 0); + clks[IMX8MQ_CLK_CSI2_ROOT] = imx_clk_gate4("csi2_root_clk", "csi2_core", base + 0x4660, 0); + clks[IMX8MQ_CLK_SDMA1_ROOT] = imx_clk_gate4("sdma1_clk", "ipg_root", base + 0x43a0, 0); + clks[IMX8MQ_CLK_SDMA2_ROOT] = imx_clk_gate4("sdma2_clk", "ipg_audio_root", base + 0x43b0, 0); clks[IMX8MQ_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc_25m", 1, 8); - clks[IMX8MQ_CLK_DRAM_ALT_ROOT] = imx_clk_fixed_factor("dram_alt_root", "dram_alt_div", 1, 4); + clks[IMX8MQ_CLK_DRAM_ALT_ROOT] = imx_clk_fixed_factor("dram_alt_root", "dram_alt", 1, 4); for (i = 0; i < IMX8MQ_CLK_END; i++) if (IS_ERR(clks[i])) @@ -587,7 +565,10 @@ static void __init imx8mq_clocks_init(struct device_node *ccm_node) clk_data.clks = clks; clk_data.clk_num = ARRAY_SIZE(clks); - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); -} + err = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + WARN_ON(err); + + return err; +} CLK_OF_DECLARE(imx8mq, "fsl,imx8mq-ccm", imx8mq_clocks_init); diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index c6ec0fc403..945671cbad 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -102,6 +102,13 @@ static inline struct clk *imx_clk_gate2_shared2(const char *name, const char *pa CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE); } +static inline struct clk *imx_clk_gate2_flags(const char *name, + const char *parent, void __iomem *reg, u8 shift, + unsigned long flags) +{ + return clk_gate2(name, parent, reg, shift, 0x3, flags); +} + static inline struct clk *imx_clk_gate2_cgr(const char *name, const char *parent, void __iomem *reg, u8 shift, u8 cgr_val) { @@ -194,4 +201,16 @@ struct clk *imx_clk_cpu(const char *name, const char *parent_name, struct clk *div, struct clk *mux, struct clk *pll, struct clk *step); +struct clk *imx8m_clk_composite_flags(const char *name, + const char **parent_names, int num_parents, void __iomem *reg, + unsigned long flags); + +#define __imx8m_clk_composite(name, parent_names, reg, flags) \ + imx8m_clk_composite_flags(name, parent_names, \ + ARRAY_SIZE(parent_names), reg, \ + flags | CLK_OPS_PARENT_ENABLE) + +#define imx8m_clk_composite(name, parent_names, reg) \ + __imx8m_clk_composite(name, parent_names, reg, 0) + #endif /* __IMX_CLK_H */ diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 337a7a2e13..7b04663d2e 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -88,4 +88,10 @@ config CLOCKSOURCE_DW_APB_TIMER help Enables the support for the dw_apb timer. +config CLOCKSOURCE_TI_DM + bool + +config CLOCKSOURCE_TI_32K + bool + endmenu diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index ab78f0700d..f8ff83d60a 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -15,3 +15,5 @@ obj-$(CONFIG_CLOCKSOURCE_ARMV8_TIMER) += armv8-timer.o obj-$(CONFIG_CLOCKSOURCE_ARM_GLOBAL_TIMER) += arm_global_timer.o obj-$(CONFIG_CLOCKSOURCE_IMX_GPT) += timer-imx-gpt.o obj-$(CONFIG_CLOCKSOURCE_DW_APB_TIMER) += dw_apb_timer.o +obj-$(CONFIG_CLOCKSOURCE_TI_DM) += timer-ti-dm.o +obj-$(CONFIG_CLOCKSOURCE_TI_32K) += timer-ti-32k.o
\ No newline at end of file diff --git a/drivers/clocksource/clps711x.c b/drivers/clocksource/clps711x.c index f6399e9300..a99147f30c 100644 --- a/drivers/clocksource/clps711x.c +++ b/drivers/clocksource/clps711x.c @@ -1,11 +1,5 @@ -/* - * Copyright (C) 2013 Alexander Shiyan <shc_work@mail.ru> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Author: Alexander Shiyan <shc_work@mail.ru> */ #include <common.h> #include <clock.h> @@ -51,13 +45,14 @@ static int clps711x_cs_probe(struct device_d *dev) return init_clock(&clps711x_cs); } +static __maybe_unused struct of_device_id clps711x_timer_dt_ids[] = { + { .compatible = "cirrus,ep7209-timer", }, + { } +}; + static struct driver_d clps711x_cs_driver = { .name = "clps711x-cs", .probe = clps711x_cs_probe, + .of_compatible = DRV_OF_COMPAT(clps711x_timer_dt_ids), }; - -static __init int clps711x_cs_init(void) -{ - return platform_driver_register(&clps711x_cs_driver); -} -coredevice_initcall(clps711x_cs_init); +coredevice_platform_driver(clps711x_cs_driver); diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c index 40895847f0..e23f1e5ec4 100644 --- a/drivers/clocksource/timer-atmel-pit.c +++ b/drivers/clocksource/timer-atmel-pit.c @@ -40,7 +40,7 @@ static __iomem void *pit_base; -uint64_t at91sam9_clocksource_read(void) +static uint64_t at91sam9_clocksource_read(void) { return pit_read(AT91_PIT_PIIR); } diff --git a/drivers/clocksource/timer-ti-32k.c b/drivers/clocksource/timer-ti-32k.c new file mode 100644 index 0000000000..f93ab5bcff --- /dev/null +++ b/drivers/clocksource/timer-ti-32k.c @@ -0,0 +1,106 @@ +/** + * @file + * @brief Provide @ref clocksource functionality for OMAP + * + * @ref clocksource provides a neat architecture. all we do is + * To loop in with Sync 32Khz clock ticking away at 32768hz on OMAP. + * Sync 32Khz clock is an always ON clock. + * + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * Nishanth Menon <x0nishan@ti.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <clock.h> +#include <init.h> +#include <io.h> +#include <mach/omap3-silicon.h> +#include <mach/omap4-silicon.h> +#include <mach/clocks.h> +#include <mach/timers.h> +#include <mach/sys_info.h> +#include <mach/syslib.h> + +/** Sync 32Khz Timer registers */ +#define S32K_CR 0x10 +#define S32K_FREQUENCY 32768 + +static void __iomem *timerbase; + +/** + * @brief Provide a simple clock read + * + * Nothing is simpler.. read direct from clock and provide it + * to the caller. + * + * @return S32K clock counter + */ +static uint64_t s32k_clocksource_read(void) +{ + return readl(timerbase + S32K_CR); +} + +/* A bit obvious isn't it? */ +static struct clocksource s32k_cs = { + .read = s32k_clocksource_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 10, +}; + +/** + * @brief Initialize the Clock + * + * There is nothing to do on OMAP as SYNC32K clock is + * always on, and we do a simple data structure initialization. + * 32K clock gives 32768 ticks a seconds + * + * @return result of @ref init_clock + */ +static int omap_32ktimer_probe(struct device_d *dev) +{ + struct resource *iores; + + /* one timer is enough */ + if (timerbase) + return 0; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + timerbase = IOMEM(iores->start); + + s32k_cs.mult = clocksource_hz2mult(S32K_FREQUENCY, s32k_cs.shift); + + return init_clock(&s32k_cs); +} + +static __maybe_unused struct of_device_id omap_32ktimer_dt_ids[] = { + { + .compatible = "ti,omap-counter32k", + }, { + /* sentinel */ + } +}; + +static struct driver_d omap_32ktimer_driver = { + .name = "omap-32ktimer", + .probe = omap_32ktimer_probe, + .of_compatible = DRV_OF_COMPAT(omap_32ktimer_dt_ids), +}; + +static int omap_32ktimer_init(void) +{ + return platform_driver_register(&omap_32ktimer_driver); +} +postcore_initcall(omap_32ktimer_init); diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c new file mode 100644 index 0000000000..f41f0bb423 --- /dev/null +++ b/drivers/clocksource/timer-ti-dm.c @@ -0,0 +1,119 @@ +/** + * @file + * @brief Support DMTimer counter + * + * FileName: arch/arm/mach-omap/dmtimer.c + */ +/* + * This File is based on arch/arm/mach-omap/s32k_clksource.c + * (C) Copyright 2008 + * Texas Instruments, <www.ti.com> + * Nishanth Menon <x0nishan@ti.com> + * + * (C) Copyright 2012 Phytec Messtechnik GmbH + * Author: Teresa Gámez <t.gamez@phytec.de> + * (C) Copyright 2015 Phytec Messtechnik GmbH + * Author: Daniel Schultz <d.schultz@phytec.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <clock.h> +#include <init.h> +#include <io.h> +#include <mach/am33xx-silicon.h> +#include <mach/am33xx-clock.h> + +#include <stdio.h> + +#define CLK_RC32K 32768 + +#define TIDR 0x0 +#define TIOCP_CFG 0x10 +#define IRQ_EOI 0x20 +#define IRQSTATUS_RAW 0x24 +#define IRQSTATUS 0x28 +#define IRQSTATUS_SET 0x2c +#define IRQSTATUS_CLR 0x30 +#define IRQWAKEEN 0x34 +#define TCLR 0x38 +#define TCRR 0x3C +#define TLDR 0x40 +#define TTGR 0x44 +#define TWPS 0x48 +#define TMAR 0x4C +#define TCAR1 0x50 +#define TSICR 0x54 +#define TCAR2 0x58 + +static void *base; + +/** + * @brief Provide a simple counter read + * + * @return DMTimer counter + */ +static uint64_t dmtimer_read(void) +{ + return readl(base + TCRR); +} + +static struct clocksource dmtimer_cs = { + .read = dmtimer_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 10, +}; + +static int omap_dmtimer_probe(struct device_d *dev) +{ + struct resource *iores; + u64 clk_speed; + + /* one timer is enough */ + if (base) + return 0; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + base = IOMEM(iores->start); + + clk_speed = am33xx_get_osc_clock(); + clk_speed *= 1000; + dmtimer_cs.mult = clocksource_hz2mult(clk_speed, dmtimer_cs.shift); + + /* Enable counter */ + writel(0x3, base + TCLR); + + return init_clock(&dmtimer_cs); +} + +static __maybe_unused struct of_device_id omap_dmtimer_dt_ids[] = { + { + .compatible = "ti,am335x-timer", + }, { + /* sentinel */ + } +}; + +static struct driver_d omap_dmtimer_driver = { + .name = "omap-dmtimer", + .probe = omap_dmtimer_probe, + .of_compatible = DRV_OF_COMPAT(omap_dmtimer_dt_ids), +}; + +static int omap_dmtimer_init(void) +{ + return platform_driver_register(&omap_dmtimer_driver); +} +postcore_initcall(omap_dmtimer_init); diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 9f02c17c26..d1687e3774 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -1,7 +1,6 @@ menuconfig CRYPTO_HW bool "Hardware crypto devices" - help if CRYPTO_HW diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c index c1ec6ab685..44f40c36e4 100644 --- a/drivers/gpio/gpio-clps711x.c +++ b/drivers/gpio/gpio-clps711x.c @@ -1,11 +1,5 @@ -/* - * Copyright (C) 2013-2014 Alexander Shiyan <shc_work@mail.ru> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Author: Alexander Shiyan <shc_work@mail.ru> */ #include <init.h> #include <common.h> @@ -71,7 +65,7 @@ out_err: } static struct of_device_id __maybe_unused clps711x_gpio_dt_ids[] = { - { .compatible = "cirrus,clps711x-gpio", }, + { .compatible = "cirrus,ep7209-gpio", }, { /* sentinel */ } }; @@ -80,9 +74,4 @@ static struct driver_d clps711x_gpio_driver = { .probe = clps711x_gpio_probe, .of_compatible = DRV_OF_COMPAT(clps711x_gpio_dt_ids), }; - -static __init int clps711x_gpio_register(void) -{ - return platform_driver_register(&clps711x_gpio_driver); -} -coredevice_initcall(clps711x_gpio_register); +coredevice_platform_driver(clps711x_gpio_driver); diff --git a/drivers/led/core.c b/drivers/led/core.c index a388e6b365..431966d067 100644 --- a/drivers/led/core.c +++ b/drivers/led/core.c @@ -127,12 +127,13 @@ static void led_blink_func(struct poller_struct *poller) struct led *led; list_for_each_entry(led, &leds, list) { + const uint64_t now = get_time_ns(); int on; if (!led->blink && !led->flash) continue; - if (led->blink_next_event > get_time_ns()) { + if (led->blink_next_event > now) { continue; } @@ -140,7 +141,7 @@ static void led_blink_func(struct poller_struct *poller) if (on) on = led->max_value; - led->blink_next_event = get_time_ns() + + led->blink_next_event = now + (led->blink_states[led->blink_next_state] * MSECOND); led->blink_next_state = (led->blink_next_state + 1) % led->blink_nr_states; @@ -176,7 +177,7 @@ int led_blink_pattern(struct led *led, const unsigned int *pattern, pattern_len * sizeof(*led->blink_states)); led->blink_nr_states = pattern_len; led->blink_next_state = 0; - led->blink_next_event = get_time_ns(); + led->blink_next_event = 0; led->blink = 1; led->flash = 0; @@ -187,7 +188,7 @@ int led_blink(struct led *led, unsigned int on_ms, unsigned int off_ms) { unsigned int pattern[] = {on_ms, off_ms}; - return led_blink_pattern(led, pattern, 2); + return led_blink_pattern(led, ARRAY_AND_SIZE(pattern)); } int led_flash(struct led *led, unsigned int duration_ms) @@ -195,7 +196,7 @@ int led_flash(struct led *led, unsigned int duration_ms) unsigned int pattern[] = {duration_ms, 0}; int ret; - ret = led_blink_pattern(led, pattern, 2); + ret = led_blink_pattern(led, ARRAY_AND_SIZE(pattern)); if (ret) return ret; diff --git a/drivers/mci/dw_mmc.c b/drivers/mci/dw_mmc.c index e4c550c3ed..f035317ef2 100644 --- a/drivers/mci/dw_mmc.c +++ b/drivers/mci/dw_mmc.c @@ -602,9 +602,6 @@ static int dw_mmc_probe(struct device_d *dev) host->mci.host_caps &= ~MMC_CAP_BIT_DATA_MASK; host->mci.host_caps |= pdata->bus_width_caps; } else if (dev->device_node) { - const char *alias = of_alias_get(dev->device_node); - if (alias) - host->mci.devname = xstrdup(alias); of_property_read_u32(dev->device_node, "dw-mshc-ciu-div", &host->ciu_div); } diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index 7f2285635b..09df7945cb 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -668,10 +668,6 @@ static int fsl_esdhc_probe(struct device_d *dev) mci->host_caps = pdata->caps; if (pdata->devname) mci->devname = pdata->devname; - } else if (dev->device_node) { - const char *alias = of_alias_get(dev->device_node); - if (alias) - mci->devname = xstrdup(alias); } if (caps & ESDHC_HOSTCAPBLT_HSS) diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index c8d1d5e164..67257bcd18 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -1628,7 +1628,12 @@ static int mci_register_partition(struct mci_part *part) if (np) { of_parse_partitions(&part->blk.cdev, np); - of_partitions_register_fixup(&part->blk.cdev); + + /* bootN-partitions binding barebox-specific, so don't register + * for fixup into kernel device tree + */ + if (part->area_type != MMC_BLK_DATA_AREA_BOOT) + of_partitions_register_fixup(&part->blk.cdev); } return 0; @@ -1650,13 +1655,11 @@ static int mci_card_probe(struct mci *mci) return -ENODEV; } - if (!IS_ERR(host->supply)) { - ret = regulator_enable(host->supply); - if (ret) { - dev_err(&mci->dev, "failed to enable regulator: %s\n", - strerror(-ret)); - return ret; - } + ret = regulator_enable(host->supply); + if (ret) { + dev_err(&mci->dev, "failed to enable regulator: %s\n", + strerror(-ret)); + return ret; } /* start with a host interface reset */ @@ -1728,8 +1731,7 @@ on_error: if (rc != 0) { host->clock = 0; /* disable the MCI clock */ mci_set_ios(mci); - if (!IS_ERR(host->supply)) - regulator_disable(host->supply); + regulator_disable(host->supply); } return rc; @@ -1816,8 +1818,10 @@ int mci_register(struct mci_host *host) mci->dev.detect = mci_detect; host->supply = regulator_get(host->hw_dev, "vmmc"); - if (IS_ERR(host->supply)) + if (IS_ERR(host->supply)) { dev_err(&mci->dev, "Failed to get 'vmmc' regulator.\n"); + host->supply = NULL; + } ret = register_device(&mci->dev); if (ret) @@ -1858,6 +1862,7 @@ void mci_of_parse_node(struct mci_host *host, { u32 bus_width; u32 dsr_val; + const char *alias; if (!IS_ENABLED(CONFIG_OFDEVICE)) return; @@ -1865,6 +1870,10 @@ void mci_of_parse_node(struct mci_host *host, if (!host->hw_dev || !np) return; + alias = of_alias_get(np); + if (alias) + host->devname = xstrdup(alias); + /* "bus-width" is translated to MMC_CAP_*_BIT_DATA flags */ if (of_property_read_u32(np, "bus-width", &bus_width) < 0) { /* If bus-width is missing we get the driver's default, which diff --git a/drivers/mci/mxs.c b/drivers/mci/mxs.c index 446da8ad53..afd6a56397 100644 --- a/drivers/mci/mxs.c +++ b/drivers/mci/mxs.c @@ -574,12 +574,6 @@ static int mxs_mci_probe(struct device_d *hw_dev) /* fixed to 3.3 V */ host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; - if (hw_dev->device_node) { - const char *alias = of_alias_get(hw_dev->device_node); - if (alias) - host->devname = xstrdup(alias); - } - mci_of_parse(host); } diff --git a/drivers/mci/omap_hsmmc.c b/drivers/mci/omap_hsmmc.c index cbc69e4083..4e809bae4f 100644 --- a/drivers/mci/omap_hsmmc.c +++ b/drivers/mci/omap_hsmmc.c @@ -316,13 +316,16 @@ static int mmc_read_data(struct omap_hsmmc *hsmmc, char *buf, unsigned int size) do { mmc_stat = readl(&mmc_base->stat); if (is_timeout(start, SECOND)) { - dev_dbg(hsmmc->dev, "timedout waiting for status!\n"); + dev_err(hsmmc->dev, "timedout waiting for status!\n"); return -ETIMEDOUT; } } while (mmc_stat == 0); - if ((mmc_stat & ERRI_MASK) != 0) - return 1; + if ((mmc_stat & ERRI_MASK) != 0) { + dev_err(hsmmc->dev, "Error while reading data. status: 0x%08x\n", + mmc_stat); + return -EIO; + } if (mmc_stat & BRR_MASK) { unsigned int k; @@ -349,7 +352,6 @@ static int mmc_read_data(struct omap_hsmmc *hsmmc, char *buf, unsigned int size) return 0; } -#ifdef CONFIG_MCI_WRITE static int mmc_write_data(struct omap_hsmmc *hsmmc, const char *buf, unsigned int size) { struct hsmmc *mmc_base = hsmmc->base; @@ -373,8 +375,11 @@ static int mmc_write_data(struct omap_hsmmc *hsmmc, const char *buf, unsigned in } } while (mmc_stat == 0); - if ((mmc_stat & ERRI_MASK) != 0) - return 1; + if ((mmc_stat & ERRI_MASK) != 0) { + dev_err(hsmmc->dev, "Error while reading data. status: 0x%08x\n", + mmc_stat); + return -EIO; + } if (mmc_stat & BWR_MASK) { unsigned int k; @@ -400,7 +405,6 @@ static int mmc_write_data(struct omap_hsmmc *hsmmc, const char *buf, unsigned in } return 0; } -#endif static int mmc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) @@ -511,13 +515,18 @@ static int mmc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, } } - if (data && (data->flags & MMC_DATA_READ)) - mmc_read_data(hsmmc, data->dest, data->blocksize * data->blocks); -#ifdef CONFIG_MCI_WRITE - else if (data && (data->flags & MMC_DATA_WRITE)) - mmc_write_data(hsmmc, data->src, data->blocksize * data->blocks); -#endif - return 0; + if (!data) + return 0; + + if (data->flags & MMC_DATA_READ) + return mmc_read_data(hsmmc, data->dest, + data->blocksize * data->blocks); + + if (IS_ENABLED(CONFIG_MCI_WRITE)) + return mmc_write_data(hsmmc, data->src, + data->blocksize * data->blocks); + + return -ENOSYS; } static void mmc_set_ios(struct mci_host *mci, struct mci_ios *ios) @@ -625,12 +634,6 @@ static int omap_mmc_probe(struct device_d *dev) hsmmc->mci.devname = pdata->devname; } - if (dev->device_node) { - const char *alias = of_alias_get(dev->device_node); - if (alias) - hsmmc->mci.devname = xstrdup(alias); - } - mci_of_parse(&hsmmc->mci); dev->priv = hsmmc; diff --git a/drivers/mci/tegra-sdmmc.c b/drivers/mci/tegra-sdmmc.c index e465d891a2..4c47918076 100644 --- a/drivers/mci/tegra-sdmmc.c +++ b/drivers/mci/tegra-sdmmc.c @@ -411,10 +411,7 @@ static int tegra_sdmmc_detect(struct device_d *dev) static void tegra_sdmmc_parse_dt(struct tegra_sdmmc_host *host) { struct device_node *np = host->mci.hw_dev->device_node; - const char *alias = of_alias_get(np); - if (alias) - host->mci.devname = xstrdup(alias); host->gpio_cd = of_get_named_gpio(np, "cd-gpios", 0); host->gpio_pwr = of_get_named_gpio(np, "power-gpios", 0); mci_of_parse(&host->mci); diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c index 469ce4cc0d..1448c4143f 100644 --- a/drivers/mfd/rave-sp.c +++ b/drivers/mfd/rave-sp.c @@ -57,6 +57,8 @@ #define RAVE_SP_TX_BUFFER_SIZE \ (RAVE_SP_STX_ETX_SIZE + 2 * RAVE_SP_RX_BUFFER_SIZE) +#define RAVE_SP_IPADDR_INVALID U32_MAX + /** * enum rave_sp_deframer_state - Possible state for de-framer * @@ -183,6 +185,7 @@ struct rave_sp_variant { * @part_number_bootloader: Bootloader version */ struct rave_sp { + struct device_d dev; struct serdev_device *serdev; struct rave_sp_deframer deframer; unsigned int ackid; @@ -192,6 +195,9 @@ struct rave_sp { const char *part_number_firmware; const char *part_number_bootloader; + + IPaddr_t ipaddr; + IPaddr_t netmask; }; static bool rave_sp_id_is_event(u8 code) @@ -314,7 +320,6 @@ int rave_sp_exec(struct rave_sp *sp, unsigned char *data = __data; int command, ret = 0; u8 ackid; - uint64_t start = get_time_ns(); command = sp->variant->cmd.translate(data[0]); if (command < 0) @@ -334,12 +339,9 @@ int rave_sp_exec(struct rave_sp *sp, * is_timeout will implicitly poll serdev via poller * infrastructure */ - while (!is_timeout(start, SECOND) && !reply.received) - ; - - if (!reply.received) { + ret = wait_on_timeout(SECOND, reply.received); + if (ret) { dev_err(dev, "Command timeout\n"); - ret = -ETIMEDOUT; sp->reply = NULL; } @@ -718,6 +720,65 @@ static const struct of_device_id __maybe_unused rave_sp_dt_ids[] = { { /* sentinel */ } }; +static int rave_sp_req_ip_addr(struct param_d *p, void *context) +{ + struct rave_sp *sp = context; + u8 cmd[] = { + [0] = RAVE_SP_CMD_REQ_IP_ADDR, + [1] = 0, + [2] = 0, /* FIXME: Support for RJU? */ + [3] = 0, /* Add support for IPs other than "self" */ + }; + struct { + __le32 ipaddr; + __le32 netmask; + } __packed rsp; + int ret; + + /* + * We only query RAVE SP device for IP/Netmask once, after + * that we just "serve" cached data. + */ + if (sp->ipaddr != RAVE_SP_IPADDR_INVALID) + return 0; + + ret = rave_sp_exec(sp, &cmd, sizeof(cmd), &rsp, sizeof(rsp)); + if (ret < 0) + return ret; + + sp->ipaddr = le32_to_cpu(rsp.ipaddr); + sp->netmask = le32_to_cpu(rsp.netmask); + + return 0; +} + +static int rave_sp_add_params(struct rave_sp *sp) +{ + struct device_d *dev = &sp->dev; + struct param_d *p; + int ret; + + dev->parent = sp->serdev->dev; + dev_set_name(dev, "sp"); + dev->id = DEVICE_ID_SINGLE; + + ret = register_device(dev); + if (ret) + return ret; + + p = dev_add_param_ip(dev, "ipaddr", NULL, rave_sp_req_ip_addr, + &sp->ipaddr, sp); + if (IS_ERR(p)) + return PTR_ERR(p); + + p = dev_add_param_ip(dev, "netmask", NULL, rave_sp_req_ip_addr, + &sp->netmask, sp); + if (IS_ERR(p)) + return PTR_ERR(p); + + return 0; +} + static int rave_sp_probe(struct device_d *dev) { struct serdev_device *serdev = to_serdev_device(dev->parent); @@ -733,6 +794,7 @@ static int rave_sp_probe(struct device_d *dev) sp = xzalloc(sizeof(*sp)); sp->serdev = serdev; + sp->ipaddr = RAVE_SP_IPADDR_INVALID; dev->priv = sp; serdev->dev = dev; serdev->receive_buf = rave_sp_receive_buf; @@ -773,6 +835,12 @@ static int rave_sp_probe(struct device_d *dev) dev_info(dev, "Firmware version: %s", sp->part_number_firmware); dev_info(dev, "Bootloader version: %s", sp->part_number_bootloader); + ret = rave_sp_add_params(sp); + if (ret) { + dev_err(dev, "Failed to add parameters to RAVE SP\n"); + return ret; + } + return of_platform_populate(dev->device_node, NULL, dev); } diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index 957d9a7267..30ed65f737 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c @@ -176,7 +176,7 @@ static int syscon_probe(struct device_d *dev) syscon->base = IOMEM(res->start); dev->priv = syscon; - dev_dbg(dev, "map 0x%x-0x%x registered\n", res->start, res->end); + dev_dbg(dev, "map %pa-%pa registered\n", &res->start, &res->end); return 0; } diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c index d3cbe502fa..f44c6cfc69 100644 --- a/drivers/mtd/core.c +++ b/drivers/mtd/core.c @@ -141,15 +141,28 @@ static struct mtd_erase_region_info *mtd_find_erase_region(struct mtd_info *mtd, return NULL; } +static loff_t __mtd_erase_round(loff_t x, uint32_t esize, int up) +{ + uint64_t dividend = x; + uint32_t mod = do_div(dividend, esize); + if (mod == 0) + return x; + if (up) + x += esize; + return x - mod; +} +#define mtd_erase_round_up(x, esize) __mtd_erase_round(x, esize, 1) +#define mtd_erase_round_down(x, esize) __mtd_erase_round(x, esize, 0) + static int mtd_erase_align(struct mtd_info *mtd, loff_t *count, loff_t *offset) { struct mtd_erase_region_info *e; loff_t ofs; if (mtd->numeraseregions == 0) { - ofs = *offset & ~(loff_t)(mtd->erasesize - 1); - *count += (*offset - ofs); - *count = ALIGN(*count, mtd->erasesize); + ofs = mtd_erase_round_down(*offset, mtd->erasesize); + *count += *offset - ofs; + *count = mtd_erase_round_up(*count, mtd->erasesize); *offset = ofs; return 0; } @@ -158,14 +171,14 @@ static int mtd_erase_align(struct mtd_info *mtd, loff_t *count, loff_t *offset) if (!e) return -EINVAL; - ofs = *offset & ~(e->erasesize - 1); - *count += (*offset - ofs); + ofs = mtd_erase_round_down(*offset, e->erasesize); + *count += *offset - ofs; e = mtd_find_erase_region(mtd, *offset + *count); if (!e) return -EINVAL; - *count = ALIGN(*count, e->erasesize); + *count = mtd_erase_round_up(*count, e->erasesize); *offset = ofs; return 0; diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 4c1725d096..b4d4e79d91 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -1297,6 +1297,7 @@ static int atmel_hw_nand_init_params(struct device_d *dev, nand_chip->ecc.hwctl = atmel_nand_hwctl; nand_chip->ecc.read_page = atmel_nand_read_page; nand_chip->ecc.bytes = 4; + nand_chip->ecc.strength = 1; return 0; } @@ -1387,6 +1388,8 @@ static int __init atmel_nand_probe(struct device_d *dev) } nand_chip->ecc.mode = pdata->ecc_mode; + nand_chip->ecc.strength = pdata->ecc_strength ? : 1; + nand_chip->ecc.size = 1 << pdata->ecc_size_shift ? : 512; if (IS_ENABLED(CONFIG_NAND_ECC_HW) && pdata->ecc_mode == NAND_ECC_HW) { diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 128802fa5c..8ae6f34468 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -36,13 +36,13 @@ #include <clock.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> -#include <linux/err.h> +#include <linux/mtd/nand_bch.h> #include <linux/mtd/nand_ecc.h> +#include <linux/err.h> #include <asm/byteorder.h> #include <io.h> #include <malloc.h> #include <module.h> -#include <linux/mtd/nand_bch.h> /* Define default oob placement schemes for large and small page devices */ static struct nand_ecclayout nand_oob_8 = { @@ -326,28 +326,70 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) } /** - * nand_default_block_markbad - [DEFAULT] mark a block bad + * nand_default_block_markbad - [DEFAULT] mark a block bad via bad block marker * @mtd: MTD device structure * @ofs: offset from device start * * This is the default implementation, which can be overridden by a hardware - * specific driver. We try operations in the following order, according to our - * bbt_options (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH): + * specific driver. It provides the details for writing a bad block marker to a + * block. + */ +static __maybe_unused int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + struct nand_chip *chip = mtd->priv; + struct mtd_oob_ops ops; + uint8_t buf[2] = { 0, 0 }; + int ret = 0, res, i = 0; + + ops.datbuf = NULL; + ops.oobbuf = buf; + ops.ooboffs = chip->badblockpos; + if (chip->options & NAND_BUSWIDTH_16) { + ops.ooboffs &= ~0x01; + ops.len = ops.ooblen = 2; + } else { + ops.len = ops.ooblen = 1; + } + ops.mode = MTD_OPS_PLACE_OOB; + + /* Write to first/last page(s) if necessary */ + if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) + ofs += mtd->erasesize - mtd->writesize; + do { + res = nand_do_write_oob(mtd, ofs, &ops); + if (!ret) + ret = res; + + i++; + ofs += mtd->writesize; + } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2); + + return ret; +} + +/** + * nand_block_markbad_lowlevel - mark a block bad + * @mtd: MTD device structure + * @ofs: offset from device start + * + * This function performs the generic NAND bad block marking steps (i.e., bad + * block table(s) and/or marker(s)). We only allow the hardware driver to + * specify how to write bad block markers to OOB (chip->block_markbad). + * + * We try operations in the following order: * (1) erase the affected block, to allow OOB marker to be written cleanly - * (2) update in-memory BBT - * (3) write bad block marker to OOB area of affected block - * (4) update flash-based BBT - * Note that we retain the first error encountered in (3) or (4), finish the + * (2) write bad block marker to OOB area of affected block (unless flag + * NAND_BBT_NO_OOB_BBM is present) + * (3) update the BBT + * Note that we retain the first error encountered in (2) or (3), finish the * procedures, and dump the error in the end. -*/ -static __maybe_unused int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) + */ +static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) { struct nand_chip *chip = mtd->priv; - uint8_t buf[2] = { 0, 0 }; - int block, res, ret = 0, i = 0; - int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM); + int res, ret = 0; - if (write_oob) { + if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) { struct erase_info einfo; /* Attempt erase before marking OOB */ @@ -356,50 +398,16 @@ static __maybe_unused int nand_default_block_markbad(struct mtd_info *mtd, loff einfo.addr = ofs; einfo.len = 1 << chip->phys_erase_shift; nand_erase_nand(mtd, &einfo, 0); - } - - /* Get block number */ - block = (int)(ofs >> chip->bbt_erase_shift); - /* Mark block bad in memory-based BBT */ - if (chip->bbt) - chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); - - /* Write bad block marker to OOB */ - if (write_oob) { - struct mtd_oob_ops ops; - loff_t wr_ofs = ofs; + /* Write bad block marker to OOB */ nand_get_device(mtd, FL_WRITING); - - ops.datbuf = NULL; - ops.oobbuf = buf; - ops.ooboffs = chip->badblockpos; - if (chip->options & NAND_BUSWIDTH_16) { - ops.ooboffs &= ~0x01; - ops.len = ops.ooblen = 2; - } else { - ops.len = ops.ooblen = 1; - } - ops.mode = MTD_OPS_PLACE_OOB; - - /* Write to first/last page(s) if necessary */ - if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) - wr_ofs += mtd->erasesize - mtd->writesize; - do { - res = nand_do_write_oob(mtd, wr_ofs, &ops); - if (!ret) - ret = res; - - i++; - wr_ofs += mtd->writesize; - } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2); - + ret = chip->block_markbad(mtd, ofs); nand_release_device(mtd); } - /* Update flash-based bad block table */ - if (IS_ENABLED(CONFIG_NAND_BBT) && chip->bbt_options & NAND_BBT_USE_FLASH) { - res = nand_update_bbt(mtd, ofs); + /* Mark block bad in BBT */ + if (chip->bbt) { + res = nand_markbad_bbt(mtd, ofs); if (!ret) ret = res; } @@ -411,6 +419,57 @@ static __maybe_unused int nand_default_block_markbad(struct mtd_info *mtd, loff } /** + * nand_block_markgood_lowlevel - mark a block good + * @mtd: MTD device structure + * @ofs: offset from device start + * + * We try operations in the following order: + * (1) erase the affected block + * (2) check bad block marker + * (3) update the BBT + */ +static int nand_block_markgood_lowlevel(struct mtd_info *mtd, loff_t ofs) +{ + struct nand_chip *chip = mtd->priv; + bool allow_erasebad; + int ret; + + if (!(chip->bbt_options & NAND_BBT_NO_OOB_BBM)) { + struct erase_info einfo; + + /* Attempt erase possibly bad block */ + allow_erasebad = mtd->allow_erasebad; + mtd->allow_erasebad = true; + memset(&einfo, 0, sizeof(einfo)); + einfo.mtd = mtd; + einfo.addr = ofs; + einfo.len = 1 << chip->phys_erase_shift; + nand_erase_nand(mtd, &einfo, 0); + mtd->allow_erasebad = allow_erasebad; + + /* + * Verify erase succeded. We need to select chip again, + * as nand_erase_nand deselected it. + */ + ret = chip->block_bad(mtd, ofs, 1); + if (ret) + return ret; + } + + /* Mark block good in BBT */ + if (chip->bbt) { + ret = nand_markgood_bbt(mtd, ofs); + if (ret) + return ret; + } + + if (mtd->ecc_stats.badblocks > 0) + mtd->ecc_stats.badblocks--; + + return 0; +} + +/** * nand_check_wp - [GENERIC] check if the chip is write protected * @mtd: MTD device structure * @@ -453,38 +512,6 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, return chip->block_bad(mtd, ofs, getchip); } -/** - * nand_default_block_markgood - [DEFAULT] mark a block good - * @mtd: MTD device structure - * @ofs: offset from device start - * - * This is the default implementation, which can be overridden by - * a hardware specific driver. -*/ -static __maybe_unused int nand_default_block_markgood(struct mtd_info *mtd, loff_t ofs) -{ - struct nand_chip *chip = mtd->priv; - int block, res, ret = 0; - - /* Get block number */ - block = (int)(ofs >> chip->bbt_erase_shift); - /* Mark block good in memory-based BBT */ - if (chip->bbt) - chip->bbt[block >> 2] &= ~(0x01 << ((block & 0x03) << 1)); - - /* Update flash-based bad block table */ - if (IS_ENABLED(CONFIG_NAND_BBT) && chip->bbt_options & NAND_BBT_USE_FLASH) { - res = nand_update_bbt(mtd, ofs); - if (!ret) - ret = res; - } - - if (!ret) - mtd->ecc_stats.badblocks++; - - return ret; -} - /* Wait for the ready pin, after a command. The timeout is caught later. */ void nand_wait_ready(struct mtd_info *mtd) { @@ -2804,7 +2831,6 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs) */ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) { - struct nand_chip *chip = mtd->priv; int ret; if (!IS_ENABLED(CONFIG_MTD_WRITE)) @@ -2818,17 +2844,16 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) return ret; } - return chip->block_markbad(mtd, ofs); + return nand_block_markbad_lowlevel(mtd, ofs); } /** - * nand_block_markgood - [MTD Interface] Mark block at the given offset as bad + * nand_block_markgood - [MTD Interface] Mark block at the given offset as good * @mtd: MTD device structure * @ofs: offset relative to mtd start */ static int nand_block_markgood(struct mtd_info *mtd, loff_t ofs) { - struct nand_chip *chip = mtd->priv; int ret; if (!IS_ENABLED(CONFIG_MTD_WRITE)) @@ -2842,7 +2867,7 @@ static int nand_block_markgood(struct mtd_info *mtd, loff_t ofs) if (!ret) return 0; - return chip->block_markgood(mtd, ofs); + return nand_block_markgood_lowlevel(mtd, ofs); } /** @@ -2926,17 +2951,11 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) #ifdef CONFIG_MTD_WRITE if (!chip->block_markbad) chip->block_markbad = nand_default_block_markbad; - if (!chip->block_markgood) - chip->block_markgood = nand_default_block_markgood; if (!chip->write_buf) chip->write_buf = busw ? nand_write_buf16 : nand_write_buf; #endif if (!chip->read_buf) chip->read_buf = busw ? nand_read_buf16 : nand_read_buf; -#ifdef CONFIG_NAND_BBT - if (!chip->scan_bbt) - chip->scan_bbt = nand_default_bbt; -#endif if (!chip->controller) { chip->controller = &chip->hwcontrol; } @@ -3100,6 +3119,16 @@ static int nand_id_len(u8 *id_data, int arrlen) return arrlen; } +/* Extract the bits of per cell from the 3rd byte of the extended ID */ +static int nand_get_bits_per_cell(u8 cellinfo) +{ + int bits; + + bits = cellinfo & NAND_CI_CELLTYPE_MSK; + bits >>= NAND_CI_CELLTYPE_SHIFT; + return bits + 1; +} + /* * Many new NAND share similar device ID codes, which represent the size of the * chip. The rest of the parameters must be decoded according to generic or @@ -3110,7 +3139,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, { int extid, id_len; /* The 3rd id byte holds MLC / multichip data */ - chip->cellinfo = id_data[2]; + chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]); /* The 4th id byte is the important one */ extid = id_data[3]; @@ -3126,8 +3155,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, * ID to decide what to do. */ if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG && - (chip->cellinfo & NAND_CI_CELLTYPE_MSK) && - id_data[5] != 0x00) { + !nand_is_slc(chip) && id_data[5] != 0x00) { /* Calc pagesize */ mtd->writesize = 2048 << (extid & 0x03); extid >>= 2; @@ -3159,7 +3187,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, (((extid >> 1) & 0x04) | (extid & 0x03)); *busw = 0; } else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX && - (chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { + !nand_is_slc(chip)) { unsigned int tmp; /* Calc pagesize */ @@ -3212,6 +3240,20 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, extid >>= 2; /* Get buswidth information */ *busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; + /* + * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per + * 512B page. For Toshiba SLC, we decode the 5th/6th byte as + * follows: + * - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm, + * 110b -> 24nm + * - ID byte 5, bit[7]: 1 -> BENAND, 0 -> raw SLC + */ + if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA && + nand_is_slc(chip) && + (id_data[5] & 0x7) == 0x6 /* 24nm */ && + !(id_data[4] & 0x80) /* !BENAND */) { + mtd->oobsize = 32 * mtd->writesize >> 9; + } } } @@ -3231,6 +3273,9 @@ static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip, mtd->oobsize = mtd->writesize / 32; *busw = type->options & NAND_BUSWIDTH_16; + /* All legacy ID NAND are small-page, SLC */ + chip->bits_per_cell = 1; + /* * Check for Spansion/AMD ID + repeating 5th, 6th byte since * some Spansion chips have erasesize that conflicts with size @@ -3267,11 +3312,11 @@ static void nand_decode_bbm_options(struct mtd_info *mtd, * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba, * AMD/Spansion, and Macronix. All others scan only the first page. */ - if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && + if (!nand_is_slc(chip) && (maf_id == NAND_MFR_SAMSUNG || maf_id == NAND_MFR_HYNIX)) chip->bbt_options |= NAND_BBT_SCANLASTPAGE; - else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && + else if ((nand_is_slc(chip) && (maf_id == NAND_MFR_SAMSUNG || maf_id == NAND_MFR_HYNIX || maf_id == NAND_MFR_TOSHIBA || @@ -3295,7 +3340,7 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, mtd->erasesize = type->erasesize; mtd->oobsize = type->oobsize; - chip->cellinfo = id_data[2]; + chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]); chip->chipsize = (uint64_t)type->chipsize << 20; chip->options |= type->options; @@ -3675,25 +3720,22 @@ int nand_scan_tail(struct mtd_info *mtd) chip->ecc.read_oob = nand_read_oob_std; chip->ecc.write_oob = nand_write_oob_std; /* - * Board driver should supply ecc.size and ecc.bytes values to - * select how many bits are correctable; see nand_bch_init() - * for details. Otherwise, default to 4 bits for large page - * devices. + * Board driver should supply ecc.size and ecc.strength values + * to select how many bits are correctable. Otherwise, default + * to 4 bits for large page devices. */ if (!chip->ecc.size && (mtd->oobsize >= 64)) { chip->ecc.size = 512; - chip->ecc.bytes = 7; + chip->ecc.strength = 4; } - chip->ecc.priv = nand_bch_init(mtd, - chip->ecc.size, - chip->ecc.bytes, - &chip->ecc.layout); + + /* See nand_bch_init() for details. */ + chip->ecc.bytes = 0; + chip->ecc.priv = nand_bch_init(mtd); if (!chip->ecc.priv) { pr_warn("BCH ECC initialization failed!\n"); BUG(); } - chip->ecc.strength = - chip->ecc.bytes * 8 / fls(8 * chip->ecc.size); break; #endif #ifdef CONFIG_NAND_ECC_NONE @@ -3744,8 +3786,7 @@ int nand_scan_tail(struct mtd_info *mtd) chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */ - if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && - !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { + if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) { switch (chip->ecc.steps) { case 2: mtd->subpage_sft = 1; @@ -3805,7 +3846,7 @@ int nand_scan_tail(struct mtd_info *mtd) return 0; /* Build bad block table */ - return chip->scan_bbt(mtd); + return nand_create_bbt(mtd); } EXPORT_SYMBOL(nand_scan_tail); diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 94a2e57834..90c10862c5 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -77,6 +77,8 @@ #define BBT_ENTRY_MASK 0x03 #define BBT_ENTRY_SHIFT 2 +static int nand_update_bbt(struct mtd_info *mtd, loff_t offs); + static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block) { uint8_t entry = chip->bbt[block >> BBT_ENTRY_SHIFT]; @@ -87,8 +89,14 @@ static inline uint8_t bbt_get_entry(struct nand_chip *chip, int block) static inline void bbt_mark_entry(struct nand_chip *chip, int block, uint8_t mark) { - uint8_t msk = (mark & BBT_ENTRY_MASK) << ((block & BBT_ENTRY_MASK) * 2); - chip->bbt[block >> BBT_ENTRY_SHIFT] |= msk; + /* + * Unlike original Linux implementation, Barebox needs also + * mark block as good again, so mask entry comletely. + */ + int index = block >> BBT_ENTRY_SHIFT; + int shift = (block & BBT_ENTRY_MASK) * 2; + chip->bbt[index] &= ~(BBT_ENTRY_MASK << shift); + chip->bbt[index] |= (mark & BBT_ENTRY_MASK) << shift; } static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td) @@ -106,33 +114,17 @@ static int check_pattern_no_oob(uint8_t *buf, struct nand_bbt_descr *td) * @td: search pattern descriptor * * Check for a pattern at the given place. Used to search bad block tables and - * good / bad block identifiers. If the SCAN_EMPTY option is set then check, if - * all bytes except the pattern area contain 0xff. + * good / bad block identifiers. */ static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) { - int end = 0; - uint8_t *p = buf; - if (td->options & NAND_BBT_NO_OOB) return check_pattern_no_oob(buf, td); - end = paglen + td->offs; - if (td->options & NAND_BBT_SCANEMPTY) - if (memchr_inv(p, 0xff, end)) - return -1; - p += end; - /* Compare the pattern */ - if (memcmp(p, td->pattern, td->len)) + if (memcmp(buf + paglen + td->offs, td->pattern, td->len)) return -1; - if (td->options & NAND_BBT_SCANEMPTY) { - p += td->len; - end += td->len; - if (memchr_inv(p, 0xff, len - end)) - return -1; - } return 0; } @@ -179,7 +171,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td) * @page: the starting page * @num: the number of bbt descriptors to read * @td: the bbt describtion table - * @offs: offset in the memory table + * @offs: block number offset in the table * * Read the bad block table starting from page. */ @@ -229,29 +221,28 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num, /* Analyse data */ for (i = 0; i < len; i++) { uint8_t dat = buf[i]; - for (j = 0; j < 8; j += bits, act += 2) { + for (j = 0; j < 8; j += bits, act++) { uint8_t tmp = (dat >> j) & msk; if (tmp == msk) continue; if (reserved_block_code && (tmp == reserved_block_code)) { pr_info("nand_read_bbt: reserved block at 0x%012llx\n", - (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); - bbt_mark_entry(this, (offs << 2) + - (act >> 1), + (loff_t)(offs + act) << + this->bbt_erase_shift); + bbt_mark_entry(this, offs + act, BBT_BLOCK_RESERVED); mtd->ecc_stats.bbtblocks++; continue; } pr_debug("nand_read_bbt: bad block at 0x%012llx\n", - (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift); + (loff_t)(offs + act) << + this->bbt_erase_shift); /* Factory marked bad or worn out? */ if (tmp == 0) - bbt_mark_entry(this, (offs << 2) + - (act >> 1), + bbt_mark_entry(this, offs + act, BBT_BLOCK_FACTORY_BAD); else - bbt_mark_entry(this, (offs << 2) + - (act >> 1), + bbt_mark_entry(this, offs + act, BBT_BLOCK_WORN); mtd->ecc_stats.badblocks++; } @@ -287,7 +278,7 @@ static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc td, offs); if (res) return res; - offs += this->chipsize >> (this->bbt_erase_shift + 2); + offs += this->chipsize >> this->bbt_erase_shift; } } else { res = read_bbt(mtd, buf, td->pages[0], @@ -421,25 +412,6 @@ static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, } } -/* Scan a given block full */ -static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, - loff_t offs, uint8_t *buf, size_t readlen, - int scanlen, int numpages) -{ - int ret, j; - - ret = scan_read_oob(mtd, buf, offs, readlen); - /* Ignore ECC errors when checking for BBM */ - if (ret && !mtd_is_bitflip_or_eccerr(ret)) - return ret; - - for (j = 0; j < numpages; j++, buf += scanlen) { - if (check_pattern(buf, scanlen, mtd->writesize, bd)) - return 1; - } - return 0; -} - /* Scan a given block partially */ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, loff_t offs, uint8_t *buf, int numpages) @@ -486,36 +458,19 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip) { struct nand_chip *this = mtd->priv; - int i, numblocks, numpages, scanlen; + int i, numblocks, numpages; int startblock; loff_t from; - size_t readlen; pr_info("Scanning device for bad blocks\n"); - if (bd->options & NAND_BBT_SCANALLPAGES) - numpages = 1 << (this->bbt_erase_shift - this->page_shift); - else if (bd->options & NAND_BBT_SCAN2NDPAGE) + if (bd->options & NAND_BBT_SCAN2NDPAGE) numpages = 2; else numpages = 1; - if (!(bd->options & NAND_BBT_SCANEMPTY)) { - /* We need only read few bytes from the OOB area */ - scanlen = 0; - readlen = bd->len; - } else { - /* Full page content should be read */ - scanlen = mtd->writesize + mtd->oobsize; - readlen = numpages * mtd->writesize; - } - if (chip == -1) { - /* - * Note that numblocks is 2 * (real numblocks) here, see i+=2 - * below as it makes shifting and masking less painful - */ - numblocks = mtd->size >> (this->bbt_erase_shift - 1); + numblocks = mtd->size >> this->bbt_erase_shift; startblock = 0; from = 0; } else { @@ -524,37 +479,31 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, chip + 1, this->numchips); return -EINVAL; } - numblocks = this->chipsize >> (this->bbt_erase_shift - 1); + numblocks = this->chipsize >> this->bbt_erase_shift; startblock = chip * numblocks; numblocks += startblock; - from = (loff_t)startblock << (this->bbt_erase_shift - 1); + from = (loff_t)startblock << this->bbt_erase_shift; } if (this->bbt_options & NAND_BBT_SCANLASTPAGE) from += mtd->erasesize - (mtd->writesize * numpages); - for (i = startblock; i < numblocks;) { + for (i = startblock; i < numblocks; i++) { int ret; BUG_ON(bd->options & NAND_BBT_NO_OOB); - if (bd->options & NAND_BBT_SCANALLPAGES) - ret = scan_block_full(mtd, bd, from, buf, readlen, - scanlen, numpages); - else - ret = scan_block_fast(mtd, bd, from, buf, numpages); - + ret = scan_block_fast(mtd, bd, from, buf, numpages); if (ret < 0) return ret; if (ret) { - bbt_mark_entry(this, i >> 1, BBT_BLOCK_FACTORY_BAD); + bbt_mark_entry(this, i, BBT_BLOCK_FACTORY_BAD); pr_warn("Bad eraseblock %d at 0x%012llx\n", - i >> 1, (unsigned long long)from); + i, (unsigned long long)from); mtd->ecc_stats.badblocks++; } - i += 2; from += (1 << this->bbt_erase_shift); } return 0; @@ -659,6 +608,100 @@ static void search_read_bbts(struct mtd_info *mtd, uint8_t *buf, } /** + * get_bbt_block - Get the first valid eraseblock suitable to store a BBT + * @this: the NAND device + * @td: the BBT description + * @md: the mirror BBT descriptor + * @chip: the CHIP selector + * + * This functions returns a positive block number pointing a valid eraseblock + * suitable to store a BBT (i.e. in the range reserved for BBT), or -ENOSPC if + * all blocks are already used of marked bad. If td->pages[chip] was already + * pointing to a valid block we re-use it, otherwise we search for the next + * valid one. + */ +static int get_bbt_block(struct nand_chip *this, struct nand_bbt_descr *td, + struct nand_bbt_descr *md, int chip) +{ + int startblock, dir, page, numblocks, i; + + /* + * There was already a version of the table, reuse the page. This + * applies for absolute placement too, as we have the page number in + * td->pages. + */ + if (td->pages[chip] != -1) + return td->pages[chip] >> + (this->bbt_erase_shift - this->page_shift); + + numblocks = (int)(this->chipsize >> this->bbt_erase_shift); + if (!(td->options & NAND_BBT_PERCHIP)) + numblocks *= this->numchips; + + /* + * Automatic placement of the bad block table. Search direction + * top -> down? + */ + if (td->options & NAND_BBT_LASTBLOCK) { + startblock = numblocks * (chip + 1) - 1; + dir = -1; + } else { + startblock = chip * numblocks; + dir = 1; + } + + for (i = 0; i < td->maxblocks; i++) { + int block = startblock + dir * i; + + /* Check, if the block is bad */ + switch (bbt_get_entry(this, block)) { + case BBT_BLOCK_WORN: + case BBT_BLOCK_FACTORY_BAD: + continue; + } + + page = block << (this->bbt_erase_shift - this->page_shift); + + /* Check, if the block is used by the mirror table */ + if (!md || md->pages[chip] != page) + return block; + } + + return -ENOSPC; +} + +/** + * mark_bbt_block_bad - Mark one of the block reserved for BBT bad + * @mtd: the MTD device + * @td: the BBT description + * @chip: the CHIP selector + * @block: the BBT block to mark + * + * Blocks reserved for BBT can become bad. This functions is an helper to mark + * such blocks as bad. It takes care of updating the in-memory BBT, marking the + * block as bad using a bad block marker and invalidating the associated + * td->pages[] entry. + */ +static void mark_bbt_block_bad(struct mtd_info *mtd, + struct nand_bbt_descr *td, + int chip, int block) +{ + struct nand_chip *this = mtd->priv; + loff_t to; + int res; + + bbt_mark_entry(this, block, BBT_BLOCK_WORN); + + to = (loff_t)block << this->bbt_erase_shift; + res = this->block_markbad(mtd, to); + if (res) + pr_warn("nand_bbt: error %d while marking block %d bad\n", + res, block); + + td->pages[chip] = -1; +} + +/** * write_bbt - [GENERIC] (Re)write the bad block table * @mtd: MTD device structure * @buf: temporary buffer @@ -674,9 +717,9 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, { struct nand_chip *this = mtd->priv; struct erase_info einfo; - int i, j, res, chip = 0; - int bits, startblock, dir, page, offs, numblocks, sft, sftmsk; - int nrchips, bbtoffs, pageoffs, ooboffs; + int i, res, chip = 0; + int bits, page, offs, numblocks, sft, sftmsk; + int nrchips, pageoffs, ooboffs; uint8_t msk[4]; uint8_t rcode = td->reserved_block_code; size_t retlen, len = 0; @@ -706,46 +749,21 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, } /* Loop through the chips */ - for (; chip < nrchips; chip++) { - /* - * There was already a version of the table, reuse the page - * This applies for absolute placement too, as we have the - * page nr. in td->pages. - */ - if (td->pages[chip] != -1) { - page = td->pages[chip]; - goto write; + while (chip < nrchips) { + int block; + + block = get_bbt_block(this, td, md, chip); + if (block < 0) { + pr_err("No space left to write bad block table\n"); + res = block; + goto outerr; } /* - * Automatic placement of the bad block table. Search direction - * top -> down? + * get_bbt_block() returns a block number, shift the value to + * get a page number. */ - if (td->options & NAND_BBT_LASTBLOCK) { - startblock = numblocks * (chip + 1) - 1; - dir = -1; - } else { - startblock = chip * numblocks; - dir = 1; - } - - for (i = 0; i < td->maxblocks; i++) { - int block = startblock + dir * i; - /* Check, if the block is bad */ - switch (bbt_get_entry(this, block)) { - case BBT_BLOCK_WORN: - case BBT_BLOCK_FACTORY_BAD: - continue; - } - page = block << - (this->bbt_erase_shift - this->page_shift); - /* Check, if the block is used by the mirror table */ - if (!md || md->pages[chip] != page) - goto write; - } - pr_err("No space left to write bad block table\n"); - return -ENOSPC; - write: + page = block << (this->bbt_erase_shift - this->page_shift); /* Set up shift count and masks for the flash table */ bits = td->options & NAND_BBT_NRBITS_MSK; @@ -766,8 +784,6 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, default: return -EINVAL; } - bbtoffs = chip * (numblocks >> 2); - to = ((loff_t)page) << this->page_shift; /* Must we save the block contents? */ @@ -830,16 +846,12 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, buf[ooboffs + td->veroffs] = td->version[chip]; /* Walk through the memory table */ - for (i = 0; i < numblocks;) { + for (i = 0; i < numblocks; i++) { uint8_t dat; - dat = bbt_get_entry(this, (bbtoffs << 2) + i); - for (j = 0; j < 4; j++, i++) { - int sftcnt = (i << (3 - sft)) & sftmsk; - /* Do not store the reserved bbt blocks! */ - buf[offs + (i >> sft)] &= - ~(msk[dat & 0x03] << sftcnt); - dat >>= 2; - } + int sftcnt = (i << (3 - sft)) & sftmsk; + dat = bbt_get_entry(this, chip * numblocks + i); + /* Do not store the reserved bbt blocks! */ + buf[offs + (i >> sft)] &= ~(msk[dat] << sftcnt); } memset(&einfo, 0, sizeof(einfo)); @@ -847,20 +859,28 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf, einfo.addr = to; einfo.len = 1 << this->bbt_erase_shift; res = nand_erase_nand(mtd, &einfo, 1); - if (res < 0) - goto outerr; + if (res < 0) { + pr_warn("nand_bbt: error while erasing BBT block %d\n", + res); + mark_bbt_block_bad(mtd, td, chip, block); + continue; + } res = scan_write_bbt(mtd, to, len, buf, td->options & NAND_BBT_NO_OOB ? NULL : &buf[len]); - if (res < 0) - goto outerr; + if (res < 0) { + pr_warn("nand_bbt: error while writing BBT block %d\n", + res); + mark_bbt_block_bad(mtd, td, chip, block); + continue; + } pr_info("Bad block table written to 0x%012llx, version 0x%02X\n", (unsigned long long)to, td->version[chip]); /* Mark it as used */ - td->pages[chip] = page; + td->pages[chip++] = page; } return 0; @@ -881,7 +901,6 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *b { struct nand_chip *this = mtd->priv; - bd->options &= ~NAND_BBT_SCANEMPTY; return create_bbt(mtd, this->buffers->databuf, bd, -1); } @@ -1042,12 +1061,12 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) if (td->pages[i] == -1) continue; block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift); - block <<= 1; - oldval = bbt_get_entry(this, block >> 1); - bbt_mark_entry(this, block >> 1, BBT_BLOCK_RESERVED); + oldval = bbt_get_entry(this, block); + bbt_mark_entry(this, block, BBT_BLOCK_RESERVED); if ((oldval != BBT_BLOCK_RESERVED) && td->reserved_block_code) - nand_update_bbt(mtd, (loff_t)block << (this->bbt_erase_shift - 1)); + nand_update_bbt(mtd, (loff_t)block << + this->bbt_erase_shift); continue; } update = 0; @@ -1055,13 +1074,12 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) block = ((i + 1) * nrblocks) - td->maxblocks; else block = i * nrblocks; - block <<= 1; for (j = 0; j < td->maxblocks; j++) { - oldval = bbt_get_entry(this, block >> 1); - bbt_mark_entry(this, block >> 1, BBT_BLOCK_RESERVED); + oldval = bbt_get_entry(this, block); + bbt_mark_entry(this, block, BBT_BLOCK_RESERVED); if (oldval != BBT_BLOCK_RESERVED) update = 1; - block += 2; + block++; } /* * If we want reserved blocks to be recorded to flash, and some @@ -1069,7 +1087,8 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td) * bbts. This should only happen once. */ if (update && td->reserved_block_code) - nand_update_bbt(mtd, (loff_t)(block - 2) << (this->bbt_erase_shift - 1)); + nand_update_bbt(mtd, (loff_t)(block - 1) << + this->bbt_erase_shift); } } @@ -1133,10 +1152,10 @@ static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd) * The bad block table memory is allocated here. It must be freed by calling * the nand_free_bbt function. */ -int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) +static int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) { struct nand_chip *this = mtd->priv; - int len, res = 0; + int len, res; uint8_t *buf; struct nand_bbt_descr *td = this->bbt_td; struct nand_bbt_descr *md = this->bbt_md; @@ -1157,10 +1176,9 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) if (!td) { if ((res = nand_memory_bbt(mtd, bd))) { pr_err("nand_bbt: can't scan flash and build the RAM-based BBT\n"); - kfree(this->bbt); - this->bbt = NULL; + goto err; } - return res; + return 0; } verify_bbt_descr(mtd, td); verify_bbt_descr(mtd, md); @@ -1170,9 +1188,8 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) len += (len >> this->page_shift) * mtd->oobsize; buf = vmalloc(len); if (!buf) { - kfree(this->bbt); - this->bbt = NULL; - return -ENOMEM; + res = -ENOMEM; + goto err; } /* Is the bbt at a given page? */ @@ -1184,6 +1201,8 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) } res = check_create(mtd, buf, bd); + if (res) + goto err; /* Prevent the bbt regions from erasing / writing */ mark_bbt_region(mtd, td); @@ -1191,17 +1210,22 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) mark_bbt_region(mtd, md); vfree(buf); + return 0; + +err: + kfree(this->bbt); + this->bbt = NULL; return res; } /** - * nand_update_bbt - [NAND Interface] update bad block table(s) + * nand_update_bbt - update bad block table(s) * @mtd: MTD device structure * @offs: the offset of the newly marked block * * The function updates the bad block table(s). */ -int nand_update_bbt(struct mtd_info *mtd, loff_t offs) +static int nand_update_bbt(struct mtd_info *mtd, loff_t offs) { struct nand_chip *this = mtd->priv; int len, res = 0; @@ -1329,15 +1353,16 @@ static int nand_create_badblock_pattern(struct nand_chip *this) } /** - * nand_default_bbt - [NAND Interface] Select a default bad block table for the device + * nand_create_bbt - [NAND Interface] Select a default bad block table for the device * @mtd: MTD device structure * * This function selects the default bad block table support for the device and * calls the nand_scan_bbt function. */ -int nand_default_bbt(struct mtd_info *mtd) +int nand_create_bbt(struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; + int ret; /* Is a flash based bad block table requested? */ if (this->bbt_options & NAND_BBT_USE_FLASH) { @@ -1356,8 +1381,11 @@ int nand_default_bbt(struct mtd_info *mtd) this->bbt_md = NULL; } - if (!this->badblock_pattern) - nand_create_badblock_pattern(this); + if (!this->badblock_pattern) { + ret = nand_create_badblock_pattern(this); + if (ret) + return ret; + } return nand_scan_bbt(mtd, this->badblock_pattern); } @@ -1374,12 +1402,11 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) int block; uint8_t res; - /* Get block number * 2 */ - block = (int)(offs >> (this->bbt_erase_shift - 1)); - res = bbt_get_entry(this, block >> 1); + block = (int)(offs >> this->bbt_erase_shift); + res = bbt_get_entry(this, block); pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", - (unsigned int)offs, block >> 1, res); + (unsigned int)offs, block, res); switch ((int)res) { case BBT_BLOCK_GOOD: @@ -1392,6 +1419,41 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) return 1; } +static int nand_mark_bbt(struct mtd_info *mtd, loff_t offs, uint8_t mark) +{ + struct nand_chip *this = mtd->priv; + int block, ret = 0; + + block = (int)(offs >> this->bbt_erase_shift); + + /* Mark bad block in memory */ + bbt_mark_entry(this, block, mark); + + /* Update flash-based bad block table */ + if (this->bbt_options & NAND_BBT_USE_FLASH) + ret = nand_update_bbt(mtd, offs); + + return ret; +} + +/** + * nand_markbad_bbt - [NAND Interface] Mark a block bad in the BBT + * @mtd: MTD device structure + * @offs: offset of the bad block + */ +int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs) +{ + return nand_mark_bbt(mtd, offs, BBT_BLOCK_WORN); +} + +/** + * nand_markbad_bbt - [NAND Interface] Mark a block good in the BBT + * @mtd: MTD device structure + * @offs: offset of the good block + */ +int nand_markgood_bbt(struct mtd_info *mtd, loff_t offs) +{ + return nand_mark_bbt(mtd, offs, BBT_BLOCK_GOOD); +} + EXPORT_SYMBOL(nand_scan_bbt); -EXPORT_SYMBOL(nand_default_bbt); -EXPORT_SYMBOL_GPL(nand_update_bbt); diff --git a/drivers/mtd/nand/nand_bch.c b/drivers/mtd/nand/nand_bch.c index e37135f514..d4f2a8cbe4 100644 --- a/drivers/mtd/nand/nand_bch.c +++ b/drivers/mtd/nand/nand_bch.c @@ -104,9 +104,6 @@ EXPORT_SYMBOL(nand_bch_correct_data); /** * nand_bch_init - [NAND Interface] Initialize NAND BCH error correction * @mtd: MTD block structure - * @eccsize: ecc block size in bytes - * @eccbytes: ecc length in bytes - * @ecclayout: output default layout * * Returns: * a pointer to a new NAND BCH control structure, or NULL upon failure @@ -120,14 +117,21 @@ EXPORT_SYMBOL(nand_bch_correct_data); * @eccsize = 512 (thus, m=13 is the smallest integer such that 2^m-1 > 512*8) * @eccbytes = 7 (7 bytes are required to store m*t = 13*4 = 52 bits) */ -struct nand_bch_control * -nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, - struct nand_ecclayout **ecclayout) +struct nand_bch_control *nand_bch_init(struct mtd_info *mtd) { + struct nand_chip *nand = mtd->priv; unsigned int m, t, eccsteps, i; - struct nand_ecclayout *layout; + struct nand_ecclayout *layout = nand->ecc.layout; struct nand_bch_control *nbc = NULL; unsigned char *erased_page; + unsigned int eccsize = nand->ecc.size; + unsigned int eccbytes = nand->ecc.bytes; + unsigned int eccstrength = nand->ecc.strength; + + if (!eccbytes && eccstrength) { + eccbytes = DIV_ROUND_UP(eccstrength * fls(8 * eccsize), 8); + nand->ecc.bytes = eccbytes; + } if (!eccsize || !eccbytes) { printk(KERN_WARNING "ecc parameters not supplied\n"); @@ -155,7 +159,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, eccsteps = mtd->writesize/eccsize; /* if no ecc placement scheme was provided, build one */ - if (!*ecclayout) { + if (!layout) { /* handle large page devices only */ if (mtd->oobsize < 64) { @@ -181,7 +185,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, layout->oobfree[0].offset = 2; layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes; - *ecclayout = layout; + nand->ecc.layout = layout; } /* sanity checks */ @@ -189,7 +193,7 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, printk(KERN_WARNING "eccsize %u is too large\n", eccsize); goto fail; } - if ((*ecclayout)->eccbytes != (eccsteps*eccbytes)) { + if (layout->eccbytes != (eccsteps*eccbytes)) { printk(KERN_WARNING "invalid ecc layout\n"); goto fail; } @@ -213,6 +217,9 @@ nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes, for (i = 0; i < eccbytes; i++) nbc->eccmask[i] ^= 0xff; + if (!eccstrength) + nand->ecc.strength = (eccbytes * 8) / fls(8 * eccsize); + return nbc; fail: nand_bch_free(nbc); diff --git a/drivers/mtd/nand/nand_imx_bbm.c b/drivers/mtd/nand/nand_imx_bbm.c index 23722a9064..4fd5487aa2 100644 --- a/drivers/mtd/nand/nand_imx_bbm.c +++ b/drivers/mtd/nand/nand_imx_bbm.c @@ -129,7 +129,7 @@ static int attach_bbt(struct mtd_info *mtd, void *bbt) free(chip->bbt); chip->bbt = bbt; - return nand_update_bbt(mtd, 0); + return nand_create_bbt(mtd); } static int do_imx_nand_bbm(int argc, char *argv[]) diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c index 28a07d4cba..f69453aba5 100644 --- a/drivers/mtd/nand/nand_mxs.c +++ b/drivers/mtd/nand/nand_mxs.c @@ -1201,21 +1201,7 @@ static int mxs_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) return 0; } -/* - * Nominally, the purpose of this function is to look for or create the bad - * block table. In fact, since the we call this function at the very end of - * the initialization process started by nand_scan(), and we doesn't have a - * more formal mechanism, we "hook" this function to continue init process. - * - * At this point, the physical NAND Flash chips have been identified and - * counted, so we know the physical geometry. This enables us to make some - * important configuration decisions. - * - * The return value of this function propogates directly back to this driver's - * call to nand_scan(). Anything other than zero will cause this driver to - * tear everything down and declare failure. - */ -static int mxs_nand_scan_bbt(struct mtd_info *mtd) +static int mxs_nand_init_bch(struct mtd_info *mtd) { struct nand_chip *nand = mtd->priv; struct mxs_nand_info *nand_info = nand->priv; @@ -1252,8 +1238,7 @@ static int mxs_nand_scan_bbt(struct mtd_info *mtd) mtd->block_markbad = mxs_nand_hook_block_markbad; } - /* We use the reference implementation for bad block management. */ - return nand_default_bbt(mtd); + return 0; } /* @@ -2183,7 +2168,6 @@ static int mxs_nand_probe(struct device_d *dev) nand->dev_ready = mxs_nand_device_ready; nand->select_chip = mxs_nand_select_chip; nand->block_bad = mxs_nand_block_bad; - nand->scan_bbt = mxs_nand_scan_bbt; nand->read_byte = mxs_nand_read_byte; @@ -2215,6 +2199,13 @@ static int mxs_nand_probe(struct device_d *dev) mxs_nand_setup_timing(nand_info); + err = mxs_nand_init_bch(mtd); + if (err) + goto err2; + err = nand_create_bbt(mtd); + if (err) + goto err2; + /* second phase scan */ err = nand_scan_tail(mtd); if (err) diff --git a/drivers/mtd/nand/nand_omap_gpmc.c b/drivers/mtd/nand/nand_omap_gpmc.c index 323a9c7532..2dcf7e723b 100644 --- a/drivers/mtd/nand/nand_omap_gpmc.c +++ b/drivers/mtd/nand/nand_omap_gpmc.c @@ -125,7 +125,6 @@ static struct nand_ecclayout omap_oobinfo; */ static uint8_t scan_ff_pattern[] = { 0xff }; static struct nand_bbt_descr bb_descrip_flashbased = { - .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES, .offs = 0, .len = 1, .pattern = scan_ff_pattern, @@ -162,7 +161,7 @@ static void gpmc_nand_wp(struct gpmc_nand_info *oinfo, int mode) { unsigned long config = readl(oinfo->gpmc_base + GPMC_CFG); - debug("%s: mode=%x\n", __func__, mode); + dev_dbg(oinfo->pdev, "%s: mode=%x\n", __func__, mode); if (mode) config &= ~(NAND_WP_BIT); /* WP is ON */ @@ -228,47 +227,44 @@ static unsigned int gen_true_ecc(u8 *ecc_buf) ((ecc_buf[2] & 0x0F) << 8); } -static int __omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, - uint8_t *ecc_code, int sblock) +static int __omap_calculate_ecc(struct mtd_info *mtd, uint8_t *ecc_code, + int sblock) { struct nand_chip *nand = (struct nand_chip *)(mtd->priv); struct gpmc_nand_info *oinfo = (struct gpmc_nand_info *)(nand->priv); unsigned int reg; unsigned int val1 = 0x0, val2 = 0x0; unsigned int val3 = 0x0, val4 = 0x0; - int i; int ecc_size = 8; switch (oinfo->ecc_mode) { case OMAP_ECC_BCH8_CODE_HW: case OMAP_ECC_BCH8_CODE_HW_ROMCODE: - for (i = 0; i < 4; i++) { - /* - * Reading HW ECC_BCH_Results - * 0x240-0x24C, 0x250-0x25C, 0x260-0x26C, 0x270-0x27C - */ - reg = GPMC_ECC_BCH_RESULT_0 + (0x10 * (i + sblock)); - val1 = readl(oinfo->gpmc_base + reg); - val2 = readl(oinfo->gpmc_base + reg + 4); - if (ecc_size == 8) { - val3 = readl(oinfo->gpmc_base +reg + 8); - val4 = readl(oinfo->gpmc_base + reg + 12); - - *ecc_code++ = (val4 & 0xFF); - *ecc_code++ = ((val3 >> 24) & 0xFF); - *ecc_code++ = ((val3 >> 16) & 0xFF); - *ecc_code++ = ((val3 >> 8) & 0xFF); - *ecc_code++ = (val3 & 0xFF); - *ecc_code++ = ((val2 >> 24) & 0xFF); - } - *ecc_code++ = ((val2 >> 16) & 0xFF); - *ecc_code++ = ((val2 >> 8) & 0xFF); - *ecc_code++ = (val2 & 0xFF); - *ecc_code++ = ((val1 >> 24) & 0xFF); - *ecc_code++ = ((val1 >> 16) & 0xFF); - *ecc_code++ = ((val1 >> 8) & 0xFF); - *ecc_code++ = (val1 & 0xFF); + /* + * Reading HW ECC_BCH_Results + * 0x240-0x24C, 0x250-0x25C, 0x260-0x26C, 0x270-0x27C + */ + reg = GPMC_ECC_BCH_RESULT_0 + (0x10 * sblock); + val1 = readl(oinfo->gpmc_base + reg); + val2 = readl(oinfo->gpmc_base + reg + 4); + if (ecc_size == 8) { + val3 = readl(oinfo->gpmc_base +reg + 8); + val4 = readl(oinfo->gpmc_base + reg + 12); + + *ecc_code++ = (val4 & 0xFF); + *ecc_code++ = ((val3 >> 24) & 0xFF); + *ecc_code++ = ((val3 >> 16) & 0xFF); + *ecc_code++ = ((val3 >> 8) & 0xFF); + *ecc_code++ = (val3 & 0xFF); + *ecc_code++ = ((val2 >> 24) & 0xFF); } + *ecc_code++ = ((val2 >> 16) & 0xFF); + *ecc_code++ = ((val2 >> 8) & 0xFF); + *ecc_code++ = (val2 & 0xFF); + *ecc_code++ = ((val1 >> 24) & 0xFF); + *ecc_code++ = ((val1 >> 16) & 0xFF); + *ecc_code++ = ((val1 >> 8) & 0xFF); + *ecc_code++ = (val1 & 0xFF); break; case OMAP_ECC_HAMMING_CODE_HW_ROMCODE: /* read ecc result */ @@ -288,7 +284,7 @@ static int __omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, uint8_t *ecc_code) { - return __omap_calculate_ecc(mtd, dat, ecc_code, 0); + return __omap_calculate_ecc(mtd, ecc_code, 0); } static int omap_correct_bch(struct mtd_info *mtd, uint8_t *dat, @@ -302,7 +298,6 @@ static int omap_correct_bch(struct mtd_info *mtd, uint8_t *dat, int bch_max_err; int bitflip_count = 0; bool eccflag = 0; - int eccsize = oinfo->nand.ecc.bytes; switch (oinfo->ecc_mode) { @@ -391,14 +386,13 @@ static int omap_correct_hamming(struct mtd_info *mtd, uint8_t *dat, byte = (parity_bits >> 3) & 0x1FF; /* Flip the bit to correct */ dat[byte] ^= (0x1 << bit); + return 1; } else if (hm == 1) { - printf("Ecc is wrong\n"); /* ECC itself is corrupted */ - return 2; + return -EBADMSG; } else { - printf("bad compare! failed\n"); /* detected 2 bit error */ - return -1; + return -EBADMSG; } } @@ -425,23 +419,10 @@ static int omap_correct_data(struct mtd_info *mtd, uint8_t *dat, struct nand_chip *nand = (struct nand_chip *)(mtd->priv); struct gpmc_nand_info *oinfo = (struct gpmc_nand_info *)(nand->priv); - debug("%s\n", __func__); - - switch (oinfo->ecc_mode) { - case OMAP_ECC_HAMMING_CODE_HW_ROMCODE: - return omap_correct_hamming(mtd, dat, read_ecc, calc_ecc); - case OMAP_ECC_BCH8_CODE_HW: - case OMAP_ECC_BCH8_CODE_HW_ROMCODE: - /* - * The nand layer already called omap_calculate_ecc, - * but before it has read the oob data. Do it again, - * this time with oob data. - */ - __omap_calculate_ecc(mtd, dat, calc_ecc, 0); - return omap_correct_bch(mtd, dat, read_ecc, calc_ecc); - default: + if (oinfo->ecc_mode != OMAP_ECC_HAMMING_CODE_HW_ROMCODE) return -EINVAL; - } + + return omap_correct_hamming(mtd, dat, read_ecc, calc_ecc); return 0; } @@ -692,11 +673,10 @@ static int omap_gpmc_read_page_bch_rom_mode(struct mtd_info *mtd, for (i = 0; i < chip->ecc.total; i++) ecc_code[i] = chip->oob_poi[eccpos[i]]; - __omap_calculate_ecc(mtd, buf, ecc_calc, 1); - p = buf; for (i = 0, j = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize, j++) { + __omap_calculate_ecc(mtd, &ecc_calc[i - j], j + 1); stat = omap_correct_bch(mtd, p, &ecc_code[i], &ecc_calc[i - j]); if (stat < 0) { mtd->ecc_stats.failed++; @@ -709,6 +689,44 @@ static int omap_gpmc_read_page_bch_rom_mode(struct mtd_info *mtd, return max_bitflips; } +static int gpmc_read_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) +{ + int i, eccsize = chip->ecc.size; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + uint8_t *p = buf; + uint8_t *ecc_calc = chip->buffers->ecccalc; + uint8_t *ecc_code = chip->buffers->ecccode; + uint32_t *eccpos = chip->ecc.layout->eccpos; + unsigned int max_bitflips = 0; + + chip->ecc.hwctl(mtd, NAND_ECC_READ); + chip->read_buf(mtd, p, mtd->writesize); + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + + for (i = 0; i < chip->ecc.total; i++) + ecc_code[i] = chip->oob_poi[eccpos[i]]; + + eccsteps = chip->ecc.steps; + p = buf; + + for (i = 0 ; eccsteps; eccsteps--, i++, p += eccsize) { + int stat; + + __omap_calculate_ecc(mtd, &ecc_calc[i * eccbytes], i); + stat = omap_correct_bch(mtd, p, &ecc_code[i * eccbytes], &ecc_calc[i * eccbytes]); + if (stat < 0) { + mtd->ecc_stats.failed++; + } else { + mtd->ecc_stats.corrected += stat; + max_bitflips = max_t(unsigned int, max_bitflips, stat); + } + } + return max_bitflips; +} + static int omap_gpmc_eccmode(struct gpmc_nand_info *oinfo, enum gpmc_ecc_mode mode) { @@ -737,6 +755,7 @@ static int omap_gpmc_eccmode(struct gpmc_nand_info *oinfo, nand->ecc.read_oob = NULL; nand->ecc.write_oob = NULL; nand->ecc.mode = NAND_ECC_HW; + nand->options &= ~NAND_SUBPAGE_READ; } switch (mode) { @@ -762,11 +781,17 @@ static int omap_gpmc_eccmode(struct gpmc_nand_info *oinfo, oinfo->nand.ecc.bytes = 13; oinfo->nand.ecc.size = 512; oinfo->nand.ecc.strength = BCH8_MAX_ERROR; + nand->ecc.read_page = gpmc_read_page_hwecc; omap_oobinfo.oobfree->offset = offset; + oinfo->nand.ecc.steps = minfo->writesize / oinfo->nand.ecc.size; + oinfo->nand.ecc.total = oinfo->nand.ecc.steps * oinfo->nand.ecc.bytes; + omap_oobinfo.eccbytes = oinfo->nand.ecc.total; + omap_oobinfo.oobfree->length = minfo->oobsize - offset - omap_oobinfo.eccbytes; - offset = minfo->oobsize - oinfo->nand.ecc.bytes; - for (i = 0; i < oinfo->nand.ecc.bytes; i++) + offset = minfo->oobsize - oinfo->nand.ecc.total; + + for (i = 0; i < oinfo->nand.ecc.total; i++) omap_oobinfo.eccpos[i] = i + offset; break; case OMAP_ECC_BCH8_CODE_HW_ROMCODE: @@ -775,6 +800,9 @@ static int omap_gpmc_eccmode(struct gpmc_nand_info *oinfo, oinfo->nand.ecc.strength = BCH8_MAX_ERROR; nand->ecc.read_page = omap_gpmc_read_page_bch_rom_mode; omap_oobinfo.oobfree->length = 0; + oinfo->nand.ecc.steps = minfo->writesize / oinfo->nand.ecc.size; + oinfo->nand.ecc.total = oinfo->nand.ecc.steps * oinfo->nand.ecc.bytes; + omap_oobinfo.eccbytes = oinfo->nand.ecc.total; j = 0; for (i = 2; i < 58; i++) omap_oobinfo.eccpos[j++] = i; diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 2fccd4681e..ff35b746e2 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -32,18 +32,16 @@ #include <asm/system.h> #include <linux/phy.h> #include <mach/emac_defs.h> -#include <platform_data/eth-davinci-emac.h> +#include <of_net.h> #include "davinci_emac.h" struct davinci_emac_priv { struct device_d *dev; struct eth_device edev; - struct mii_bus miibus; /* EMAC Addresses */ void __iomem *adap_emac; /* = EMAC_BASE_ADDR */ void __iomem *adap_ewrap; /* = EMAC_WRAPPER_BASE_ADDR */ - void __iomem *adap_mdio; /* = EMAC_MDIO_BASE_ADDR */ /* EMAC descriptors */ void __iomem *emac_desc_base; /* = EMAC_WRAPPER_RAM_ADDR */ @@ -58,8 +56,6 @@ struct davinci_emac_priv { /* PHY-specific information */ phy_interface_t interface; - uint8_t phy_addr; - uint32_t phy_flags; /* mac_addr[0] goes out on the wire first */ uint8_t mac_addr[6]; @@ -86,7 +82,13 @@ static inline void __iomem *HW_TO_BD(uint32_t x) #define HW_TO_BD(x) (x) #endif -static void davinci_eth_mdio_enable(struct davinci_emac_priv *priv) +struct davinci_mdio_priv { + struct device_d *dev; + struct mii_bus miibus; + void __iomem *adap_mdio; /* = EMAC_MDIO_BASE_ADDR */ +}; + +static void davinci_eth_mdio_enable(struct davinci_mdio_priv *priv) { uint32_t clkdiv; @@ -105,13 +107,40 @@ static void davinci_eth_mdio_enable(struct davinci_emac_priv *priv) while (readl(priv->adap_mdio + EMAC_MDIO_CONTROL) & MDIO_CONTROL_IDLE); } +/* wait until hardware is ready for another user access */ +static int wait_for_user_access(struct davinci_mdio_priv *priv, uint32_t *val) +{ + u32 tmp; + uint64_t start = get_time_ns(); + + do { + tmp = readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0); + + if (!(tmp & MDIO_USERACCESS0_GO)) + break; + + if (is_timeout(start, 100 * MSECOND)) { + dev_err(priv->dev, "timeout waiting for user access\n"); + return -ETIMEDOUT; + } + } while (1); + + if (val) + *val = tmp; + + return 0; +} + + static int davinci_miibus_read(struct mii_bus *bus, int addr, int reg) { - struct davinci_emac_priv *priv = bus->priv; + struct davinci_mdio_priv *priv = bus->priv; uint16_t value; - int tmp; + int tmp, ret; - while (readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0) & MDIO_USERACCESS0_GO); + ret = wait_for_user_access(priv, NULL); + if (ret) + return ret; writel(MDIO_USERACCESS0_GO | MDIO_USERACCESS0_WRITE_READ | @@ -119,8 +148,9 @@ static int davinci_miibus_read(struct mii_bus *bus, int addr, int reg) ((addr & 0x1f) << 16), priv->adap_mdio + EMAC_MDIO_USERACCESS0); - /* Wait for command to complete */ - while ((tmp = readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0)) & MDIO_USERACCESS0_GO); + ret = wait_for_user_access(priv, &tmp); + if (ret) + return ret; if (tmp & MDIO_USERACCESS0_ACK) { value = tmp & 0xffff; @@ -134,8 +164,12 @@ static int davinci_miibus_read(struct mii_bus *bus, int addr, int reg) static int davinci_miibus_write(struct mii_bus *bus, int addr, int reg, u16 value) { - struct davinci_emac_priv *priv = bus->priv; - while (readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0) & MDIO_USERACCESS0_GO); + struct davinci_mdio_priv *priv = bus->priv; + int ret; + + ret = wait_for_user_access(priv, NULL); + if (ret) + return ret; dev_dbg(priv->dev, "davinci_miibus_write: addr=0x%02x reg=0x%02x value=0x%04x\n", addr, reg, value); @@ -146,10 +180,7 @@ static int davinci_miibus_write(struct mii_bus *bus, int addr, int reg, u16 valu (value & 0xffff), priv->adap_mdio + EMAC_MDIO_USERACCESS0); - /* Wait for command to complete */ - while (readl(priv->adap_mdio + EMAC_MDIO_USERACCESS0) & MDIO_USERACCESS0_GO); - - return 0; + return wait_for_user_access(priv, NULL); } static int davinci_emac_get_ethaddr(struct eth_device *edev, unsigned char *adr) @@ -173,6 +204,17 @@ static int davinci_emac_set_ethaddr(struct eth_device *edev, const unsigned char static int davinci_emac_init(struct eth_device *edev) { + struct davinci_emac_priv *priv = edev->priv; + uint32_t cnt; + + /* Set DMA head and completion pointers to 0 */ + for(cnt = 0; cnt < 8; cnt++) { + writel(0, (void *)priv->adap_emac + EMAC_TX0HDP + 4 * cnt); + writel(0, (void *)priv->adap_emac + EMAC_RX0HDP + 4 * cnt); + writel(0, (void *)priv->adap_emac + EMAC_TX0CP + 4 * cnt); + writel(0, (void *)priv->adap_emac + EMAC_RX0CP + 4 * cnt); + } + dev_dbg(&edev->dev, "* emac_init\n"); return 0; } @@ -180,7 +222,7 @@ static int davinci_emac_init(struct eth_device *edev) static int davinci_emac_open(struct eth_device *edev) { struct davinci_emac_priv *priv = edev->priv; - uint32_t clkdiv, cnt; + uint32_t cnt; void __iomem *rx_desc; unsigned long mac_hi, mac_lo; int ret; @@ -282,16 +324,10 @@ static int davinci_emac_open(struct eth_device *edev) EMAC_MACCONTROL_RMIISPEED_100), priv->adap_emac + EMAC_MACCONTROL); - /* Init MDIO & get link state */ - clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; - writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT, - priv->adap_mdio + EMAC_MDIO_CONTROL); - /* Start receive process */ writel(BD_TO_HW(priv->emac_rx_desc), priv->adap_emac + EMAC_RX0HDP); - ret = phy_device_connect(edev, &priv->miibus, priv->phy_addr, NULL, - priv->phy_flags, priv->interface); + ret = phy_device_connect(edev, NULL, -1, NULL, 0, priv->interface); if (ret) return ret; @@ -500,19 +536,13 @@ out: static int davinci_emac_probe(struct device_d *dev) { struct resource *iores; - struct davinci_emac_platform_data *pdata; struct davinci_emac_priv *priv; - uint64_t start; - uint32_t phy_mask; + uint32_t ctrl_reg_offset; + uint32_t ctrl_ram_offset; + struct device_node *np = dev->device_node; dev_dbg(dev, "+ emac_probe\n"); - if (!dev->platform_data) { - dev_err(dev, "no platform_data\n"); - return -ENODEV; - } - pdata = dev->platform_data; - priv = xzalloc(sizeof(*priv)); dev->priv = priv; @@ -521,22 +551,14 @@ static int davinci_emac_probe(struct device_d *dev) iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) return PTR_ERR(iores); - priv->adap_emac = IOMEM(iores->start); - iores = dev_request_mem_resource(dev, 1); - if (IS_ERR(iores)) - return PTR_ERR(iores); priv->adap_ewrap = IOMEM(iores->start); - iores = dev_request_mem_resource(dev, 2); - if (IS_ERR(iores)) - return PTR_ERR(iores); - priv->adap_mdio = IOMEM(iores->start); + of_property_read_u32(np, "ti,davinci-ctrl-reg-offset", &ctrl_reg_offset); + priv->adap_emac = IOMEM(iores->start) + ctrl_reg_offset; - iores = dev_request_mem_resource(dev, 3); - if (IS_ERR(iores)) - return PTR_ERR(iores); - priv->emac_desc_base = IOMEM(iores->start); + of_property_read_u32(np, "ti,davinci-ctrl-ram-offset", &ctrl_ram_offset); + priv->emac_desc_base = IOMEM(iores->start) + ctrl_ram_offset; /* EMAC descriptors */ priv->emac_rx_desc = priv->emac_desc_base + EMAC_RX_DESC_BASE; @@ -558,37 +580,7 @@ static int davinci_emac_probe(struct device_d *dev) priv->edev.set_ethaddr = davinci_emac_set_ethaddr; priv->edev.parent = dev; - davinci_eth_mdio_enable(priv); - - start = get_time_ns(); - while (1) { - phy_mask = readl(priv->adap_mdio + EMAC_MDIO_ALIVE); - if (phy_mask) { - dev_info(dev, "detected phy mask 0x%x\n", phy_mask); - phy_mask = ~phy_mask; - break; - } - if (is_timeout(start, 256 * MSECOND)) { - dev_err(dev, "no live phy, scanning all\n"); - phy_mask = 0; - break; - } - } - - if (pdata->interface_rmii) - priv->interface = PHY_INTERFACE_MODE_RMII; - else - priv->interface = PHY_INTERFACE_MODE_MII; - priv->phy_addr = pdata->phy_addr; - priv->phy_flags = pdata->force_link ? PHYLIB_FORCE_LINK : 0; - - priv->miibus.read = davinci_miibus_read; - priv->miibus.write = davinci_miibus_write; - priv->miibus.priv = priv; - priv->miibus.parent = dev; - priv->miibus.phy_mask = phy_mask; - - mdiobus_register(&priv->miibus); + priv->interface = of_get_phy_mode(np); eth_register(&priv->edev); @@ -603,9 +595,73 @@ static void davinci_emac_remove(struct device_d *dev) davinci_emac_halt(&priv->edev); } +static __maybe_unused struct of_device_id davinci_emac_dt_ids[] = { + { + .compatible = "ti,am3517-emac", + }, { + /* sentinel */ + } +}; + static struct driver_d davinci_emac_driver = { .name = "davinci_emac", .probe = davinci_emac_probe, .remove = davinci_emac_remove, + .of_compatible = DRV_OF_COMPAT(davinci_emac_dt_ids), }; device_platform_driver(davinci_emac_driver); + +static int davinci_mdio_probe(struct device_d *dev) +{ + struct resource *iores; + struct davinci_mdio_priv *priv; + int ret; + uint32_t clkdiv; + + priv = xzalloc(sizeof(*priv)); + + priv->dev = dev; + priv->miibus.read = davinci_miibus_read; + priv->miibus.write = davinci_miibus_write; + priv->miibus.priv = priv; + priv->miibus.parent = dev; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + priv->adap_mdio = IOMEM(iores->start); + + davinci_eth_mdio_enable(priv); + + /* Init MDIO & get link state */ + clkdiv = (EMAC_MDIO_BUS_FREQ / EMAC_MDIO_CLOCK_FREQ) - 1; + writel((clkdiv & 0xff) | MDIO_CONTROL_ENABLE | MDIO_CONTROL_FAULT, + priv->adap_mdio + EMAC_MDIO_CONTROL); + + ret = mdiobus_register(&priv->miibus); + if (ret) + goto err; + + return 0; + +err: + free(priv); + + return ret; +} + +static __maybe_unused struct of_device_id davinci_mdio_dt_ids[] = { + { + .compatible = "ti,davinci_mdio", + }, { + /* sentinel */ + } +}; + +static struct driver_d davinci_mdio_driver = { + .name = "davinci_mdio", + .probe = davinci_mdio_probe, + .of_compatible = DRV_OF_COMPAT(davinci_mdio_dt_ids), +}; +device_platform_driver(davinci_mdio_driver); diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 4a1a1aa336..0a9e107c07 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -95,19 +95,17 @@ typedef enum { /* Error Codes */ #define E1000_SUCCESS 0 -#define E1000_ERR_EEPROM 1 -#define E1000_ERR_PHY 2 -#define E1000_ERR_CONFIG 3 -#define E1000_ERR_PARAM 4 -#define E1000_ERR_MAC_TYPE 5 -#define E1000_ERR_PHY_TYPE 6 -#define E1000_ERR_NOLINK 7 -#define E1000_ERR_TIMEOUT 8 -#define E1000_ERR_RESET 9 -#define E1000_ERR_MASTER_REQUESTS_PENDING 10 -#define E1000_ERR_HOST_INTERFACE_COMMAND 11 -#define E1000_BLK_PHY_RESET 12 -#define E1000_ERR_SWFW_SYNC 13 +#define E1000_ERR_EEPROM EIO +#define E1000_ERR_PHY EIO +#define E1000_ERR_CONFIG EINVAL +#define E1000_ERR_PARAM EINVAL +#define E1000_ERR_MAC_TYPE EINVAL +#define E1000_ERR_PHY_TYPE EINVAL +#define E1000_ERR_NOLINK ENETDOWN +#define E1000_ERR_TIMEOUT ETIMEDOUT +#define E1000_ERR_RESET EIO +#define E1000_BLK_PHY_RESET EWOULDBLOCK +#define E1000_ERR_SWFW_SYNC EBUSY /* PCI Device IDs */ #define E1000_DEV_ID_82542 0x1000 diff --git a/drivers/net/e1000/main.c b/drivers/net/e1000/main.c index caa7274a8d..0ef8fd6231 100644 --- a/drivers/net/e1000/main.c +++ b/drivers/net/e1000/main.c @@ -231,7 +231,7 @@ static int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw) if (!timeout) { /* Release semaphores */ e1000_put_hw_eeprom_semaphore(hw); - dev_dbg(hw->dev, "Driver can't access the Eeprom - " + dev_err(hw->dev, "Driver can't access the Eeprom - " "SWESMBI bit is set.\n"); return -E1000_ERR_EEPROM; } @@ -262,7 +262,7 @@ int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask) } if (!timeout) { - dev_dbg(hw->dev, "Driver can't access resource, SW_FW_SYNC timeout.\n"); + dev_err(hw->dev, "Driver can't access resource, SW_FW_SYNC timeout.\n"); return -E1000_ERR_SWFW_SYNC; } @@ -332,7 +332,7 @@ static int e1000_get_ethaddr(struct eth_device *edev, unsigned char *adr) for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) { if (e1000_read_eeprom(hw, i >> 1, 1, &eeprom_data) < 0) { - dev_dbg(hw->dev, "EEPROM Read Error\n"); + dev_err(hw->dev, "EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } adr[i] = eeprom_data & 0xff; @@ -832,20 +832,6 @@ static int e1000_setup_link(struct e1000_hw *hw) if (e1000_check_phy_reset_block(hw)) return E1000_SUCCESS; - /* Read and store word 0x0F of the EEPROM. This word contains bits - * that determine the hardware's default PAUSE (flow control) mode, - * a bit that determines whether the HW defaults to enabling or - * disabling auto-negotiation, and the direction of the - * SW defined pins. If there is no SW over-ride of the flow - * control setting, then the variable hw->fc will - * be initialized based on a value in the EEPROM. - */ - if (e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, - &eeprom_data) < 0) { - dev_dbg(hw->dev, "EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - switch (hw->mac_type) { case e1000_ich8lan: case e1000_82573: @@ -854,6 +840,22 @@ static int e1000_setup_link(struct e1000_hw *hw) hw->fc = e1000_fc_full; break; default: + /* Read and store word 0x0F of the EEPROM. This word + * contains bits that determine the hardware's default + * PAUSE (flow control) mode, a bit that determines + * whether the HW defaults to enabling or disabling + * auto-negotiation, and the direction of the SW + * defined pins. If there is no SW over-ride of the + * flow control setting, then the variable hw->fc will + * be initialized based on a value in the EEPROM. + */ + ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, + &eeprom_data); + if (ret_val < 0) { + dev_err(hw->dev, "EEPROM Read Error\n"); + return ret_val; + } + if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) hw->fc = e1000_fc_none; else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == EEPROM_WORD0F_ASM_DIR) @@ -1006,7 +1008,7 @@ static int e1000_setup_fiber_link(struct e1000_hw *hw) txcw = E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK; break; default: - dev_dbg(hw->dev, "Flow control param set incorrectly\n"); + dev_err(hw->dev, "Flow control param set incorrectly\n"); return -E1000_ERR_CONFIG; break; } @@ -1044,7 +1046,7 @@ static int e1000_setup_fiber_link(struct e1000_hw *hw) * detect a signal. This will allow us to communicate with * non-autonegotiating link partners. */ - dev_dbg(hw->dev, "Never got a valid link from auto-neg!!!\n"); + dev_err(hw->dev, "Never got a valid link from auto-neg!!!\n"); hw->autoneg_failed = 1; return -E1000_ERR_NOLINK; } else { @@ -1052,7 +1054,7 @@ static int e1000_setup_fiber_link(struct e1000_hw *hw) dev_dbg(hw->dev, "Valid Link Found\n"); } } else { - dev_dbg(hw->dev, "No Signal Detected\n"); + dev_err(hw->dev, "No Signal Detected\n"); return -E1000_ERR_NOLINK; } return 0; @@ -1092,7 +1094,7 @@ static int32_t e1000_copper_link_preconfig(struct e1000_hw *hw) /* Make sure we have a valid PHY */ ret_val = e1000_detect_gig_phy(hw); if (ret_val) { - dev_dbg(hw->dev, "Error, did not detect valid phy.\n"); + dev_err(hw->dev, "Error, did not detect valid phy.\n"); return ret_val; } dev_dbg(hw->dev, "Phy ID = %x \n", hw->phy_id); @@ -1236,7 +1238,7 @@ static int32_t e1000_copper_link_igp_setup(struct e1000_hw *hw) ret_val = e1000_phy_reset(hw); if (ret_val) { - dev_dbg(hw->dev, "Error Resetting the PHY\n"); + dev_err(hw->dev, "Error Resetting the PHY\n"); return ret_val; } @@ -1255,7 +1257,7 @@ static int32_t e1000_copper_link_igp_setup(struct e1000_hw *hw) /* disable lplu d3 during driver init */ ret_val = e1000_set_d3_lplu_state_off(hw); if (ret_val) { - dev_dbg(hw->dev, "Error Disabling LPLU D3\n"); + dev_err(hw->dev, "Error Disabling LPLU D3\n"); return ret_val; } } @@ -1263,7 +1265,7 @@ static int32_t e1000_copper_link_igp_setup(struct e1000_hw *hw) /* disable lplu d0 during driver init */ ret_val = e1000_set_d0_lplu_state_off(hw); if (ret_val) { - dev_dbg(hw->dev, "Error Disabling LPLU D0\n"); + dev_err(hw->dev, "Error Disabling LPLU D0\n"); return ret_val; } @@ -1457,7 +1459,7 @@ static int32_t e1000_copper_link_ggp_setup(struct e1000_hw *hw) /* SW Reset the PHY so all changes take effect */ ret_val = e1000_phy_reset(hw); if (ret_val) { - dev_dbg(hw->dev, "Error Resetting the PHY\n"); + dev_err(hw->dev, "Error Resetting the PHY\n"); return ret_val; } @@ -1586,7 +1588,7 @@ static int32_t e1000_copper_link_mgp_setup(struct e1000_hw *hw) /* SW Reset the PHY so all changes take effect */ ret_val = e1000_phy_reset(hw); if (ret_val) { - dev_dbg(hw->dev, "Error Resetting the PHY\n"); + dev_err(hw->dev, "Error Resetting the PHY\n"); return ret_val; } @@ -1615,7 +1617,7 @@ static int32_t e1000_copper_link_autoneg(struct e1000_hw *hw) dev_dbg(hw->dev, "Reconfiguring auto-neg advertisement params\n"); ret_val = e1000_phy_setup_autoneg(hw); if (ret_val) { - dev_dbg(hw->dev, "Error Setting up Auto-Negotiation\n"); + dev_err(hw->dev, "Error Setting up Auto-Negotiation\n"); return ret_val; } dev_dbg(hw->dev, "Restarting Auto-Neg\n"); @@ -1634,7 +1636,7 @@ static int32_t e1000_copper_link_autoneg(struct e1000_hw *hw) ret_val = e1000_wait_autoneg(hw); if (ret_val) { - dev_dbg(hw->dev, "Error while waiting for autoneg to complete\n"); + dev_err(hw->dev, "Error while waiting for autoneg to complete\n"); return ret_val; } @@ -1663,14 +1665,14 @@ static int32_t e1000_copper_link_postconfig(struct e1000_hw *hw) } else { ret_val = e1000_config_mac_to_phy(hw); if (ret_val) { - dev_dbg(hw->dev, "Error configuring MAC to PHY settings\n"); + dev_err(hw->dev, "Error configuring MAC to PHY settings\n"); return ret_val; } } ret_val = e1000_config_fc_after_link_up(hw); if (ret_val) { - dev_dbg(hw->dev, "Error Configuring Flow Control\n"); + dev_err(hw->dev, "Error Configuring Flow Control\n"); return ret_val; } @@ -1983,7 +1985,7 @@ static int e1000_config_mac_to_phy(struct e1000_hw *hw) * registers depending on negotiated values. */ if (e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { - dev_dbg(hw->dev, "PHY Read Error\n"); + dev_err(hw->dev, "PHY Read Error\n"); return -E1000_ERR_PHY; } if (phy_data & M88E1000_PSSR_DPLX) @@ -2059,7 +2061,7 @@ static int e1000_force_mac_fc(struct e1000_hw *hw) ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); break; default: - dev_dbg(hw->dev, "Flow control param set incorrectly\n"); + dev_err(hw->dev, "Flow control param set incorrectly\n"); return -E1000_ERR_CONFIG; } @@ -2098,17 +2100,17 @@ static int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw) * some "sticky" (latched) bits. */ if (e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - dev_dbg(hw->dev, "PHY Read Error \n"); + dev_err(hw->dev, "PHY Read Error \n"); return -E1000_ERR_PHY; } if (e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - dev_dbg(hw->dev, "PHY Read Error \n"); + dev_err(hw->dev, "PHY Read Error \n"); return -E1000_ERR_PHY; } if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) { - dev_dbg(hw->dev, "Copper PHY and Auto Neg has not completed.\n"); + dev_err(hw->dev, "Copper PHY and Auto Neg has not completed.\n"); return 0; } @@ -2119,12 +2121,12 @@ static int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw) * negotiated. */ if (e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg) < 0) { - dev_dbg(hw->dev, "PHY Read Error\n"); + dev_err(hw->dev, "PHY Read Error\n"); return -E1000_ERR_PHY; } if (e1000_read_phy_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg) < 0) { - dev_dbg(hw->dev, "PHY Read Error\n"); + dev_err(hw->dev, "PHY Read Error\n"); return -E1000_ERR_PHY; } @@ -2250,7 +2252,7 @@ static int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw) */ ret_val = e1000_force_mac_fc(hw); if (ret_val < 0) { - dev_dbg(hw->dev, "Error forcing flow control settings\n"); + dev_err(hw->dev, "Error forcing flow control settings\n"); return ret_val; } @@ -2399,11 +2401,11 @@ static int e1000_wait_autoneg(struct e1000_hw *hw) * Complete bit to be set. */ if (e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - dev_dbg(hw->dev, "PHY Read Error\n"); + dev_err(hw->dev, "PHY Read Error\n"); return -E1000_ERR_PHY; } if (e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - dev_dbg(hw->dev, "PHY Read Error\n"); + dev_err(hw->dev, "PHY Read Error\n"); return -E1000_ERR_PHY; } if (phy_data & MII_SR_AUTONEG_COMPLETE) { @@ -2412,7 +2414,7 @@ static int e1000_wait_autoneg(struct e1000_hw *hw) } mdelay(100); } - dev_dbg(hw->dev, "Auto-Neg timedout.\n"); + dev_err(hw->dev, "Auto-Neg timedout.\n"); return -E1000_ERR_TIMEOUT; } @@ -2578,11 +2580,11 @@ static int e1000_phy_read(struct mii_bus *bus, int phy_addr, int reg_addr) break; } if (!(mdic & E1000_MDIC_READY)) { - dev_dbg(hw->dev, "MDI Read did not complete\n"); + dev_err(hw->dev, "MDI Read did not complete\n"); return -E1000_ERR_PHY; } if (mdic & E1000_MDIC_ERROR) { - dev_dbg(hw->dev, "MDI Error\n"); + dev_err(hw->dev, "MDI Error\n"); return -E1000_ERR_PHY; } return mdic; @@ -2667,7 +2669,7 @@ static int e1000_phy_write(struct mii_bus *bus, int phy_addr, break; } if (!(mdic & E1000_MDIC_READY)) { - dev_dbg(hw->dev, "MDI Write did not complete\n"); + dev_err(hw->dev, "MDI Write did not complete\n"); return -E1000_ERR_PHY; } } else { @@ -2774,7 +2776,7 @@ static int32_t e1000_get_phy_cfg_done(struct e1000_hw *hw) timeout--; } if (!timeout) { - dev_dbg(hw->dev, "MNG configuration cycle has not completed.\n"); + dev_err(hw->dev, "MNG configuration cycle has not completed.\n"); return -E1000_ERR_RESET; } break; @@ -2810,7 +2812,7 @@ static int32_t e1000_phy_hw_reset(struct e1000_hw *hw) swfw = E1000_SWFW_PHY1_SM; if (e1000_swfw_sync_acquire(hw, swfw)) { - dev_dbg(hw->dev, "Unable to acquire swfw sync\n"); + dev_err(hw->dev, "Unable to acquire swfw sync\n"); return -E1000_ERR_SWFW_SYNC; } @@ -3109,12 +3111,12 @@ static int32_t e1000_detect_gig_phy(struct e1000_hw *hw) phy_type = e1000_phy_igb; break; default: - dev_dbg(hw->dev, "Invalid MAC type %d\n", hw->mac_type); + dev_err(hw->dev, "Invalid MAC type %d\n", hw->mac_type); return -E1000_ERR_CONFIG; } if (phy_type == e1000_phy_undefined) { - dev_dbg(hw->dev, "Invalid PHY ID 0x%X\n", hw->phy_id); + dev_err(hw->dev, "Invalid PHY ID 0x%X\n", hw->phy_id); return -EINVAL; } diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c index c2628cc1d6..4823b08340 100644 --- a/drivers/net/fec_imx.c +++ b/drivers/net/fec_imx.c @@ -51,7 +51,7 @@ static int fec_miibus_read(struct mii_bus *bus, int phyAddr, int regAddr) * wait for the related interrupt */ if (readl_poll_timeout(fec->regs + FEC_IEVENT, reg, - reg & FEC_IEVENT_MII, MSECOND)) { + reg & FEC_IEVENT_MII, USEC_PER_MSEC)) { dev_err(&fec->edev.dev, "Read MDIO failed...\n"); return -1; } @@ -88,7 +88,7 @@ static int fec_miibus_write(struct mii_bus *bus, int phyAddr, * wait for the MII interrupt */ if (readl_poll_timeout(fec->regs + FEC_IEVENT, reg, - reg & FEC_IEVENT_MII, MSECOND)) { + reg & FEC_IEVENT_MII, USEC_PER_MSEC)) { dev_err(&fec->edev.dev, "Write MDIO failed...\n"); return -1; } @@ -401,7 +401,7 @@ static void fec_halt(struct eth_device *dev) /* wait for graceful stop to register */ if (readl_poll_timeout(fec->regs + FEC_IEVENT, reg, - reg & FEC_IEVENT_GRA, SECOND)) + reg & FEC_IEVENT_GRA, USEC_PER_SEC)) dev_err(&dev->dev, "graceful stop timeout\n"); /* Disable SmartDMA tasks */ @@ -475,7 +475,7 @@ static int fec_send(struct eth_device *dev, void *eth_data, int data_length) fec_tx_task_enable(fec); if (readw_poll_timeout(&fec->tbd_base[fec->tbd_index].status, - status, !(status & FEC_TBD_READY), SECOND)) + status, !(status & FEC_TBD_READY), USEC_PER_SEC)) dev_err(&dev->dev, "transmission timeout\n"); dma_unmap_single(fec->dev, dma, data_length, DMA_TO_DEVICE); @@ -796,7 +796,7 @@ static int fec_probe(struct device_d *dev) /* Reset chip. */ writel(FEC_ECNTRL_RESET, fec->regs + FEC_ECNTRL); ret = readl_poll_timeout(fec->regs + FEC_ECNTRL, reg, - !(reg & FEC_ECNTRL_RESET), SECOND); + !(reg & FEC_ECNTRL_RESET), USEC_PER_SEC); if (ret) goto free_gpio; diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c index c0608112d5..b037e19633 100644 --- a/drivers/net/ks8851_mll.c +++ b/drivers/net/ks8851_mll.c @@ -435,7 +435,7 @@ static inline void ks_outblk(struct ks_net *ks, u16 *wptr, u32 len) writew(*wptr++, ks->hw_addr); } -void ks_enable_qmu(struct ks_net *ks) +static void ks_enable_qmu(struct ks_net *ks) { u16 w; diff --git a/drivers/nvmem/ocotp.c b/drivers/nvmem/ocotp.c index e0cf35f0b7..5b8b925cb4 100644 --- a/drivers/nvmem/ocotp.c +++ b/drivers/nvmem/ocotp.c @@ -446,9 +446,18 @@ static int imx_ocotp_set_mac(struct param_d *param, void *priv) { char buf[MAC_BYTES]; struct ocotp_priv_ethaddr *ethaddr = priv; + int ret; - ethaddr->data->format_mac(buf, ethaddr->value, - OCOTP_MAC_TO_HW); + ret = regmap_bulk_read(ethaddr->map, ethaddr->offset, buf, MAC_BYTES); + if (ret < 0) + return ret; + + if (ethaddr->offset != IMX6UL_MAC_OFFSET_1) + ethaddr->data->format_mac(buf, ethaddr->value, + OCOTP_MAC_TO_HW); + else + ethaddr->data->format_mac(buf + 2, ethaddr->value, + OCOTP_MAC_TO_HW); return regmap_bulk_write(ethaddr->map, ethaddr->offset, buf, MAC_BYTES); @@ -697,11 +706,4 @@ static struct driver_d imx_ocotp_driver = { .probe = imx_ocotp_probe, .of_compatible = DRV_OF_COMPAT(imx_ocotp_dt_ids), }; - -static int imx_ocotp_init(void) -{ - platform_driver_register(&imx_ocotp_driver); - - return 0; -} -postcore_initcall(imx_ocotp_init); +postcore_platform_driver(imx_ocotp_driver); diff --git a/drivers/pinctrl/imx-iomux-v3.c b/drivers/pinctrl/imx-iomux-v3.c index b2a67fcccc..5fadc84151 100644 --- a/drivers/pinctrl/imx-iomux-v3.c +++ b/drivers/pinctrl/imx-iomux-v3.c @@ -220,9 +220,6 @@ static struct imx_iomux_v3_data imx_iomux_imx7_lpsr_data = { .flags = ZERO_OFFSET_VALID | IMX7_PINMUX_LPSR, }; -static struct imx_iomux_v3_data imx_iomux_imx8_data = { - .flags = SHARE_CONF, -}; static __maybe_unused struct of_device_id imx_iomux_v3_dt_ids[] = { { @@ -250,7 +247,6 @@ static __maybe_unused struct of_device_id imx_iomux_v3_dt_ids[] = { .data = &imx_iomux_imx7_lpsr_data, }, { .compatible = "fsl,imx8mq-iomuxc", - .data = &imx_iomux_imx8_data, }, { /* sentinel */ } diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 4c4067d5b5..9b567e3cd2 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -148,7 +148,7 @@ static void pl011_rlcr(struct amba_uart_port *uart, u32 lcr) } } -int pl011_init_port (struct console_device *cdev) +static int pl011_init_port(struct console_device *cdev) { struct amba_uart_port *uart = to_amba_uart_port(cdev); @@ -185,7 +185,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) struct regulator *r; r = regulator_get(&dev->dev, NULL); - if (r) { + if (!IS_ERR(r)) { int ret; ret = regulator_enable(r); diff --git a/drivers/serial/serial_clps711x.c b/drivers/serial/serial_clps711x.c index fa6342346a..7a7d595dff 100644 --- a/drivers/serial/serial_clps711x.c +++ b/drivers/serial/serial_clps711x.c @@ -1,13 +1,5 @@ -/* - * Simple CLPS711X serial driver - * - * (C) Copyright 2012-2014 Alexander Shiyan <shc_work@mail.ru> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Author: Alexander Shiyan <shc_work@mail.ru> */ #include <common.h> #include <malloc.h> @@ -54,7 +46,7 @@ static int clps711x_setbaudrate(struct console_device *cdev, int baudrate) int divisor; u32 tmp; - divisor = (clk_get_rate(s->uart_clk) / 16) / baudrate; + divisor = DIV_ROUND_CLOSEST(clk_get_rate(s->uart_clk), baudrate * 16); tmp = readl(s->base + UBRLCR) & ~UBRLCR_BAUD_MASK; tmp |= divisor - 1; @@ -132,6 +124,7 @@ static int clps711x_probe(struct device_d *dev) struct clps711x_uart *s; int err, id = dev->id; char syscon_dev[8]; + const char *devname; if (dev->device_node) id = of_alias_get_id(dev->device_node, "serial"); @@ -170,6 +163,14 @@ static int clps711x_probe(struct device_d *dev) s->cdev.getc = clps711x_getc; s->cdev.flush = clps711x_flush; s->cdev.setbrg = clps711x_setbaudrate; + s->cdev.linux_console_name = "ttyCL"; + + devname = of_alias_get(dev->device_node); + if (devname) { + s->cdev.devname = xstrdup(devname); + s->cdev.devid = DEVICE_ID_SINGLE; + } + clps711x_init_port(&s->cdev); err = console_register(&s->cdev); @@ -182,7 +183,7 @@ out_err: } static struct of_device_id __maybe_unused clps711x_uart_dt_ids[] = { - { .compatible = "cirrus,clps711x-uart", }, + { .compatible = "cirrus,ep7209-uart", }, }; static struct driver_d clps711x_driver = { diff --git a/drivers/spi/imx_spi.c b/drivers/spi/imx_spi.c index 10621d00c8..46e8955abb 100644 --- a/drivers/spi/imx_spi.c +++ b/drivers/spi/imx_spi.c @@ -605,17 +605,20 @@ static int imx_spi_probe(struct device_d *dev) master = &imx->master; master->dev = dev; - master->bus_num = dev->id; master->setup = imx_spi_setup; master->transfer = imx_spi_transfer; if (pdata) { + master->bus_num = dev->id; master->num_chipselect = pdata->num_chipselect; imx->cs_array = pdata->chipselect; - } else { - if (IS_ENABLED(CONFIG_OFDEVICE)) - imx_spi_dt_probe(imx); + } else if (IS_ENABLED(CONFIG_OFDEVICE)) { + ret = of_alias_get_id(dev->device_node, "spi"); + if (ret < 0) + goto err_free; + master->bus_num = ret; + imx_spi_dt_probe(imx); } imx->clk = clk_get(dev, NULL); diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c index d7bf92cdff..c2b3d481af 100644 --- a/drivers/usb/gadget/dfu.c +++ b/drivers/usb/gadget/dfu.c @@ -489,7 +489,6 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) value = handle_dnload(f, ctrl); dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE; return 0; - break; case USB_REQ_DFU_UPLOAD: dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE; debug("dfu: starting upload from %s\n", dfu_file_entry->filename); @@ -505,7 +504,6 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) } handle_upload(f, ctrl); return 0; - break; case USB_REQ_DFU_ABORT: dfu->dfu_status = DFU_STATUS_OK; value = 0; @@ -517,7 +515,6 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) default: dfu->dfu_state = DFU_STATE_dfuERROR; value = -EINVAL; - goto out; break; } break; @@ -544,7 +541,6 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) case USB_REQ_DFU_UPLOAD: handle_upload(f, ctrl); return 0; - break; case USB_REQ_DFU_ABORT: dfu_abort(dfu); value = 0; @@ -574,7 +570,6 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) case DFU_STATE_dfuMANIFEST: dfu->dfu_state = DFU_STATE_dfuERROR; value = -EINVAL; - goto out; break; default: break; diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index d61920e42d..bdf0c807df 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -80,6 +80,7 @@ struct f_fastboot { const char *filename, const void *buf, size_t len); int download_fd; void *buf; + bool active; size_t download_bytes; size_t download_size; @@ -182,15 +183,8 @@ static struct usb_gadget_strings *fastboot_strings[] = { static void rx_handler_command(struct usb_ep *ep, struct usb_request *req); -static int in_req_complete; - static void fastboot_complete(struct usb_ep *ep, struct usb_request *req) { - int status = req->status; - - in_req_complete = 1; - - pr_debug("status: %d ep '%s' trans: %d\n", status, ep->name, req->actual); } static struct usb_request *fastboot_alloc_request(struct usb_ep *ep) @@ -404,7 +398,6 @@ static int fastboot_bind(struct usb_configuration *c, struct usb_function *f) return ret; } f_fb->in_req->complete = fastboot_complete; - f_fb->out_req->context = f_fb; ret = usb_assign_descriptors(f, fb_fs_descs, fb_hs_descs, NULL); if (ret) @@ -434,6 +427,8 @@ static void fastboot_unbind(struct usb_configuration *c, struct usb_function *f) list_del(&var->list); free(var); } + + f_fb->active = false; } static void fastboot_disable(struct usb_function *f) @@ -486,13 +481,36 @@ err: return ret; } +static struct f_fastboot *g_f_fb; + static void fastboot_free_func(struct usb_function *f) { struct f_fastboot *f_fb = container_of(f, struct f_fastboot, func); + if (g_f_fb == f_fb) + g_f_fb = NULL; + free(f_fb); } +/* + * A "oem exec bootm" or similar commands will stop barebox. Tell the + * fastboot command on the other side so that it doesn't run into a + * timeout. + */ +static void fastboot_shutdown(void) +{ + struct f_fastboot *f_fb = g_f_fb; + + if (!f_fb || !f_fb->active) + return; + + fastboot_tx_print(f_fb, FASTBOOT_MSG_INFO, "barebox shutting down"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_OKAY, ""); +} + +early_exitcall(fastboot_shutdown); + static struct usb_function *fastboot_alloc_func(struct usb_function_instance *fi) { struct f_fastboot *f_fb; @@ -509,6 +527,9 @@ static struct usb_function *fastboot_alloc_func(struct usb_function_instance *fi f_fb->func.unbind = fastboot_unbind; f_fb->func.free_func = fastboot_free_func; + if (!g_f_fb) + g_f_fb = f_fb; + return &f_fb->func; } @@ -540,30 +561,62 @@ static int fastboot_tx_write(struct f_fastboot *f_fb, const char *buffer, unsign memcpy(in_req->buf, buffer, buffer_size); in_req->length = buffer_size; - in_req_complete = 0; + ret = usb_ep_queue(f_fb->in_ep, in_req); if (ret) pr_err("Error %d on queue\n", ret); start = get_time_ns(); - while (!in_req_complete) { + while (in_req->status == -EINPROGRESS) { if (is_timeout(start, 2 * SECOND)) return -ETIMEDOUT; usb_gadget_poll(); } + if (in_req->status) + pr_err("Failed to send answer: %d\n", in_req->status); + return 0; } -int fastboot_tx_print(struct f_fastboot *f_fb, const char *fmt, ...) +static char *fastboot_msg[] = { + [FASTBOOT_MSG_OKAY] = "OKAY", + [FASTBOOT_MSG_FAIL] = "FAIL", + [FASTBOOT_MSG_INFO] = "INFO", + [FASTBOOT_MSG_DATA] = "DATA", +}; + +int fastboot_tx_print(struct f_fastboot *f_fb, enum fastboot_msg_type type, + const char *fmt, ...) { + struct va_format vaf; char buf[64]; va_list ap; int n; + const char *msg = fastboot_msg[type]; va_start(ap, fmt); - n = vsnprintf(buf, 64, fmt, ap); + vaf.fmt = fmt; + vaf.va = ≈ + + n = snprintf(buf, 64, "%s%pV", msg, &vaf); + + switch (type) { + case FASTBOOT_MSG_OKAY: + f_fb->active = false; + break; + case FASTBOOT_MSG_FAIL: + f_fb->active = false; + pr_err("%pV\n", &vaf); + break; + case FASTBOOT_MSG_INFO: + pr_info("%pV\n", &vaf); + break; + case FASTBOOT_MSG_DATA: + break; + } + va_end(ap); if (n > 64) @@ -572,15 +625,9 @@ int fastboot_tx_print(struct f_fastboot *f_fb, const char *fmt, ...) return fastboot_tx_write(f_fb, buf, n); } -static void compl_do_reset(struct usb_ep *ep, struct usb_request *req) -{ - restart_machine(); -} - static void cb_reboot(struct f_fastboot *f_fb, const char *cmd) { - f_fb->in_req->complete = compl_do_reset; - fastboot_tx_print(f_fb, "OKAY"); + restart_machine(); } static int strcmp_l1(const char *s1, const char *s2) @@ -598,20 +645,21 @@ static void cb_getvar(struct f_fastboot *f_fb, const char *cmd) if (!strcmp_l1(cmd, "all")) { list_for_each_entry(var, &f_fb->variables, list) { - fastboot_tx_print(f_fb, "INFO%s: %s", var->name, var->value); + fastboot_tx_print(f_fb, FASTBOOT_MSG_INFO, "%s: %s", + var->name, var->value); } - fastboot_tx_print(f_fb, "OKAY"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_OKAY, ""); return; } list_for_each_entry(var, &f_fb->variables, list) { if (!strcmp(cmd, var->name)) { - fastboot_tx_print(f_fb, "OKAY%s", var->value); + fastboot_tx_print(f_fb, FASTBOOT_MSG_OKAY, var->value); return; } } - fastboot_tx_print(f_fb, "OKAY"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_OKAY, ""); } static int rx_bytes_expected(struct f_fastboot *f_fb) @@ -640,7 +688,7 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) } else { ret = write(f_fb->download_fd, buffer, req->actual); if (ret < 0) { - fastboot_tx_print(f_fb, "FAIL%s", strerror(-ret)); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, strerror(-ret)); return; } } @@ -657,12 +705,12 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) req->length = EP_BUFFER_SIZE; close(f_fb->download_fd); - fastboot_tx_print(f_fb, "INFODownloading %d bytes finished", - f_fb->download_bytes); + printf("\n"); - fastboot_tx_print(f_fb, "OKAY"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_INFO, "Downloading %d bytes finished", + f_fb->download_bytes); - printf("\n"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_OKAY, ""); } req->actual = 0; @@ -674,7 +722,8 @@ static void cb_download(struct f_fastboot *f_fb, const char *cmd) f_fb->download_size = simple_strtoul(cmd, NULL, 16); f_fb->download_bytes = 0; - fastboot_tx_print(f_fb, "INFODownloading %d bytes...", f_fb->download_size); + fastboot_tx_print(f_fb, FASTBOOT_MSG_INFO, "Downloading %d bytes...", + f_fb->download_size); init_progression_bar(f_fb->download_size); @@ -682,28 +731,32 @@ static void cb_download(struct f_fastboot *f_fb, const char *cmd) free(f_fb->buf); f_fb->buf = malloc(f_fb->download_size); if (!f_fb->buf) { - fastboot_tx_print(f_fb, "FAILnot enough memory"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "not enough memory"); return; } } else { f_fb->download_fd = open(FASTBOOT_TMPFILE, O_WRONLY | O_CREAT | O_TRUNC); if (f_fb->download_fd < 0) { - fastboot_tx_print(f_fb, "FAILInternal Error"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "internal error"); return; } } if (!f_fb->download_size) { - fastboot_tx_print(f_fb, "FAILdata invalid size"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "data invalid size"); } else { struct usb_request *req = f_fb->out_req; - fastboot_tx_print(f_fb, "DATA%08x", f_fb->download_size); + fastboot_tx_print(f_fb, FASTBOOT_MSG_DATA, + "%08x", f_fb->download_size); req->complete = rx_handler_dl_image; req->length = rx_bytes_expected(f_fb); } } -static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req) +static void __maybe_unused cb_boot(struct f_fastboot *f_fb, const char *opt) { int ret; struct bootm_data data = { @@ -711,7 +764,7 @@ static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req) .os_address = UIMAGE_SOME_ADDRESS, }; - pr_info("Booting kernel..\n"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_INFO, "Booting kernel..\n"); globalvar_set_match("linux.bootargs.dyn.", ""); globalvar_set_match("bootm.", ""); @@ -719,14 +772,12 @@ static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req) data.os_file = xstrdup(FASTBOOT_TMPFILE); ret = bootm_boot(&data); - if (ret) - pr_err("Booting failed\n"); -} -static void __maybe_unused cb_boot(struct f_fastboot *f_fb, const char *opt) -{ - f_fb->in_req->complete = do_bootm_on_complete; - fastboot_tx_print(f_fb, "OKAY"); + if (ret) + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, "Booting failed: %s", + strerror(-ret)); + else + fastboot_tx_print(f_fb, FASTBOOT_MSG_OKAY, ""); } static struct mtd_info *get_mtd(struct f_fastboot *f_fb, const char *filename) @@ -762,7 +813,8 @@ static int do_ubiformat(struct f_fastboot *f_fb, struct mtd_info *mtd, args.novtbl = 1; if (!IS_ENABLED(CONFIG_UBIFORMAT)) { - fastboot_tx_print(f_fb, "FAILubiformat is not available"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "ubiformat is not available"); return -ENODEV; } @@ -784,31 +836,37 @@ static int check_ubi(struct f_fastboot *f_fb, struct file_list_entry *fentry, */ if (!IS_ERR(mtd) && filetype == filetype_ubi && !(fentry->flags & FILE_LIST_FLAG_UBI)) { - fastboot_tx_print(f_fb, "INFOwriting UBI image to MTD device, " - "add the 'u' "); - fastboot_tx_print(f_fb, "INFOflag to the partition description"); - return 0; + fastboot_tx_print(f_fb, FASTBOOT_MSG_INFO, + "writing UBI image to MTD device, " + "add the 'u' "); + fastboot_tx_print(f_fb, FASTBOOT_MSG_INFO, + "flag to the partition description"); + return 0; } if (!(fentry->flags & FILE_LIST_FLAG_UBI)) return 0; if (!IS_ENABLED(CONFIG_UBIFORMAT)) { - fastboot_tx_print(f_fb, "FAILformat not available"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "ubiformat not available"); return -ENOSYS; } if (IS_ERR(mtd)) { - fastboot_tx_print(f_fb, "FAILUBI flag given on non-MTD device"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "UBI flag given on non-MTD device"); return -EINVAL; } if (filetype == filetype_ubi) { - fastboot_tx_print(f_fb, "INFOThis is an UBI image..."); + fastboot_tx_print(f_fb, FASTBOOT_MSG_INFO, + "This is an UBI image..."); return 1; } else { - fastboot_tx_print(f_fb, "FAILThis is no UBI image but %s", - file_type_to_string(filetype)); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "This is no UBI image but %s", + file_type_to_string(filetype)); return -EINVAL; } } @@ -937,12 +995,14 @@ static void cb_flash(struct f_fastboot *f_fb, const char *cmd) filetype = file_name_detect_type(FASTBOOT_TMPFILE); } - fastboot_tx_print(f_fb, "INFOCopying file to %s...", cmd); + fastboot_tx_print(f_fb, FASTBOOT_MSG_INFO, "Copying file to %s...", + cmd); fentry = file_list_entry_by_name(f_fb->files, cmd); if (!fentry) { - fastboot_tx_print(f_fb, "FAILNo such partition: %s", cmd); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, "No such partition: %s", + cmd); ret = -ENOENT; goto out; } @@ -957,20 +1017,18 @@ static void cb_flash(struct f_fastboot *f_fb, const char *cmd) filename = fentry->filename; if (filetype == filetype_android_sparse) { - if (!IS_ENABLED(CONFIG_USB_GADGET_FASTBOOT_SPARSE)) { - fastboot_tx_print(f_fb, "FAILsparse image not supported"); + if (!IS_ENABLED(CONFIG_USB_GADGET_FASTBOOT_SPARSE) || + fastboot_download_to_buf(f_fb)) { + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "sparse image not supported"); ret = -EOPNOTSUPP; goto out; } - if (fastboot_download_to_buf(f_fb)) { - fastboot_tx_print(f_fb, "FAILsparse image not supported"); - goto out; - } - ret = fastboot_handle_sparse(f_fb, fentry); if (ret) - fastboot_tx_print(f_fb, "FAILwriting sparse image: %s", + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "writing sparse image: %s", strerror(-ret)); goto out; @@ -988,7 +1046,9 @@ static void cb_flash(struct f_fastboot *f_fb, const char *cmd) ret = do_ubiformat(f_fb, mtd, sourcefile, f_fb->buf, f_fb->download_size); if (ret) { - fastboot_tx_print(f_fb, "FAILwrite partition: %s", strerror(-ret)); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "write partition: %s", + strerror(-ret)); goto out; } @@ -1006,7 +1066,8 @@ static void cb_flash(struct f_fastboot *f_fb, const char *cmd) if (!handler) goto copy; - fastboot_tx_print(f_fb, "INFOThis is a barebox image..."); + fastboot_tx_print(f_fb, FASTBOOT_MSG_INFO, + "This is a barebox image..."); if (fastboot_download_to_buf(f_fb)) { data.len = f_fb->download_size; @@ -1014,7 +1075,8 @@ static void cb_flash(struct f_fastboot *f_fb, const char *cmd) ret = read_file_2(sourcefile, &data.len, &f_fb->buf, f_fb->download_size); if (ret) { - fastboot_tx_print(f_fb, "FAILreading barebox"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "reading barebox"); goto out; } } @@ -1025,7 +1087,8 @@ static void cb_flash(struct f_fastboot *f_fb, const char *cmd) ret = barebox_update(&data, handler); if (ret) - fastboot_tx_print(f_fb, "FAILupdate barebox: %s", strerror(-ret)); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "update barebox: %s", strerror(-ret)); goto out; } @@ -1037,11 +1100,12 @@ copy: ret = copy_file(FASTBOOT_TMPFILE, filename, 1); if (ret) - fastboot_tx_print(f_fb, "FAILwrite partition: %s", strerror(-ret)); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "write partition: %s", strerror(-ret)); out: if (!ret) - fastboot_tx_print(f_fb, "OKAY"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_OKAY, ""); free(f_fb->buf); f_fb->buf = NULL; @@ -1057,7 +1121,7 @@ static void cb_erase(struct f_fastboot *f_fb, const char *cmd) const char *filename = NULL; int fd; - fastboot_tx_print(f_fb, "INFOErasing %s...", cmd); + fastboot_tx_print(f_fb, FASTBOOT_MSG_INFO, "Erasing %s...", cmd); file_list_for_each_entry(f_fb->files, fentry) { if (!strcmp(cmd, fentry->name)) { @@ -1067,23 +1131,25 @@ static void cb_erase(struct f_fastboot *f_fb, const char *cmd) } if (!filename) { - fastboot_tx_print(f_fb, "FAILNo such partition: %s", cmd); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "No such partition: %s", cmd); return; } fd = open(filename, O_RDWR); if (fd < 0) - fastboot_tx_print(f_fb, "FAIL%s", strerror(-fd)); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, strerror(-fd)); ret = erase(fd, ERASE_SIZE_ALL, 0); close(fd); if (ret) - fastboot_tx_print(f_fb, "FAILcannot erase partition %s: %s", - filename, strerror(-ret)); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "cannot erase partition %s: %s", + filename, strerror(-ret)); else - fastboot_tx_print(f_fb, "OKAY"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_OKAY, ""); } struct cmd_dispatch_info { @@ -1109,7 +1175,8 @@ static void fb_run_command(struct f_fastboot *f_fb, const char *cmdbuf, } } - fastboot_tx_print(f_fb, "FAILunknown command %s", cmdbuf); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, "unknown command %s", + cmdbuf); } static void cb_oem_getenv(struct f_fastboot *f_fb, const char *cmd) @@ -1120,8 +1187,8 @@ static void cb_oem_getenv(struct f_fastboot *f_fb, const char *cmd) value = getenv(cmd); - fastboot_tx_print(f_fb, "INFO%s", value ? value : ""); - fastboot_tx_print(f_fb, "OKAY"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_INFO, value ? value : ""); + fastboot_tx_print(f_fb, FASTBOOT_MSG_OKAY, ""); } static void cb_oem_setenv(struct f_fastboot *f_fb, const char *cmd) @@ -1144,12 +1211,12 @@ static void cb_oem_setenv(struct f_fastboot *f_fb, const char *cmd) if (ret) goto out; - fastboot_tx_print(f_fb, "OKAY"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_OKAY, ""); out: free(var); if (ret) - fastboot_tx_print(f_fb, "FAIL%s", strerror(-ret)); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, strerror(-ret)); } static void cb_oem_exec(struct f_fastboot *f_fb, const char *cmd) @@ -1157,17 +1224,18 @@ static void cb_oem_exec(struct f_fastboot *f_fb, const char *cmd) int ret; if (!IS_ENABLED(CONFIG_COMMAND_SUPPORT)) { - fastboot_tx_print(f_fb, "FAILno command support available"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, + "no command support available"); return; } ret = run_command(cmd); if (ret < 0) - fastboot_tx_print(f_fb, "FAIL%s", strerror(-ret)); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, strerror(-ret)); else if (ret > 0) - fastboot_tx_print(f_fb, "FAIL"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, ""); else - fastboot_tx_print(f_fb, "OKAY"); + fastboot_tx_print(f_fb, FASTBOOT_MSG_OKAY, ""); } static const struct cmd_dispatch_info cmd_oem_dispatch_info[] = { @@ -1226,6 +1294,8 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) if (req->status != 0) return; + f_fb->active = true; + *(cmdbuf + req->actual) = 0; if (f_fb->cmd_exec) { diff --git a/drivers/video/mtl017.c b/drivers/video/mtl017.c index 085ea110ba..c04875cd07 100644 --- a/drivers/video/mtl017.c +++ b/drivers/video/mtl017.c @@ -244,6 +244,9 @@ static int mtl017_probe(struct device_d *dev) mtl017->client = to_i2c_client(dev); mtl017->regulator = regulator_get(dev, "vdd"); + if (IS_ERR(mtl017->regulator)) + mtl017->regulator = NULL; + mtl017->enable_gpio = of_get_named_gpio_flags(dev->device_node, "enable-gpios", 0, &flags); if (gpio_is_valid(mtl017->enable_gpio)) { @@ -265,8 +268,8 @@ static int mtl017_probe(struct device_d *dev) return 0; } -static struct driver_d twl_driver = { +static struct driver_d mtl_driver = { .name = "mtl017", .probe = mtl017_probe, }; -device_i2c_driver(twl_driver); +device_i2c_driver(mtl_driver); diff --git a/drivers/video/rave-sp-backlight.c b/drivers/video/rave-sp-backlight.c index 3a20def661..877a5feeb6 100644 --- a/drivers/video/rave-sp-backlight.c +++ b/drivers/video/rave-sp-backlight.c @@ -47,7 +47,7 @@ static int rave_sp_backlight_probe(struct device_d *dev) bd = xzalloc(sizeof(*bd)); bd->dev.priv = dev->parent->priv; bd->dev.parent = dev; - bd->brightness_default = 50; + bd->brightness = bd->brightness_cur = bd->brightness_default = 50; bd->brightness_max = 100; bd->brightness_set = rave_sp_backlight_set; diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 694ffa853e..f74046c0b7 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -456,7 +456,7 @@ int w1_driver_register(struct w1_driver *drv) return register_driver(&drv->drv); } -void w1_found(struct w1_bus *bus, u64 rn) +static void w1_found(struct w1_bus *bus, u64 rn) { struct w1_device *dev; u64 tmp = be64_to_cpu(rn); |