[PATCH] Add TI CDCE925 I2C controlled clock synthesizer driver
This driver supports the TI CDCE925 programmable clock synthesizer. The chip contains two PLLs with spread-spectrum clocking support and five output dividers. The driver only supports the following setup, and uses a fixed setting for the output muxes: Y1 is derived from the input clock Y2 and Y3 derive from PLL1 Y4 and Y5 derive from PLL2 Given a target output frequency, the driver will set the PLL and divider to best approximate the desired output. Signed-off-by: Mike Looijmans --- drivers/clk/Kconfig | 17 + drivers/clk/Makefile |1 + drivers/clk/clk-cdce925.c | 784 + 3 files changed, 802 insertions(+) create mode 100644 drivers/clk/clk-cdce925.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 6f56d3a..a898ef6 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -64,6 +64,23 @@ config COMMON_CLK_SI570 This driver supports Silicon Labs 570/571/598/599 programmable clock generators. +config COMMON_CLK_CDCE925 + tristate "Clock driver for TI CDCE925 devices" + depends on I2C + depends on OF + select REGMAP_I2C + help + ---help--- + This driver supports the TI CDCE925 programmable clock synthesizer. + The chip contains two PLLs with spread-spectrum clocking support and + five output dividers. The driver only supports the following setup, + and uses a fixed setting for the output muxes. + Y1 is derived from the input clock + Y2 and Y3 derive from PLL1 + Y4 and Y5 derive from PLL2 + Given a target output frequency, the driver will set the PLL and + divider to best approximate the desired output. + config COMMON_CLK_S2MPS11 tristate "Clock driver for S2MPS11/S5M8767 MFD" depends on MFD_SEC_CORE diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 5f8a287..cdd1d06 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o obj-$(CONFIG_COMMON_CLK_SI5351)+= clk-si5351.o obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o +obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o obj-$(CONFIG_ARCH_U300)+= clk-u300.o obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c new file mode 100644 index 000..e7fbe0a --- /dev/null +++ b/drivers/clk/clk-cdce925.c @@ -0,0 +1,784 @@ +/* + * Driver for TI Dual PLL CDCE925 clock synthesizer + * + * This driver always connects the Y1 to the input clock, Y2/Y3 to PLL1 + * and Y4/Y5 to PLL2. PLL frequency is set on a first-come-first-serve + * basis. Clients can directly request any frequency that the chip can + * deliver using the standard clk framework. In addition, the device can + * be configured and activated via the devicetree. + * + * Copyright (C) 2014, Topic Embedded Products + * Licenced under GPL + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* The chip has 2 PLLs which can be routed through dividers to 5 outputs. + * Model this as 2 PLL clocks which are parents to the outputs. + */ +#define NUMBER_OF_PLLS 2 +#define NUMBER_OF_OUTPUTS 5 + +#define CDCE925_REG_GLOBAL10x01 +#define CDCE925_REG_Y1SPIPDIVH 0x02 +#define CDCE925_REG_PDIVL 0x03 +#define CDCE925_REG_XCSEL 0x05 +/* PLL parameters start at 0x10, steps of 0x10 */ +#define CDCE925_OFFSET_PLL 0x10 +/* Add CDCE925_OFFSET_PLL * (pll) to these registers before sending */ +#define CDCE925_PLL_MUX_OUTPUTS0x14 +#define CDCE925_PLL_MULDIV 0x18 + +#define CDCE925_PLL_FREQUENCY_MIN 8000 +#define CDCE925_PLL_FREQUENCY_MAX 23000 +struct clk_cdce925_chip; + +struct clk_cdce925_output { + struct clk_hw hw; + struct clk_cdce925_chip *chip; + u8 index; + u16 pdiv; /* 1..127 for Y2-Y5; 1..1023 for Y1 */ +}; +#define to_clk_cdce925_output(_hw) \ + container_of(_hw, struct clk_cdce925_output, hw) + +struct clk_cdce925_pll { + struct clk_hw hw; + struct clk_cdce925_chip *chip; + u8 index; + u16 m; /* 1..511 */ + u16 n; /* 1..4095 */ +}; +#define to_clk_cdce925_pll(_hw)container_of(_hw, struct clk_cdce925_pll, hw) + +struct clk_cdce925_chip { + struct regmap *regmap; + struct i2c_client *i2c_client; + struct clk_cdce925_pll pll[NUMBER_OF_PLLS]; + struct clk_cdce925_output clk[NUMBER_OF_OUTPUTS]; +}; + +/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ + +static unsigned long cdce925_pll_calculate_rate(unsigned long parent_rate, + u16 n, u16 m) +{ + if ((!m || !n) || (m == n)) + return parent_rate; /* In bypass mode runs at same frequency
[PATCH] Add TI CDCE925 I2C controlled clock synthesizer driver
This driver supports the TI CDCE925 programmable clock synthesizer. The chip contains two PLLs with spread-spectrum clocking support and five output dividers. The driver only supports the following setup, and uses a fixed setting for the output muxes: Y1 is derived from the input clock Y2 and Y3 derive from PLL1 Y4 and Y5 derive from PLL2 Given a target output frequency, the driver will set the PLL and divider to best approximate the desired output. Signed-off-by: Mike Looijmans mike.looijm...@topic.nl --- drivers/clk/Kconfig | 17 + drivers/clk/Makefile |1 + drivers/clk/clk-cdce925.c | 784 + 3 files changed, 802 insertions(+) create mode 100644 drivers/clk/clk-cdce925.c diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 6f56d3a..a898ef6 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -64,6 +64,23 @@ config COMMON_CLK_SI570 This driver supports Silicon Labs 570/571/598/599 programmable clock generators. +config COMMON_CLK_CDCE925 + tristate Clock driver for TI CDCE925 devices + depends on I2C + depends on OF + select REGMAP_I2C + help + ---help--- + This driver supports the TI CDCE925 programmable clock synthesizer. + The chip contains two PLLs with spread-spectrum clocking support and + five output dividers. The driver only supports the following setup, + and uses a fixed setting for the output muxes. + Y1 is derived from the input clock + Y2 and Y3 derive from PLL1 + Y4 and Y5 derive from PLL2 + Given a target output frequency, the driver will set the PLL and + divider to best approximate the desired output. + config COMMON_CLK_S2MPS11 tristate Clock driver for S2MPS11/S5M8767 MFD depends on MFD_SEC_CORE diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 5f8a287..cdd1d06 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o obj-$(CONFIG_COMMON_CLK_SI5351)+= clk-si5351.o obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o +obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o obj-$(CONFIG_ARCH_U300)+= clk-u300.o obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c new file mode 100644 index 000..e7fbe0a --- /dev/null +++ b/drivers/clk/clk-cdce925.c @@ -0,0 +1,784 @@ +/* + * Driver for TI Dual PLL CDCE925 clock synthesizer + * + * This driver always connects the Y1 to the input clock, Y2/Y3 to PLL1 + * and Y4/Y5 to PLL2. PLL frequency is set on a first-come-first-serve + * basis. Clients can directly request any frequency that the chip can + * deliver using the standard clk framework. In addition, the device can + * be configured and activated via the devicetree. + * + * Copyright (C) 2014, Topic Embedded Products + * Licenced under GPL + */ +#include linux/clk-provider.h +#include linux/clk-private.h +#include linux/delay.h +#include linux/module.h +#include linux/i2c.h +#include linux/regmap.h +#include linux/slab.h +#include linux/gcd.h + +/* The chip has 2 PLLs which can be routed through dividers to 5 outputs. + * Model this as 2 PLL clocks which are parents to the outputs. + */ +#define NUMBER_OF_PLLS 2 +#define NUMBER_OF_OUTPUTS 5 + +#define CDCE925_REG_GLOBAL10x01 +#define CDCE925_REG_Y1SPIPDIVH 0x02 +#define CDCE925_REG_PDIVL 0x03 +#define CDCE925_REG_XCSEL 0x05 +/* PLL parameters start at 0x10, steps of 0x10 */ +#define CDCE925_OFFSET_PLL 0x10 +/* Add CDCE925_OFFSET_PLL * (pll) to these registers before sending */ +#define CDCE925_PLL_MUX_OUTPUTS0x14 +#define CDCE925_PLL_MULDIV 0x18 + +#define CDCE925_PLL_FREQUENCY_MIN 8000 +#define CDCE925_PLL_FREQUENCY_MAX 23000 +struct clk_cdce925_chip; + +struct clk_cdce925_output { + struct clk_hw hw; + struct clk_cdce925_chip *chip; + u8 index; + u16 pdiv; /* 1..127 for Y2-Y5; 1..1023 for Y1 */ +}; +#define to_clk_cdce925_output(_hw) \ + container_of(_hw, struct clk_cdce925_output, hw) + +struct clk_cdce925_pll { + struct clk_hw hw; + struct clk_cdce925_chip *chip; + u8 index; + u16 m; /* 1..511 */ + u16 n; /* 1..4095 */ +}; +#define to_clk_cdce925_pll(_hw)container_of(_hw, struct clk_cdce925_pll, hw) + +struct clk_cdce925_chip { + struct regmap *regmap; + struct i2c_client *i2c_client; + struct clk_cdce925_pll pll[NUMBER_OF_PLLS]; + struct clk_cdce925_output clk[NUMBER_OF_OUTPUTS]; +}; + +/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ + +static unsigned long cdce925_pll_calculate_rate(unsigned long parent_rate, +