diff options
Diffstat (limited to 'drivers')
-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 |
9 files changed, 170 insertions, 3 deletions
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 |