From 3164f3c68941a1665090bca903d56754ac36f89d Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Mon, 16 May 2016 11:47:25 +0530 Subject: [PATCH] ARM: AM33xx: Add support for Clock Synthesizer The CDCE913 and CDCEL913 devices are modular PLL-based, low cost, high performance , programmable clock synthesizers. They generate upto 3 output clocks from a single input frequency. Each output can be programmed for any clock-frequency. Adding support for the same. Reviewed-by: Tom Rini Signed-off-by: Lokesh Vutla --- arch/arm/cpu/armv7/am33xx/Makefile | 2 + arch/arm/cpu/armv7/am33xx/clk_synthesizer.c | 104 ++++++++++++++++++ .../include/asm/arch-am33xx/clk_synthesizer.h | 43 ++++++++ 3 files changed, 149 insertions(+) create mode 100644 arch/arm/cpu/armv7/am33xx/clk_synthesizer.c create mode 100644 arch/arm/include/asm/arch-am33xx/clk_synthesizer.h diff --git a/arch/arm/cpu/armv7/am33xx/Makefile b/arch/arm/cpu/armv7/am33xx/Makefile index aae3f096b2..6fda4825fc 100644 --- a/arch/arm/cpu/armv7/am33xx/Makefile +++ b/arch/arm/cpu/armv7/am33xx/Makefile @@ -18,3 +18,5 @@ obj-y += ddr.o obj-y += emif4.o obj-y += board.o obj-y += mux.o + +obj-$(CONFIG_CLOCK_SYNTHESIZER) += clk_synthesizer.o diff --git a/arch/arm/cpu/armv7/am33xx/clk_synthesizer.c b/arch/arm/cpu/armv7/am33xx/clk_synthesizer.c new file mode 100644 index 0000000000..316e677c65 --- /dev/null +++ b/arch/arm/cpu/armv7/am33xx/clk_synthesizer.c @@ -0,0 +1,104 @@ +/* + * clk-synthesizer.c + * + * Clock synthesizer apis + * + * Copyright (C) 2016, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + +#include +#include +#include + +/** + * clk_synthesizer_reg_read - Read register from synthesizer. + * @addr: addr within the i2c device + * buf: Buffer to which value is to be read. + * + * For reading the register from this clock synthesizer, a command needs to + * be send along with enabling byte read more, and then read can happen. + * Returns 0 on success + */ +static int clk_synthesizer_reg_read(int addr, uint8_t *buf) +{ + int rc; + + /* Enable Bye read */ + addr = addr | CLK_SYNTHESIZER_BYTE_MODE; + + /* Send the command byte */ + rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1); + if (rc) + printf("Failed to send command to clock synthesizer\n"); + + /* Read the Data */ + return i2c_read(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, buf, 1); +} + +/** + * clk_synthesizer_reg_write - Write a value to register in synthesizer. + * @addr: addr within the i2c device + * val: Value to be written in the addr. + * + * Enable the byte read mode in the address and start the i2c transfer. + * Returns 0 on success + */ +static int clk_synthesizer_reg_write(int addr, uint8_t val) +{ + uint8_t cmd[2]; + int rc = 0; + + /* Enable byte write */ + cmd[0] = addr | CLK_SYNTHESIZER_BYTE_MODE; + cmd[1] = val; + + rc = i2c_write(CLK_SYNTHESIZER_I2C_ADDR, addr, 1, cmd, 2); + if (rc) + printf("Clock synthesizer reg write failed at addr = 0x%x\n", + addr); + return rc; +} + +/** + * setup_clock_syntherizer - Program the clock synthesizer to get the desired + * frequency. + * @data: Data containing the desired output + * + * This is a PLL-based high performance synthesizer which gives 3 outputs + * as per the PLL_DIV and load capacitor programmed. + */ +int setup_clock_synthesizer(struct clk_synth *data) +{ + int rc; + uint8_t val; + + rc = i2c_probe(CLK_SYNTHESIZER_I2C_ADDR); + if (rc) { + printf("i2c probe failed at address 0x%x\n", + CLK_SYNTHESIZER_I2C_ADDR); + return rc; + } + + rc = clk_synthesizer_reg_read(CLK_SYNTHESIZER_ID_REG, &val); + if (val != data->id) + return rc; + + /* Crystal Load capacitor selection */ + rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_XCSEL, data->capacitor); + if (rc) + return rc; + rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_MUX_REG, data->mux); + if (rc) + return rc; + rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_PDIV2_REG, data->pdiv2); + if (rc) + return rc; + rc = clk_synthesizer_reg_write(CLK_SYNTHESIZER_PDIV3_REG, data->pdiv3); + if (rc) + return rc; + + return 0; +} diff --git a/arch/arm/include/asm/arch-am33xx/clk_synthesizer.h b/arch/arm/include/asm/arch-am33xx/clk_synthesizer.h new file mode 100644 index 0000000000..a5af0120d8 --- /dev/null +++ b/arch/arm/include/asm/arch-am33xx/clk_synthesizer.h @@ -0,0 +1,43 @@ +/* + * clk-synthesizer.h + * + * Clock synthesizer header + * + * Copyright (C) 2016, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CLK_SYNTHESIZER_H +#define __CLK_SYNTHESIZER_H + +#include + +#define CLK_SYNTHESIZER_ID_REG 0x0 +#define CLK_SYNTHESIZER_XCSEL 0x05 +#define CLK_SYNTHESIZER_MUX_REG 0x14 +#define CLK_SYNTHESIZER_PDIV2_REG 0x16 +#define CLK_SYNTHESIZER_PDIV3_REG 0x17 + +#define CLK_SYNTHESIZER_BYTE_MODE 0x80 + +/** + * struct clk_synth: This structure holds data neeed for configuring + * for clock synthesizer. + * @id: The id of synthesizer + * @capacitor: value of the capacitor attached + * @mux: mux settings. + * @pdiv2: Div to be applied to second output + * @pdiv3: Div to be applied to third output + */ +struct clk_synth { + u32 id; + u32 capacitor; + u32 mux; + u32 pdiv2; + u32 pdiv3; +}; + +int setup_clock_synthesizer(struct clk_synth *data); + +#endif -- 2.25.1