Loading Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt 0 → 100644 +77 −0 Original line number Diff line number Diff line * Samsung S3C64xx Clock Controller The S3C64xx clock controller generates and supplies clock to various controllers within the SoC. The clock binding described here is applicable to all SoCs in the S3C64xx family. Required Properties: - compatible: should be one of the following. - "samsung,s3c6400-clock" - controller compatible with S3C6400 SoC. - "samsung,s3c6410-clock" - controller compatible with S3C6410 SoC. - reg: physical base address of the controller and length of memory mapped region. - #clock-cells: should be 1. Each clock is assigned an identifier and client nodes can use this identifier to specify the clock which they consume. Some of the clocks are available only on a particular S3C64xx SoC and this is specified where applicable. All available clocks are defined as preprocessor macros in dt-bindings/clock/samsung,s3c64xx-clock.h header and can be used in device tree sources. External clocks: There are several clocks that are generated outside the SoC. It is expected that they are defined using standard clock bindings with following clock-output-names: - "fin_pll" - PLL input clock (xtal/extclk) - required, - "xusbxti" - USB xtal - required, - "iiscdclk0" - I2S0 codec clock - optional, - "iiscdclk1" - I2S1 codec clock - optional, - "iiscdclk2" - I2S2 codec clock - optional, - "pcmcdclk0" - PCM0 codec clock - optional, - "pcmcdclk1" - PCM1 codec clock - optional, only S3C6410. Example: Clock controller node: clock: clock-controller@7e00f000 { compatible = "samsung,s3c6410-clock"; reg = <0x7e00f000 0x1000>; #clock-cells = <1>; }; Example: Required external clocks: fin_pll: clock-fin-pll { compatible = "fixed-clock"; clock-output-names = "fin_pll"; clock-frequency = <12000000>; #clock-cells = <0>; }; xusbxti: clock-xusbxti { compatible = "fixed-clock"; clock-output-names = "xusbxti"; clock-frequency = <48000000>; #clock-cells = <0>; }; Example: UART controller node that consumes the clock generated by the clock controller (refer to the standard clock bindings for information about "clocks" and "clock-names" properties): uart0: serial@7f005000 { compatible = "samsung,s3c6400-uart"; reg = <0x7f005000 0x100>; interrupt-parent = <&vic1>; interrupts = <5>; clock-names = "uart", "clk_uart_baud2", "clk_uart_baud3"; clocks = <&clock PCLK_UART0>, <&clocks PCLK_UART0>, <&clock SCLK_UART>; status = "disabled"; }; drivers/clk/clk-mux.c +9 −1 Original line number Diff line number Diff line Loading @@ -107,6 +107,11 @@ const struct clk_ops clk_mux_ops = { }; EXPORT_SYMBOL_GPL(clk_mux_ops); const struct clk_ops clk_mux_ro_ops = { .get_parent = clk_mux_get_parent, }; EXPORT_SYMBOL_GPL(clk_mux_ro_ops); struct clk *clk_register_mux_table(struct device *dev, const char *name, const char **parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, Loading @@ -133,6 +138,9 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name, } init.name = name; if (clk_mux_flags & CLK_MUX_READ_ONLY) init.ops = &clk_mux_ro_ops; else init.ops = &clk_mux_ops; init.flags = flags | CLK_IS_BASIC; init.parent_names = parent_names; Loading drivers/clk/samsung/Makefile +3 −0 Original line number Diff line number Diff line Loading @@ -8,3 +8,6 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o ifdef CONFIG_COMMON_CLK obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o endif drivers/clk/samsung/clk-pll.c +160 −0 Original line number Diff line number Diff line Loading @@ -437,6 +437,166 @@ struct clk * __init samsung_clk_register_pll46xx(const char *name, return clk; } /* * PLL6552 Clock Type */ #define PLL6552_LOCK_REG 0x00 #define PLL6552_CON_REG 0x0c #define PLL6552_MDIV_MASK 0x3ff #define PLL6552_PDIV_MASK 0x3f #define PLL6552_SDIV_MASK 0x7 #define PLL6552_MDIV_SHIFT 16 #define PLL6552_PDIV_SHIFT 8 #define PLL6552_SDIV_SHIFT 0 struct samsung_clk_pll6552 { struct clk_hw hw; void __iomem *reg_base; }; #define to_clk_pll6552(_hw) container_of(_hw, struct samsung_clk_pll6552, hw) static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct samsung_clk_pll6552 *pll = to_clk_pll6552(hw); u32 mdiv, pdiv, sdiv, pll_con; u64 fvco = parent_rate; pll_con = __raw_readl(pll->reg_base + PLL6552_CON_REG); mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK; pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK; sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK; fvco *= mdiv; do_div(fvco, (pdiv << sdiv)); return (unsigned long)fvco; } static const struct clk_ops samsung_pll6552_clk_ops = { .recalc_rate = samsung_pll6552_recalc_rate, }; struct clk * __init samsung_clk_register_pll6552(const char *name, const char *pname, void __iomem *base) { struct samsung_clk_pll6552 *pll; struct clk *clk; struct clk_init_data init; pll = kzalloc(sizeof(*pll), GFP_KERNEL); if (!pll) { pr_err("%s: could not allocate pll clk %s\n", __func__, name); return NULL; } init.name = name; init.ops = &samsung_pll6552_clk_ops; init.parent_names = &pname; init.num_parents = 1; pll->hw.init = &init; pll->reg_base = base; clk = clk_register(NULL, &pll->hw); if (IS_ERR(clk)) { pr_err("%s: failed to register pll clock %s\n", __func__, name); kfree(pll); } if (clk_register_clkdev(clk, name, NULL)) pr_err("%s: failed to register lookup for %s", __func__, name); return clk; } /* * PLL6553 Clock Type */ #define PLL6553_LOCK_REG 0x00 #define PLL6553_CON0_REG 0x0c #define PLL6553_CON1_REG 0x10 #define PLL6553_MDIV_MASK 0xff #define PLL6553_PDIV_MASK 0x3f #define PLL6553_SDIV_MASK 0x7 #define PLL6553_KDIV_MASK 0xffff #define PLL6553_MDIV_SHIFT 16 #define PLL6553_PDIV_SHIFT 8 #define PLL6553_SDIV_SHIFT 0 #define PLL6553_KDIV_SHIFT 0 struct samsung_clk_pll6553 { struct clk_hw hw; void __iomem *reg_base; }; #define to_clk_pll6553(_hw) container_of(_hw, struct samsung_clk_pll6553, hw) static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct samsung_clk_pll6553 *pll = to_clk_pll6553(hw); u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1; u64 fvco = parent_rate; pll_con0 = __raw_readl(pll->reg_base + PLL6553_CON0_REG); pll_con1 = __raw_readl(pll->reg_base + PLL6553_CON1_REG); mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK; pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK; sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK; kdiv = (pll_con1 >> PLL6553_KDIV_SHIFT) & PLL6553_KDIV_MASK; fvco *= (mdiv << 16) + kdiv; do_div(fvco, (pdiv << sdiv)); fvco >>= 16; return (unsigned long)fvco; } static const struct clk_ops samsung_pll6553_clk_ops = { .recalc_rate = samsung_pll6553_recalc_rate, }; struct clk * __init samsung_clk_register_pll6553(const char *name, const char *pname, void __iomem *base) { struct samsung_clk_pll6553 *pll; struct clk *clk; struct clk_init_data init; pll = kzalloc(sizeof(*pll), GFP_KERNEL); if (!pll) { pr_err("%s: could not allocate pll clk %s\n", __func__, name); return NULL; } init.name = name; init.ops = &samsung_pll6553_clk_ops; init.parent_names = &pname; init.num_parents = 1; pll->hw.init = &init; pll->reg_base = base; clk = clk_register(NULL, &pll->hw); if (IS_ERR(clk)) { pr_err("%s: failed to register pll clock %s\n", __func__, name); kfree(pll); } if (clk_register_clkdev(clk, name, NULL)) pr_err("%s: failed to register lookup for %s", __func__, name); return clk; } /* * PLL2550x Clock Type */ Loading drivers/clk/samsung/clk-pll.h +4 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,10 @@ extern struct clk * __init samsung_clk_register_pll45xx(const char *name, extern struct clk * __init samsung_clk_register_pll46xx(const char *name, const char *pname, const void __iomem *con_reg, enum pll46xx_type type); extern struct clk *samsung_clk_register_pll6552(const char *name, const char *pname, void __iomem *base); extern struct clk *samsung_clk_register_pll6553(const char *name, const char *pname, void __iomem *base); extern struct clk * __init samsung_clk_register_pll2550x(const char *name, const char *pname, const void __iomem *reg_base, const unsigned long offset); Loading Loading
Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt 0 → 100644 +77 −0 Original line number Diff line number Diff line * Samsung S3C64xx Clock Controller The S3C64xx clock controller generates and supplies clock to various controllers within the SoC. The clock binding described here is applicable to all SoCs in the S3C64xx family. Required Properties: - compatible: should be one of the following. - "samsung,s3c6400-clock" - controller compatible with S3C6400 SoC. - "samsung,s3c6410-clock" - controller compatible with S3C6410 SoC. - reg: physical base address of the controller and length of memory mapped region. - #clock-cells: should be 1. Each clock is assigned an identifier and client nodes can use this identifier to specify the clock which they consume. Some of the clocks are available only on a particular S3C64xx SoC and this is specified where applicable. All available clocks are defined as preprocessor macros in dt-bindings/clock/samsung,s3c64xx-clock.h header and can be used in device tree sources. External clocks: There are several clocks that are generated outside the SoC. It is expected that they are defined using standard clock bindings with following clock-output-names: - "fin_pll" - PLL input clock (xtal/extclk) - required, - "xusbxti" - USB xtal - required, - "iiscdclk0" - I2S0 codec clock - optional, - "iiscdclk1" - I2S1 codec clock - optional, - "iiscdclk2" - I2S2 codec clock - optional, - "pcmcdclk0" - PCM0 codec clock - optional, - "pcmcdclk1" - PCM1 codec clock - optional, only S3C6410. Example: Clock controller node: clock: clock-controller@7e00f000 { compatible = "samsung,s3c6410-clock"; reg = <0x7e00f000 0x1000>; #clock-cells = <1>; }; Example: Required external clocks: fin_pll: clock-fin-pll { compatible = "fixed-clock"; clock-output-names = "fin_pll"; clock-frequency = <12000000>; #clock-cells = <0>; }; xusbxti: clock-xusbxti { compatible = "fixed-clock"; clock-output-names = "xusbxti"; clock-frequency = <48000000>; #clock-cells = <0>; }; Example: UART controller node that consumes the clock generated by the clock controller (refer to the standard clock bindings for information about "clocks" and "clock-names" properties): uart0: serial@7f005000 { compatible = "samsung,s3c6400-uart"; reg = <0x7f005000 0x100>; interrupt-parent = <&vic1>; interrupts = <5>; clock-names = "uart", "clk_uart_baud2", "clk_uart_baud3"; clocks = <&clock PCLK_UART0>, <&clocks PCLK_UART0>, <&clock SCLK_UART>; status = "disabled"; };
drivers/clk/clk-mux.c +9 −1 Original line number Diff line number Diff line Loading @@ -107,6 +107,11 @@ const struct clk_ops clk_mux_ops = { }; EXPORT_SYMBOL_GPL(clk_mux_ops); const struct clk_ops clk_mux_ro_ops = { .get_parent = clk_mux_get_parent, }; EXPORT_SYMBOL_GPL(clk_mux_ro_ops); struct clk *clk_register_mux_table(struct device *dev, const char *name, const char **parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, Loading @@ -133,6 +138,9 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name, } init.name = name; if (clk_mux_flags & CLK_MUX_READ_ONLY) init.ops = &clk_mux_ro_ops; else init.ops = &clk_mux_ops; init.flags = flags | CLK_IS_BASIC; init.parent_names = parent_names; Loading
drivers/clk/samsung/Makefile +3 −0 Original line number Diff line number Diff line Loading @@ -8,3 +8,6 @@ obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o ifdef CONFIG_COMMON_CLK obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o endif
drivers/clk/samsung/clk-pll.c +160 −0 Original line number Diff line number Diff line Loading @@ -437,6 +437,166 @@ struct clk * __init samsung_clk_register_pll46xx(const char *name, return clk; } /* * PLL6552 Clock Type */ #define PLL6552_LOCK_REG 0x00 #define PLL6552_CON_REG 0x0c #define PLL6552_MDIV_MASK 0x3ff #define PLL6552_PDIV_MASK 0x3f #define PLL6552_SDIV_MASK 0x7 #define PLL6552_MDIV_SHIFT 16 #define PLL6552_PDIV_SHIFT 8 #define PLL6552_SDIV_SHIFT 0 struct samsung_clk_pll6552 { struct clk_hw hw; void __iomem *reg_base; }; #define to_clk_pll6552(_hw) container_of(_hw, struct samsung_clk_pll6552, hw) static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct samsung_clk_pll6552 *pll = to_clk_pll6552(hw); u32 mdiv, pdiv, sdiv, pll_con; u64 fvco = parent_rate; pll_con = __raw_readl(pll->reg_base + PLL6552_CON_REG); mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK; pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK; sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK; fvco *= mdiv; do_div(fvco, (pdiv << sdiv)); return (unsigned long)fvco; } static const struct clk_ops samsung_pll6552_clk_ops = { .recalc_rate = samsung_pll6552_recalc_rate, }; struct clk * __init samsung_clk_register_pll6552(const char *name, const char *pname, void __iomem *base) { struct samsung_clk_pll6552 *pll; struct clk *clk; struct clk_init_data init; pll = kzalloc(sizeof(*pll), GFP_KERNEL); if (!pll) { pr_err("%s: could not allocate pll clk %s\n", __func__, name); return NULL; } init.name = name; init.ops = &samsung_pll6552_clk_ops; init.parent_names = &pname; init.num_parents = 1; pll->hw.init = &init; pll->reg_base = base; clk = clk_register(NULL, &pll->hw); if (IS_ERR(clk)) { pr_err("%s: failed to register pll clock %s\n", __func__, name); kfree(pll); } if (clk_register_clkdev(clk, name, NULL)) pr_err("%s: failed to register lookup for %s", __func__, name); return clk; } /* * PLL6553 Clock Type */ #define PLL6553_LOCK_REG 0x00 #define PLL6553_CON0_REG 0x0c #define PLL6553_CON1_REG 0x10 #define PLL6553_MDIV_MASK 0xff #define PLL6553_PDIV_MASK 0x3f #define PLL6553_SDIV_MASK 0x7 #define PLL6553_KDIV_MASK 0xffff #define PLL6553_MDIV_SHIFT 16 #define PLL6553_PDIV_SHIFT 8 #define PLL6553_SDIV_SHIFT 0 #define PLL6553_KDIV_SHIFT 0 struct samsung_clk_pll6553 { struct clk_hw hw; void __iomem *reg_base; }; #define to_clk_pll6553(_hw) container_of(_hw, struct samsung_clk_pll6553, hw) static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct samsung_clk_pll6553 *pll = to_clk_pll6553(hw); u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1; u64 fvco = parent_rate; pll_con0 = __raw_readl(pll->reg_base + PLL6553_CON0_REG); pll_con1 = __raw_readl(pll->reg_base + PLL6553_CON1_REG); mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK; pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK; sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK; kdiv = (pll_con1 >> PLL6553_KDIV_SHIFT) & PLL6553_KDIV_MASK; fvco *= (mdiv << 16) + kdiv; do_div(fvco, (pdiv << sdiv)); fvco >>= 16; return (unsigned long)fvco; } static const struct clk_ops samsung_pll6553_clk_ops = { .recalc_rate = samsung_pll6553_recalc_rate, }; struct clk * __init samsung_clk_register_pll6553(const char *name, const char *pname, void __iomem *base) { struct samsung_clk_pll6553 *pll; struct clk *clk; struct clk_init_data init; pll = kzalloc(sizeof(*pll), GFP_KERNEL); if (!pll) { pr_err("%s: could not allocate pll clk %s\n", __func__, name); return NULL; } init.name = name; init.ops = &samsung_pll6553_clk_ops; init.parent_names = &pname; init.num_parents = 1; pll->hw.init = &init; pll->reg_base = base; clk = clk_register(NULL, &pll->hw); if (IS_ERR(clk)) { pr_err("%s: failed to register pll clock %s\n", __func__, name); kfree(pll); } if (clk_register_clkdev(clk, name, NULL)) pr_err("%s: failed to register lookup for %s", __func__, name); return clk; } /* * PLL2550x Clock Type */ Loading
drivers/clk/samsung/clk-pll.h +4 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,10 @@ extern struct clk * __init samsung_clk_register_pll45xx(const char *name, extern struct clk * __init samsung_clk_register_pll46xx(const char *name, const char *pname, const void __iomem *con_reg, enum pll46xx_type type); extern struct clk *samsung_clk_register_pll6552(const char *name, const char *pname, void __iomem *base); extern struct clk *samsung_clk_register_pll6553(const char *name, const char *pname, void __iomem *base); extern struct clk * __init samsung_clk_register_pll2550x(const char *name, const char *pname, const void __iomem *reg_base, const unsigned long offset); Loading