diff options
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/meson/gxbb.h | 2 | ||||
-rw-r--r-- | drivers/clk/mvebu/ap806-system-controller.c | 21 | ||||
-rw-r--r-- | drivers/clk/qcom/common.c | 2 | ||||
-rw-r--r-- | drivers/clk/sunxi-ng/Kconfig | 2 | ||||
-rw-r--r-- | drivers/clk/versatile/Kconfig | 3 | ||||
-rw-r--r-- | drivers/clk/versatile/Makefile | 2 | ||||
-rw-r--r-- | drivers/clk/versatile/clk-icst.c | 1 | ||||
-rw-r--r-- | drivers/clk/versatile/clk-icst.h | 2 | ||||
-rw-r--r-- | drivers/clk/versatile/clk-impd1.c | 1 | ||||
-rw-r--r-- | drivers/clk/versatile/clk-realview.c | 1 | ||||
-rw-r--r-- | drivers/clk/versatile/clk-versatile.c | 1 | ||||
-rw-r--r-- | drivers/clk/versatile/icst.c | 105 | ||||
-rw-r--r-- | drivers/clk/versatile/icst.h | 57 |
13 files changed, 193 insertions, 7 deletions
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h index 1d8d13f5e813..93b8f07ee7af 100644 --- a/drivers/clk/meson/gxbb.h +++ b/drivers/clk/meson/gxbb.h @@ -195,7 +195,7 @@ /* CLKID_I2C */ /* #define CLKID_SAR_ADC */ #define CLKID_SMART_CARD 24 -#define CLKID_RNG0 25 +/* CLKID_RNG0 */ #define CLKID_UART0 26 #define CLKID_SDHC 27 #define CLKID_STREAM 28 diff --git a/drivers/clk/mvebu/ap806-system-controller.c b/drivers/clk/mvebu/ap806-system-controller.c index f17702107ac5..8155baccc98e 100644 --- a/drivers/clk/mvebu/ap806-system-controller.c +++ b/drivers/clk/mvebu/ap806-system-controller.c @@ -23,7 +23,7 @@ #define AP806_SAR_REG 0x400 #define AP806_SAR_CLKFREQ_MODE_MASK 0x1f -#define AP806_CLK_NUM 4 +#define AP806_CLK_NUM 5 static struct clk *ap806_clks[AP806_CLK_NUM]; @@ -135,6 +135,23 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) goto fail3; } + /* eMMC Clock is fixed clock divided by 3 */ + if (of_property_read_string_index(np, "clock-output-names", + 4, &name)) { + ap806_clk_data.clk_num--; + dev_warn(&pdev->dev, + "eMMC clock missing: update the device tree!\n"); + } else { + ap806_clks[4] = clk_register_fixed_factor(NULL, name, + fixedclk_name, + 0, 1, 3); + if (IS_ERR(ap806_clks[4])) { + ret = PTR_ERR(ap806_clks[4]); + goto fail4; + } + } + + of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data); ret = of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data); if (ret) goto fail_clk_add; @@ -142,6 +159,8 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) return 0; fail_clk_add: + clk_unregister_fixed_factor(ap806_clks[4]); +fail4: clk_unregister_fixed_factor(ap806_clks[3]); fail3: clk_unregister_fixed_rate(ap806_clks[2]); diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index 03f9d316f969..d523991c945f 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -128,7 +128,7 @@ static void qcom_cc_gdsc_unregister(void *data) /* * Backwards compatibility with old DTs. Register a pass-through factor 1/1 - * clock to translate 'path' clk into 'name' clk and regsiter the 'path' + * clock to translate 'path' clk into 'name' clk and register the 'path' * clk as a fixed rate clock if it isn't present. */ static int _qcom_cc_register_board_clk(struct device *dev, const char *path, diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 64088e599404..b0d551a8efe4 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -16,7 +16,7 @@ config SUNXI_CCU_FRAC bool config SUNXI_CCU_GATE - bool + def_bool y config SUNXI_CCU_MUX bool diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig index a6da2aa09f83..8aa875f25239 100644 --- a/drivers/clk/versatile/Kconfig +++ b/drivers/clk/versatile/Kconfig @@ -1,3 +1,6 @@ +config ICST + bool + config COMMON_CLK_VERSATILE bool "Clock driver for ARM Reference designs" depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \ diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile index 8ff03744fe98..794130402c8d 100644 --- a/drivers/clk/versatile/Makefile +++ b/drivers/clk/versatile/Makefile @@ -1,5 +1,5 @@ # Makefile for Versatile-specific clocks -obj-$(CONFIG_ICST) += clk-icst.o clk-versatile.o +obj-$(CONFIG_ICST) += icst.o clk-icst.o clk-versatile.o obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o obj-$(CONFIG_CLK_SP810) += clk-sp810.o diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index 4faa94440779..09fbe66f1f11 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -22,6 +22,7 @@ #include <linux/regmap.h> #include <linux/mfd/syscon.h> +#include "icst.h" #include "clk-icst.h" /* Magic unlocking token used on all Versatile boards */ diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h index 04e6f0aef588..5add02ebec5d 100644 --- a/drivers/clk/versatile/clk-icst.h +++ b/drivers/clk/versatile/clk-icst.h @@ -1,5 +1,3 @@ -#include <asm/hardware/icst.h> - /** * struct clk_icst_desc - descriptor for the ICST VCO * @params: ICST parameters diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c index 74c3216dbb00..401558bfc409 100644 --- a/drivers/clk/versatile/clk-impd1.c +++ b/drivers/clk/versatile/clk-impd1.c @@ -12,6 +12,7 @@ #include <linux/io.h> #include <linux/platform_data/clk-integrator.h> +#include "icst.h" #include "clk-icst.h" #define IMPD1_OSC1 0x00 diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c index c56efc70ac16..6fdfee3232f4 100644 --- a/drivers/clk/versatile/clk-realview.c +++ b/drivers/clk/versatile/clk-realview.c @@ -11,6 +11,7 @@ #include <linux/io.h> #include <linux/clk-provider.h> +#include "icst.h" #include "clk-icst.h" #define REALVIEW_SYS_OSC0_OFFSET 0x0C diff --git a/drivers/clk/versatile/clk-versatile.c b/drivers/clk/versatile/clk-versatile.c index a89a927567e0..d6960de64d4a 100644 --- a/drivers/clk/versatile/clk-versatile.c +++ b/drivers/clk/versatile/clk-versatile.c @@ -12,6 +12,7 @@ #include <linux/of.h> #include <linux/of_address.h> +#include "icst.h" #include "clk-icst.h" #define INTEGRATOR_HDR_LOCK_OFFSET 0x14 diff --git a/drivers/clk/versatile/icst.c b/drivers/clk/versatile/icst.c new file mode 100644 index 000000000000..de2af63a3aad --- /dev/null +++ b/drivers/clk/versatile/icst.c @@ -0,0 +1,105 @@ +/* + * linux/arch/arm/common/icst307.c + * + * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. + * + * 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. + * + * Support functions for calculating clocks/divisors for the ICST307 + * clock generators. See http://www.idt.com/ for more information + * on these devices. + * + * This is an almost identical implementation to the ICST525 clock generator. + * The s2div and idx2s files are different + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/div64.h> +#include "icst.h" + +/* + * Divisors for each OD setting. + */ +const unsigned char icst307_s2div[8] = { 10, 2, 8, 4, 5, 7, 3, 6 }; +const unsigned char icst525_s2div[8] = { 10, 2, 8, 4, 5, 7, 9, 6 }; +EXPORT_SYMBOL(icst307_s2div); +EXPORT_SYMBOL(icst525_s2div); + +unsigned long icst_hz(const struct icst_params *p, struct icst_vco vco) +{ + u64 dividend = p->ref * 2 * (u64)(vco.v + 8); + u32 divisor = (vco.r + 2) * p->s2div[vco.s]; + + do_div(dividend, divisor); + return (unsigned long)dividend; +} + +EXPORT_SYMBOL(icst_hz); + +/* + * Ascending divisor S values. + */ +const unsigned char icst307_idx2s[8] = { 1, 6, 3, 4, 7, 5, 2, 0 }; +const unsigned char icst525_idx2s[8] = { 1, 3, 4, 7, 5, 2, 6, 0 }; +EXPORT_SYMBOL(icst307_idx2s); +EXPORT_SYMBOL(icst525_idx2s); + +struct icst_vco +icst_hz_to_vco(const struct icst_params *p, unsigned long freq) +{ + struct icst_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; + unsigned long f; + unsigned int i = 0, rd, best = (unsigned int)-1; + + /* + * First, find the PLL output divisor such + * that the PLL output is within spec. + */ + do { + f = freq * p->s2div[p->idx2s[i]]; + + if (f > p->vco_min && f <= p->vco_max) + break; + i++; + } while (i < 8); + + if (i >= 8) + return vco; + + vco.s = p->idx2s[i]; + + /* + * Now find the closest divisor combination + * which gives a PLL output of 'f'. + */ + for (rd = p->rd_min; rd <= p->rd_max; rd++) { + unsigned long fref_div, f_pll; + unsigned int vd; + int f_diff; + + fref_div = (2 * p->ref) / rd; + + vd = (f + fref_div / 2) / fref_div; + if (vd < p->vd_min || vd > p->vd_max) + continue; + + f_pll = fref_div * vd; + f_diff = f_pll - f; + if (f_diff < 0) + f_diff = -f_diff; + + if ((unsigned)f_diff < best) { + vco.v = vd - 8; + vco.r = rd - 2; + if (f_diff == 0) + break; + best = f_diff; + } + } + + return vco; +} + +EXPORT_SYMBOL(icst_hz_to_vco); diff --git a/drivers/clk/versatile/icst.h b/drivers/clk/versatile/icst.h new file mode 100644 index 000000000000..7519bba03b04 --- /dev/null +++ b/drivers/clk/versatile/icst.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. + * + * 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. + * + * Support functions for calculating clocks/divisors for the ICST + * clock generators. See http://www.idt.com/ for more information + * on these devices. + */ +#ifndef ICST_H +#define ICST_H + +struct icst_params { + unsigned long ref; + unsigned long vco_max; /* inclusive */ + unsigned long vco_min; /* exclusive */ + unsigned short vd_min; /* inclusive */ + unsigned short vd_max; /* inclusive */ + unsigned char rd_min; /* inclusive */ + unsigned char rd_max; /* inclusive */ + const unsigned char *s2div; /* chip specific s2div array */ + const unsigned char *idx2s; /* chip specific idx2s array */ +}; + +struct icst_vco { + unsigned short v; + unsigned char r; + unsigned char s; +}; + +unsigned long icst_hz(const struct icst_params *p, struct icst_vco vco); +struct icst_vco icst_hz_to_vco(const struct icst_params *p, unsigned long freq); + +/* + * ICST307 VCO frequency must be between 6MHz and 200MHz (3.3 or 5V). + * This frequency is pre-output divider. + */ +#define ICST307_VCO_MIN 6000000 +#define ICST307_VCO_MAX 200000000 + +extern const unsigned char icst307_s2div[]; +extern const unsigned char icst307_idx2s[]; + +/* + * ICST525 VCO frequency must be between 10MHz and 200MHz (3V) or 320MHz (5V). + * This frequency is pre-output divider. + */ +#define ICST525_VCO_MIN 10000000 +#define ICST525_VCO_MAX_3V 200000000 +#define ICST525_VCO_MAX_5V 320000000 + +extern const unsigned char icst525_s2div[]; +extern const unsigned char icst525_idx2s[]; + +#endif |