diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2015-04-13 12:57:13 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2015-04-13 12:57:13 +0200 |
commit | 9c4cf7d3b6b4ca24b3ebd6e003d3032a90af44b0 (patch) | |
tree | 67b5ff0cde85ca0b79bb3b070d78b5422b1f92f8 /arch | |
parent | c41b60fe6a61942d43405709ca2c19742dd99552 (diff) | |
parent | f929fab29c7817356c34be68671df00792fa9a30 (diff) | |
download | barebox-9c4cf7d3b6b4ca24b3ebd6e003d3032a90af44b0.tar.gz barebox-9c4cf7d3b6b4ca24b3ebd6e003d3032a90af44b0.tar.xz |
Merge branch 'for-next/pci'
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-imx/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-gate-exclusive.c | 103 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-imx6.c | 29 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk.h | 3 |
5 files changed, 137 insertions, 1 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 517beb12df..4d257a87a6 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -174,6 +174,7 @@ config ARCH_IMX6 select CPU_V7 select PINCTRL_IMX_IOMUX_V3 select COMMON_CLK_OF_PROVIDER + select HW_HAS_PCI config ARCH_IMX6SX bool diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 048cac5fb0..ae953b1bf8 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -16,7 +16,7 @@ obj-$(CONFIG_IMX_IIM) += iim.o obj-$(CONFIG_IMX_OCOTP) += ocotp.o obj-$(CONFIG_NAND_IMX) += nand.o lwl-$(CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND) += external-nand-boot.o -obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-pfd.o clk-gate2.o +obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-pfd.o clk-gate2.o clk-gate-exclusive.o obj-y += devices.o imx.o esdctl.o obj-y += boot.o obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o diff --git a/arch/arm/mach-imx/clk-gate-exclusive.c b/arch/arm/mach-imx/clk-gate-exclusive.c new file mode 100644 index 0000000000..db88db0237 --- /dev/null +++ b/arch/arm/mach-imx/clk-gate-exclusive.c @@ -0,0 +1,103 @@ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <common.h> +#include <io.h> +#include <malloc.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include "clk.h" + +/** + * struct clk_gate_exclusive - i.MX specific gate clock which is mutually + * exclusive with other gate clocks + * + * @gate: the parent class + * @exclusive_mask: mask of gate bits which are mutually exclusive to this + * gate clock + * + * The imx exclusive gate clock is a subclass of basic clk_gate + * with an addtional mask to indicate which other gate bits in the same + * register is mutually exclusive to this gate clock. + */ +struct clk_gate_exclusive { + struct clk clk; + void __iomem *reg; + int shift; + const char *parent; + u32 exclusive_mask; +}; + +static int clk_gate_exclusive_enable(struct clk *clk) +{ + struct clk_gate_exclusive *exgate = container_of(clk, + struct clk_gate_exclusive, clk); + u32 val = readl(exgate->reg); + + if (val & exgate->exclusive_mask) + return -EBUSY; + + val |= 1 << exgate->shift; + + writel(val, exgate->reg); + + return 0; +} + +static void clk_gate_exclusive_disable(struct clk *clk) +{ + struct clk_gate_exclusive *exgate = container_of(clk, + struct clk_gate_exclusive, clk); + u32 val = readl(exgate->reg); + + val &= ~(1 << exgate->shift); + + writel(val, exgate->reg); +} + +static int clk_gate_exclusive_is_enabled(struct clk *clk) +{ + struct clk_gate_exclusive *exgate = container_of(clk, + struct clk_gate_exclusive, clk); + + return readl(exgate->reg) & (1 << exgate->shift); +} + +static const struct clk_ops clk_gate_exclusive_ops = { + .enable = clk_gate_exclusive_enable, + .disable = clk_gate_exclusive_disable, + .is_enabled = clk_gate_exclusive_is_enabled, +}; + +struct clk *imx_clk_gate_exclusive(const char *name, const char *parent, + void __iomem *reg, u8 shift, u32 exclusive_mask) +{ + struct clk_gate_exclusive *exgate; + int ret; + + exgate = xzalloc(sizeof(*exgate)); + exgate->parent = parent; + exgate->clk.name = name; + exgate->clk.ops = &clk_gate_exclusive_ops; + exgate->clk.flags = CLK_SET_RATE_PARENT; + exgate->clk.parent_names = &exgate->parent; + exgate->clk.num_parents = 1; + + exgate->reg = reg; + exgate->shift = shift; + exgate->exclusive_mask = exclusive_mask; + + ret = clk_register(&exgate->clk); + if (ret) { + free(exgate); + return ERR_PTR(ret); + } + + return &exgate->clk; +} diff --git a/arch/arm/mach-imx/clk-imx6.c b/arch/arm/mach-imx/clk-imx6.c index 145b394d92..f51e559505 100644 --- a/arch/arm/mach-imx/clk-imx6.c +++ b/arch/arm/mach-imx/clk-imx6.c @@ -196,6 +196,26 @@ static const char *ipu2_di1_sels[] = { "ldb_di1_podf", }; +static const char *lvds_sels[] = { + "dummy", + "dummy", + "dummy", + "dummy", + "dummy", + "dummy", + "pll4_audio", + "pll5_video", + "pll8_mlb", + "enet_ref", + "pcie_ref_125m", + "sata_ref_100m", +}; + +static const char *pcie_axi_sels[] = { + "axi", + "ahb", +}; + static struct clk_div_table clk_enet_ref_table[] = { { .val = 0, .div = 20, }, { .val = 1, .div = 10, }, @@ -306,6 +326,12 @@ static int imx6_ccm_probe(struct device_d *dev) clks[IMX6QDL_CLK_ENET_REF] = imx_clk_divider_table("enet_ref", "pll6_enet", base + 0xe0, 0, 2, clk_enet_ref_table); + clks[IMX6QDL_CLK_LVDS1_SEL] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); + clks[IMX6QDL_CLK_LVDS2_SEL] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels)); + + clks[IMX6QDL_CLK_LVDS1_GATE] = imx_clk_gate_exclusive("lvds1_gate", "lvds1_sel", base + 0x160, 10, BIT(12)); + clks[IMX6QDL_CLK_LVDS2_GATE] = imx_clk_gate_exclusive("lvds2_gate", "lvds2_sel", base + 0x160, 11, BIT(13)); + /* name parent_name reg idx */ clks[IMX6QDL_CLK_PLL2_PFD0_352M] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0); clks[IMX6QDL_CLK_PLL2_PFD1_594M] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1); @@ -341,6 +367,7 @@ static int imx6_ccm_probe(struct device_d *dev) clks[IMX6QDL_CLK_EIM_SLOW_SEL] = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_sels, ARRAY_SIZE(eim_sels)); clks[IMX6QDL_CLK_VDO_AXI_SEL] = imx_clk_mux("vdo_axi_sel", base + 0x18, 11, 1, vdo_axi_sels, ARRAY_SIZE(vdo_axi_sels)); clks[IMX6QDL_CLK_CKO1_SEL] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels)); + clks[IMX6QDL_CLK_PCIE_AXI_SEL] = imx_clk_mux("pcie_axi_sel", base + 0x18, 10, 1, pcie_axi_sels, ARRAY_SIZE(pcie_axi_sels)); /* name reg shift width busy: reg, shift parent_names num_parents */ clks[IMX6QDL_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels)); @@ -435,6 +462,8 @@ static int imx6_ccm_probe(struct device_d *dev) clk_enable(clks[IMX6QDL_CLK_SATA_REF_100M]); clk_enable(clks[IMX6QDL_CLK_ENFC_PODF]); + clk_set_parent(clks[IMX6QDL_CLK_LVDS1_SEL], clks[IMX6QDL_CLK_SATA_REF_100M]); + return 0; } diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h index 8ec3eb5430..c8da2fa70c 100644 --- a/arch/arm/mach-imx/clk.h +++ b/arch/arm/mach-imx/clk.h @@ -92,4 +92,7 @@ static inline struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, return imx_clk_mux(name, reg, shift, width, parents, num_parents); } +struct clk *imx_clk_gate_exclusive(const char *name, const char *parent, + void __iomem *reg, u8 shift, u32 exclusive_mask); + #endif /* __IMX_CLK_H */ |