|
@@ -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 <common.h>
|
|
|
+#include <asm/arch/clk_synthesizer.h>
|
|
|
+#include <i2c.h>
|
|
|
+
|
|
|
+/**
|
|
|
+ * 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;
|
|
|
+}
|