summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2015-04-02 13:00:10 -0600
committerGregory Nutt <gnutt@nuttx.org>2015-04-02 13:00:10 -0600
commit4fee67676c775475e786abb97ab10eaf5b28f453 (patch)
tree0ae46ccb1948512acc6654f37b1d3f2697805d5f
parent88837ab1dfa4ef4b8c855d14d225d836f5f9edca (diff)
downloadpx4-nuttx-4fee67676c775475e786abb97ab10eaf5b28f453.tar.gz
px4-nuttx-4fee67676c775475e786abb97ab10eaf5b28f453.tar.bz2
px4-nuttx-4fee67676c775475e786abb97ab10eaf5b28f453.zip
Add a very basic driver for the CS2100-CP Fractional-N Multipler chip.
-rw-r--r--nuttx/Documentation/NuttxPortingGuide.html2
-rw-r--r--nuttx/configs/samv71-xult/README.txt15
-rw-r--r--nuttx/drivers/timers/Kconfig20
-rw-r--r--nuttx/drivers/timers/Make.defs6
-rwxr-xr-xnuttx/drivers/timers/cs2100-cp.c836
-rw-r--r--nuttx/include/nuttx/timers/cs2100-cp.h86
-rw-r--r--nuttx/include/sys/boardctl.h2
7 files changed, 964 insertions, 3 deletions
diff --git a/nuttx/Documentation/NuttxPortingGuide.html b/nuttx/Documentation/NuttxPortingGuide.html
index 2f6c63f2c..171c4a3ce 100644
--- a/nuttx/Documentation/NuttxPortingGuide.html
+++ b/nuttx/Documentation/NuttxPortingGuide.html
@@ -3832,7 +3832,7 @@ void lpwork_restorepriority(uint8_t reqprio);
</p>
<p>
<code>boardctl()</code> is <i>non-standard</i> OS interface to alleviate the problem.
- It basically circumvents the normal device driver <code>ioctl()</code> interlace and allows the application to perform direction IOCTL-like calls to the board-specific logic.
+ It basically circumvents the normal device driver <code>ioctl()</code> interlace and allows the application to perform direct IOCTL-like calls to the board-specific logic.
It is especially useful for setting up board operational and test configurations.
</p>
<p>
diff --git a/nuttx/configs/samv71-xult/README.txt b/nuttx/configs/samv71-xult/README.txt
index d1db40806..9f3106a6e 100644
--- a/nuttx/configs/samv71-xult/README.txt
+++ b/nuttx/configs/samv71-xult/README.txt
@@ -716,6 +716,21 @@ WM8904 Audio Codec
PD26 TD DACDAT Digital audio input (headphone)
---- ------------ ------- ----------------------------------
+CP2100-CP Fractional-N Clock Multiplier
+--------------------------------------
+
+ SAMV71 Interface CP2100-CP Interface
+ ---- ------------ ------- ----------------------------------
+ PIO Usage Pin Function
+ ---- ------------ ------- ----------------------------------
+ PA3 TWD0 SDA I2C control interface, data line
+ PA4 TWCK0 SCLK I2C control interface, clock line
+ PD21 TIOA11 CLK_IN PLL input
+ - - XTI/XTO 12.0MHz crystal
+ PA22 RK CLK_OUT PLL output
+ - - AUX_OUT N/C
+ ---- ------------ ------- ----------------------------------
+
maXTouch Xplained Pro
=====================
diff --git a/nuttx/drivers/timers/Kconfig b/nuttx/drivers/timers/Kconfig
index 2502b1d8d..30ccc14b7 100644
--- a/nuttx/drivers/timers/Kconfig
+++ b/nuttx/drivers/timers/Kconfig
@@ -3,6 +3,8 @@
# see misc/tools/kconfig-language.txt.
#
+menu "Timer Driver Support"
+
menuconfig TIMER
bool "Timer Support"
default n
@@ -132,3 +134,21 @@ config WATCHDOG_DEVPATH
default "/dev/watchdog0"
endif # WATCHDOG
+
+config TIMERS_CS2100CP
+ bool "CS2100-CP Fraction-N Clock Multiplier"
+ depends on I2C
+ select I2C_TRANSFER
+
+if TIMERS_CS2100CP
+
+config CS2100CP_DEBUG
+ bool "Enable CS2100-CP Debug Features"
+ depends on DEBUG
+
+config CS2100CP_REGDEBUG
+ bool "Enable CS2100-CP Register Debug"
+ depends on DEBUG
+
+endif # TIMERS_CS2100CP
+endmenu # Timer Driver Support
diff --git a/nuttx/drivers/timers/Make.defs b/nuttx/drivers/timers/Make.defs
index a6f15133c..f70052a21 100644
--- a/nuttx/drivers/timers/Make.defs
+++ b/nuttx/drivers/timers/Make.defs
@@ -57,6 +57,12 @@ ifeq ($(CONFIG_RTC_DRIVER),y)
TMRVPATH = :timers
endif
+ifeq ($(CONFIG_TIMERS_CS2100CP),y)
+ CSRCS += cs2100-cp.c
+ TMRDEPPATH = --dep-path timers
+ TMRVPATH = :timers
+endif
+
# Include timer build support (if any were selected)
DEPPATH += $(TMRDEPPATH)
diff --git a/nuttx/drivers/timers/cs2100-cp.c b/nuttx/drivers/timers/cs2100-cp.c
new file mode 100755
index 000000000..72ee24a78
--- /dev/null
+++ b/nuttx/drivers/timers/cs2100-cp.c
@@ -0,0 +1,836 @@
+/****************************************************************************
+ * drivers/timers/cs2100-cp.c
+ *
+ * Copyright (C) 2015 Gregory Nutt. All rights reserved.
+ * Authors: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/i2c.h>
+#include <nuttx/timers/cs2100-cp.h>
+
+#ifdef CONFIG_TIMERS_CS2100CP
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* Driver Definitions *******************************************************/
+
+#define MAX_REFCLK_FREQ 75000000
+#define MAX_REFCLK_XTAL 50000000
+
+#define MAX_SYSCLK 18750000
+
+#define MAX_SKIP_FREQ 80000000
+
+/* Debug ********************************************************************/
+
+#undef csdbg
+#ifdef CONFIG_CS2100CP_DEBUG
+# ifdef CONFIG_CPP_HAVE_VARARGS
+# define csdbg(format, ...) dbg(format, ##__VA_ARGS__)
+# else
+# define csdbg dbg
+# endif
+#else
+# ifdef CONFIG_CPP_HAVE_VARARGS
+# define csdbg(x...)
+# else
+# define csdbg (void)
+# endif
+#endif
+
+#undef regdbg
+#ifdef CONFIG_CS2100CP_REGDEBUG
+# ifdef CONFIG_CPP_HAVE_VARARGS
+# define regdbg(format, ...) dbg(format, ##__VA_ARGS__)
+# else
+# define regdbg dbg
+# endif
+#else
+# ifdef CONFIG_CPP_HAVE_VARARGS
+# define regdbg(x...)
+# else
+# define regdbg (void)
+# endif
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cs2100_write_reg
+ *
+ * Description:
+ * Write an 8 bit value to a CS2100 8-bit register.
+ *
+ * Input Parameters:
+ * config - CS2100-CP configuration
+ * regaddr - CS2100 register address
+ * regval - CS2100 register value to write
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int cs2100_write_reg(FAR const struct cs2100_config_s *config,
+ uint8_t regaddr, uint8_t regval)
+{
+ struct i2c_msg_s msgs[2];
+
+ regdbg("%02x<-%02x\n", regaddr, regval);
+ DEBUGASSERT(config->i2c->ops && config->i2c->ops->transfer);
+
+ /* Construct the I2C message (write N+1 bytes with no restart) */
+
+ msgs[0].addr = config->i2caddr;
+ msgs[0].flags = 0;
+ msgs[0].buffer = &regaddr;
+ msgs[0].length = 1;
+
+ msgs[1].addr = config->i2caddr;
+ msgs[1].flags = I2C_M_NORESTART;
+ msgs[1].buffer = &regval;
+ msgs[1].length = 1;
+
+ /* Send the message */
+
+ return I2C_TRANSFER(config->i2c, msgs, 2);
+}
+
+/****************************************************************************
+ * Name: cs2100_read_reg
+ *
+ * Description:
+ * Read an 8 bit value from a CS2100 8-bit register.
+ *
+ * Input Parameters:
+ * config - CS2100-CP configuration
+ * regaddr - CS2100 register address
+ * regval - Location to return the CS2100 register value
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_CS2100CP_DEBUG
+static int cs2100_read_reg(FAR const struct cs2100_config_s *config,
+ uint8_t regaddr, uint8_t *regval)
+{
+ struct i2c_msg_s msg;
+ int ret;
+
+ DEBUGASSERT(config->i2c->ops && config->i2c->ops->transfer);
+
+ /* Construct the I2C message (write 1 bytes, restart, read N bytes) */
+
+ msg.addr = config->i2caddr;
+ msg.flags = 0;
+ msg.buffer = &regaddr;
+ msg.length = 1;
+
+ /* Send the address followed by a STOP */
+
+ ret = I2C_TRANSFER(config->i2c, &msg, 1);
+ if (ret == OK)
+ {
+ msg.addr = config->i2caddr;
+ msg.flags = I2C_M_READ;
+ msg.buffer = regval;
+ msg.length = 1;
+
+ /* Read the register beginning with another START */
+
+ ret = I2C_TRANSFER(config->i2c, &msg, 1);
+ if (ret == OK)
+ {
+ regdbg("%02x->%02x\n", regaddr, *regval);
+ }
+ }
+
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: cs2100_write_reg
+ *
+ * Description:
+ * Write the 32-bit ratio value to CS2100 Ratio registers.
+ *
+ * Input Parameters:
+ * config - CS2100-CP configuration
+ * ratio - CS2100 ratio value to write
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int cs2100_write_ratio(FAR const struct cs2100_config_s *config,
+ uint32_t ratio)
+{
+ struct i2c_msg_s msg;
+ uint8_t buffer[5];
+
+ regdbg("%02x<-%04l\n", CS2100_RATIO0, (unsigned long)ratio);
+ DEBUGASSERT(config->i2c->ops && config->i2c->ops->transfer);
+
+ /* Construct the I2C message (write N+1 bytes with no restart) */
+
+ buffer[0] = CS2100_RATIO0;
+ buffer[1] = (uint8_t)(ratio >> 24);
+ buffer[2] = (uint8_t)((ratio >> 16) & 0xff);
+ buffer[3] = (uint8_t)((ratio >> 8) & 0xff);
+ buffer[4] = (uint8_t)(ratio & 0xff);
+
+ msg.addr = config->i2caddr;
+ msg.flags = 0;
+ msg.buffer = buffer;
+ msg.length = 5;
+
+ /* Send the message */
+
+ return I2C_TRANSFER(config->i2c, &msg, 1);
+}
+
+/****************************************************************************
+ * Name: cs2100_read_ratio
+ *
+ * Description:
+ * Read the 32-bit ratio value from the CS2100 Ratio registers.
+ *
+ * Input Parameters:
+ * config - CS2100-CP configuration
+ * ratio - Location to return the CS2100 ratio
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_CS2100CP_DEBUG
+static int cs2100_read_ratio(FAR const struct cs2100_config_s *config,
+ uint32_t *ratio)
+{
+ struct i2c_msg_s msg;
+ uint8_t buffer[4];
+ int ret;
+
+ DEBUGASSERT(config->i2c->ops && config->i2c->ops->transfer);
+
+ /* Construct the I2C message (write N+1 bytes with no restart) */
+
+ buffer[0] = CS2100_RATIO0;
+
+ msg.addr = config->i2caddr;
+ msg.flags = 0;
+ msg.buffer = buffer;
+ msg.length = 1;
+
+ /* Send the address followed by a STOP */
+
+ ret = I2C_TRANSFER(config->i2c, &msg, 1);
+ if (ret == OK)
+ {
+ msg.addr = config->i2caddr;
+ msg.flags = I2C_M_READ;
+ msg.buffer = buffer;
+ msg.length = 4;
+
+ /* Read the ratio registers beginning with another START */
+
+ ret = I2C_TRANSFER(config->i2c, &msg, 1);
+
+ /* Return the ratio */
+
+ if (ret == OK)
+ {
+ *ratio = ((uint32_t)buffer[0] << 24) |
+ ((uint32_t)buffer[1] << 16) |
+ ((uint32_t)buffer[2] << 8) |
+ (uint32_t)buffer[0];
+
+ regdbg("%02x->%04l\n", CS2100_RATIO0, (unsigned long)*ratio);
+ }
+ }
+
+ return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: cs2100_refclk
+ *
+ * Description:
+ * Set the reference clock divider value.
+ *
+ * Input Parameters:
+ * config - CS2100-CP configuration
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int cs2100_refclk(FAR const struct cs2100_config_s *config)
+{
+ uint8_t regval;
+ int ret;
+
+ DEBUGASSERT((config->xtal && config->refclk <= MAX_REFCLK_XTAL) ||
+ (!config->xtal && config->refclk <= MAX_REFCLK_FREQ));
+
+ /* Calculate and set the RefClk the divider */
+
+ if (config->refclk <= MAX_SYSCLK)
+ {
+ regval = CS2100_FNCCFG1_REFCLKDIV_NONE;
+ }
+ else if (config->refclk <= (MAX_SYSCLK / 2))
+ {
+ regval = CS2100_FNCCFG1_REFCLKDIV_DIV2;
+ }
+ else if (config->refclk <= (MAX_SYSCLK / 4))
+ {
+ regval = CS2100_FNCCFG1_REFCLKDIV_DIV4;
+ }
+ else
+ {
+ csdbg("ERROR: reflck too large: %ul\n", (unsigned long)config->refclk);
+ return -EINVAL;
+ }
+
+ /* Enable CLK_IN skipping mode? */
+
+ if (config->refclk <= MAX_SKIP_FREQ)
+ {
+ regval |= CS2100_FNCCFG1_CLKSKIPEN;
+ }
+
+ ret = cs2100_write_reg(config, CS2100_FNCCFG1, regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to set CS2100_FNCCFG1: %d\n", ret);
+ return ret;
+ }
+
+ /* Set the minimum loop bandwidth */
+
+ DEBUGASSERT(config->loopbw >=1 && config->loopbw <= 128);
+
+ if (config->loopbw < 2)
+ {
+ regval = CS2100_FNCCFG3_CLKINBW_1HZ;
+ }
+ else if (config->loopbw < 3)
+ {
+ regval = CS2100_FNCCFG3_CLKINBW_2HZ;
+ }
+ else if (config->loopbw < 6)
+ {
+ regval = CS2100_FNCCFG3_CLKINBW_4HZ;
+ }
+ else if (config->loopbw < 12)
+ {
+ regval = CS2100_FNCCFG3_CLKINBW_8HZ;
+ }
+ else if (config->loopbw < 24)
+ {
+ regval = CS2100_FNCCFG3_CLKINBW_16HZ;
+ }
+ else if (config->loopbw < 48)
+ {
+ regval = CS2100_FNCCFG3_CLKINBW_32HZ;
+ }
+ else if (config->loopbw < 96)
+ {
+ regval = CS2100_FNCCFG3_CLKINBW_64HZ;
+ }
+ else /* if (config->loopbw <= 128) */
+ {
+ regval = CS2100_FNCCFG3_CLKINBW_128HZ;
+ }
+
+ ret = cs2100_write_reg(config, CS2100_FNCCFG3, regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to set CS2100_FNCCFG3: %d\n", ret);
+ return ret;
+ }
+
+ /* Configure so that CLK_OUT will be enabled when the registers are
+ * unlocked (also clears other settings).
+ * NOTE: This implicitly sets High Multiplier mode for the Rud.
+ */
+
+ ret = cs2100_write_reg(config, CS2100_FNCCFG2, CS2100_FNCCFG2_CLKOUTUNL);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to set CS2100_FNCCFG2: %d\n", ret);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: cs2100_ratio
+ *
+ * Description:
+ * Calculate the effective input-to-output ratio
+ *
+ * Input Parameters:
+ * config - CS2100-CP configuration
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int cs2100_ratio(FAR const struct cs2100_config_s *config)
+{
+ uint64_t rudb24;
+ uint32_t rud;
+ uint8_t regval;
+ bool highmul;
+ int rmod;
+ int ret;
+
+ DEBUGASSERT(config->clkin > 0 && config->clkout > 0);
+
+ /* Calculate a 64-bit RUD value:
+ *
+ * R-Mod * clkout / clkin
+ *
+ * Initial calculation has 24-bits of accuracy (b24)
+ */
+
+ rudb24 = ((uint64_t)config->clkout << 24) / config->clkin;
+
+ /* If the b23 rudb24 is less than (1 << 39), then it can be represented as
+ * a high-precision (b20) value.
+ */
+
+ if (rudb24 < (1ull << (32+7)))
+ {
+ highmul = false;
+
+ /* Brute force! */
+
+ if (rudb24 >= (1ull << (32+6)))
+ {
+ rud = (uint32_t)rudb24 >> 7; /* RUD = RUDb20 / 8 */
+ rmod = 3; /* Reff = 8 * RUD */
+ }
+ else if (rudb24 >= (1ull << (32+5)))
+ {
+ rud = (uint32_t)rudb24 >> 6; /* RUD = RUDb20 / 4 */
+ rmod = 3; /* Reff = 4 * RUD */
+ }
+ else if (rudb24 >= (1ull << (32+4)))
+ {
+ rud = (uint32_t)rudb24 >> 5; /* RUD = RUDb20 / 2 */
+ rmod = 1; /* Reff = 2 * RUD */
+ }
+ else if (rudb24 >= (1ull << (32+3)))
+ {
+ rud = (uint32_t)rudb24 >> 4; /* RUD = RUDb20 */
+ rmod = 0; /* Reff = RUD */
+ }
+ else if (rudb24 >= (1ull << (32+2)))
+ {
+ rud = (uint32_t)rudb24 >> 3; /* RUD -> 2*RUDb20 */
+ rmod = 4; /* Reff = RUD / 2 */
+ }
+ else if (rudb24 >= (1ull << (32+1)))
+ {
+ rud = (uint32_t)rudb24 >> 2; /* RUD -> 4*RUDb20 */
+ rmod = 5; /* Reff = RUD / 4 */
+ }
+ else if (rudb24 >= (1ull << 32))
+ {
+ rud = (uint32_t)rudb24 >> 1; /* RUD -> 8*RUDb20 */
+ rmod = 6; /* Reff = RUD / 8 */
+ }
+ else
+ {
+ rud = (uint32_t)rudb24; /* RUD -> 16*RUDb20 */
+ rmod = 7; /* Reff = RUD / 16 */
+ }
+ }
+
+ /* If the b23 rudb24 is less than (1 << 47), then it can be represented as
+ * a high-multiplication (b12) value.
+ */
+
+ else if (rudb24 < (1ull << (32+12)))
+ {
+ highmul = true;
+
+ if (rudb24 >= (1ull << (32+11)))
+ {
+ rud = (uint32_t)rudb24 >> 12; /* RUD = RUDb12 */
+ rmod = 0; /* Reff = RUD */
+ }
+ else if (rudb24 >= (1ull << (32+10)))
+ {
+ rud = (uint32_t)rudb24 >> 11; /* RUD = 2*RUDb20 */
+ rmod = 4; /* Reff = RUD / 2 */
+ }
+ else if (rudb24 >= (1ull << (32+9)))
+ {
+ rud = (uint32_t)rudb24 >> 10; /* RUD = 4*RUDb20 */
+ rmod = 5; /* Reff = RUD / 4 */
+ }
+ else if (rudb24 >= (1ull << (32+8)))
+ {
+ rud = (uint32_t)rudb24 >> 9; /* RUD = 8*RUDb20 */
+ rmod = 6; /* Reff = RUD / 8 */
+ }
+ else /* if (rudb24 >= (1ull << (32+7))) */
+ {
+ rud = (uint32_t)rudb24 >> 8; /* RUD = 16*RUDb20 */
+ rmod = 7; /* Reff = RUD / 16 */
+ }
+ }
+ else
+ {
+ csdbg("ERROR: Ratio too large: %08llx\n", rudb24);
+ return -E2BIG;
+ }
+
+ /* Save the ratio */
+
+ ret = cs2100_write_ratio(config, rud);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to set ratio: %d\n", ret);
+ return ret;
+ }
+
+ /* Save the R-Mod value and EnDevCfg1. The device won't be fully enabled
+ * until EnDevCfg2 is setand registers are unfrozen and unlocked.
+ * REVISIT: Also sets AuxOutSrc to RefClk.
+ */
+
+ regval = (rmod << CS2100_DEVCFG1_RMODSEL_SHIFT) | CS2100_DEVCFG1_ENDEVCFG1;
+ ret = cs2100_write_reg(config, CS2100_DEVCFG1, regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to set CS2100_DEVCFG1: %d\n", ret);
+ return ret;
+ }
+
+ /* Set High Resolution mode if needed. NOTE: this depends on the fact
+ * that High Multipler mode was previously selected.
+ */
+
+ if (!highmul)
+ {
+ /* Preserve the ClkOutUnl bit */
+
+ regval = CS2100_FNCCFG2_CLKOUTUNL | CS2100_FNCCFG2_LFRATIOCFG;
+ ret = cs2100_write_reg(config, CS2100_FNCCFG2, regval);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: cs2100_enable
+ *
+ * Description:
+ * Enable CS2100 CLK_OUT using the provide parameters
+ *
+ * Input Parameters:
+ * config - CS2100-CP configuration
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int cs2100_enable(FAR const struct cs2100_config_s *config)
+{
+ uint8_t regval;
+ int ret;
+
+ DEBUGASSERT(config && config->i2c);
+
+ /* Lock the CS2100 and disable CLK_OUT and AUX_OUT. Subsequent settings
+ * will not take effect until the registers are unlocked.
+ */
+
+ regval = CS2100_DEVCTL_AUXOUTDIS | CS2100_DEVCTL_CLKOUTDIS;
+ ret = cs2100_write_reg(config, CS2100_DEVCTL, regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to set CS2100_DEVCTL: %d\n", ret);
+ return ret;
+ }
+
+ /* Set the internal timing reference clock divider */
+
+ ret = cs2100_refclk(config);
+ if (ret < 0)
+ {
+ csdbg("ERROR: cs2100_refclk failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Freeze device control registers. This allows modifications to r0-r4
+ * but the modifications will not take effect until the registers are
+ * unfrozen.
+ */
+
+ ret = cs2100_write_reg(config, CS2100_GBLCFG, CS2100_GBLCFG_FREEZE);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to set CS2100_GBLCFG: %d\n", ret);
+ return ret;
+ }
+
+ /* Calculate the effective ratio */
+
+ ret = cs2100_ratio(config);
+ if (ret < 0)
+ {
+ csdbg("ERROR: cs2100_ratio failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Unfreeze the r0-r4 and set EnDevCfg2 */
+
+ ret = cs2100_write_reg(config, CS2100_GBLCFG, CS2100_GBLCFG_ENDEVCFG2);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to set CS2100_GBLCFG: %d\n", ret);
+ return ret;
+ }
+
+ /* Unlock and enable the CS2100 and CLK_OUT */
+
+ regval = CS2100_DEVCTL_UNLOCK | CS2100_DEVCTL_AUXOUTDIS;
+ ret = cs2100_write_reg(config, CS2100_DEVCTL, regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to set CS2100_DEVCTL: %d\n", ret);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: cs2100_disable
+ *
+ * Description:
+ * Disable CS2100 CLK_OUT
+ *
+ * Input Parameters:
+ * config - CS2100-CP configuration
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int cs2100_disable(FAR const struct cs2100_config_s *config)
+{
+ uint8_t regval;
+ int ret;
+
+ /* Unlock and disable AUX_OUT and CLK_OUT */
+
+ regval = CS2100_DEVCTL_UNLOCK | CS2100_DEVCTL_AUXOUTDIS |
+ CS2100_DEVCTL_CLKOUTDIS;
+ ret = cs2100_write_reg(config, CS2100_DEVCTL, regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to set CS2100_DEVCTL: %d\n", ret);
+ return ret;
+ }
+
+ /* Clear EndDevCfg2 and unfreeze R0-R4 */
+
+ ret = cs2100_write_reg(config, CS2100_GBLCFG, 0);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to set CS2100_GBLCFG: %d\n", ret);
+ return ret;
+ }
+
+ /* Clear EndDevCfg1 */
+
+ ret = cs2100_write_reg(config, CS2100_DEVCFG1, 0);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to set CS2100_DEVCFG1: %d\n", ret);
+ return ret;
+ }
+
+ /* Lock the CS2100 */
+
+ regval = CS2100_DEVCTL_AUXOUTDIS | CS2100_DEVCTL_CLKOUTDIS;
+ ret = cs2100_write_reg(config, CS2100_DEVCTL, regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to set CS2100_DEVCTL: %d\n", ret);
+ }
+
+ return ret;
+}
+
+/********************************************************************************************
+ * Name: cs2100_dump
+ *
+ * Description:
+ * Dump CS2100-CP registers to the SysLog
+ *
+ * Input Parameters:
+ * config - CS2100-CP configuration (Needed only for I2C access: i2c and i2caddr)
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ********************************************************************************************/
+
+#ifdef CONFIG_CS2100CP_DEBUG
+int cs2100_dump(FAR const struct cs2100_config_s *config)
+{
+ uint32_t ratio;
+ uint8_t regval;
+ int ret;
+
+ dbg("CS200-CP Registers:\n");
+
+ ret = cs2100_read_reg(config, CS2100_DEVID, &regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to read CS2100_DEVID: %d\n", ret);
+ return ret;
+ }
+
+ dbg(" Devid: %02x\n", regval);
+
+ ret = cs2100_read_reg(config, CS2100_DEVCTL, &regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to read CS2100_DEVCTL: %d\n", ret);
+ return ret;
+ }
+
+ dbg(" DevCtl: %02x\n", regval);
+
+ ret = cs2100_read_reg(config, CS2100_DEVCFG1, &regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to read CS2100_DEVCFG1: %d\n", ret);
+ return ret;
+ }
+
+ dbg(" DevCfg1: %02x\n", regval);
+
+ ret = cs2100_read_reg(config, CS2100_GBLCFG, &regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to read CS2100_GBLCFG: %d\n", ret);
+ return ret;
+ }
+
+ dbg(" GblCfg: %02x\n", regval);
+
+ ret = cs2100_read_ratio(config, &ratio);
+ if (ret < 0)
+ {
+ csdbg("ERROR: cs2100_read_ratio failed: %d\n", ret);
+ return ret;
+ }
+
+ dbg(" Ratio: %04lx\n", (unsigned long)ratio);
+
+ ret = cs2100_read_reg(config, CS2100_FNCCFG1, &regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to read CS2100_FNCCFG1: %d\n", ret);
+ return ret;
+ }
+
+ dbg(" FuncCfg1: %02x\n", regval);
+
+ ret = cs2100_read_reg(config, CS2100_FNCCFG2, &regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to read CS2100_FNCCFG2: %d\n", ret);
+ return ret;
+ }
+
+ dbg(" FuncCfg2: %02x\n", regval);
+
+ ret = cs2100_read_reg(config, CS2100_FNCCFG3, &regval);
+ if (ret < 0)
+ {
+ csdbg("ERROR: Failed to read CS2100_FNCCFG3: %d\n", ret);
+ return ret;
+ }
+
+ dbg(" FuncCfg3: %02x\n", regval);
+ return OK;
+}
+
+#endif /* CONFIG_CS2100CP_DEBUG */
+#endif /* CONFIG_TIMERS_CS2100CP */
diff --git a/nuttx/include/nuttx/timers/cs2100-cp.h b/nuttx/include/nuttx/timers/cs2100-cp.h
index 723035232..9947f99d8 100644
--- a/nuttx/include/nuttx/timers/cs2100-cp.h
+++ b/nuttx/include/nuttx/timers/cs2100-cp.h
@@ -45,9 +45,29 @@
#include <stdint.h>
#include <nuttx/i2c.h>
+#ifdef CONFIG_TIMERS_CS2100CP
+
/********************************************************************************************
* Pre-processor Definitions
********************************************************************************************/
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_I2C
+# error I2C driver support is required (CONFIG_I2C)
+#else
+# ifndef CONFIG_I2C_TRANSFER
+# error I2C transfer method is required (CONFIG_I2C_TRANSFER)
+# endif
+#endif
+
+#ifndef CONFIG_TIMERS_CS2100CP_CLKINBW
+# define CONFIG_TIMERS_CS2100CP_CLKINBW 16
+#endif
+
+#ifndef CONFIG_DEBUG
+# undef CONFIG_CS2100CP_DEBUG
+# undef CONFIG_CS2100CP_REGDEBUG
+#endif
/* Register Addresses ***********************************************************************/
@@ -77,7 +97,7 @@
#define CS2100_DEVCTL_CLKOUTDIS (1 << 0) /* Bit 0: CLK_OUT disable */
#define CS2100_DEVCTL_AUXOUTDIS (1 << 1) /* Bit 1: AUX_OUT disable */
-#define CS2100_DEVCTL_UNLOCK (1 << 31) /* Bit 31: Unlock PLL */
+#define CS2100_DEVCTL_UNLOCK (1 << 7) /* Bit 7: Unlock PLL */
/* Device Configuration 1 */
@@ -141,6 +161,17 @@
* Public Types
********************************************************************************************/
+struct cs2100_config_s
+{
+ FAR struct i2c_dev_s *i2c; /* Instance of an I2C interface */
+ uint32_t refclk; /* RefClk/XTAL frequency */
+ uint32_t clkin; /* Frequency CLK_IN provided to the CS2100-CP */
+ uint32_t clkout; /* Desired CLK_OUT frequency */
+ uint8_t i2caddr; /* CP2100-CP I2C address */
+ uint8_t loopbw; /* Minimum loop bandwidth: 1-128 */
+ bool xtal; /* false: Refclck, true: Crystal on XTI/XTO */
+};
+
/********************************************************************************************
* Public Data
********************************************************************************************/
@@ -157,9 +188,62 @@ extern "C"
* Public Function Prototypes
********************************************************************************************/
+struct i2c_dev_s; /* Forward reference */
+
+/********************************************************************************************
+ * Name: cs2100_enable
+ *
+ * Description:
+ * Enable CS2100 CLK_OUT using the provide parameters
+ *
+ * Input Parameters:
+ * config - CS2100-CP configuration
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ********************************************************************************************/
+
+int cs2100_enable(FAR const struct cs2100_config_s *config);
+
+/********************************************************************************************
+ * Name: cs2100_disable
+ *
+ * Description:
+ * Disable CS2100 CLK_OUT
+ *
+ * Input Parameters:
+ * config - CS2100-CP configuration (Needed only for I2C access: i2c and i2caddr)
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ********************************************************************************************/
+
+int cs2100_disable(FAR const struct cs2100_config_s *config);
+
+/********************************************************************************************
+ * Name: cs2100_dump
+ *
+ * Description:
+ * Dump CS2100-CP registers to the SysLog
+ *
+ * Input Parameters:
+ * config - CS2100-CP configuration (Needed only for I2C access: i2c and i2caddr)
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ********************************************************************************************/
+
+#ifdef CONFIG_CS2100CP_DEBUG
+int cs2100_dump(FAR const struct cs2100_config_s *config);
+#endif
+
#undef EXTERN
#ifdef __cplusplus
}
#endif
+#endif /* CONFIG_TIMERS_CS2100CP */
#endif /* __INCLUDE_NUTTX_TIMERS_CS2100_CP_H */
diff --git a/nuttx/include/sys/boardctl.h b/nuttx/include/sys/boardctl.h
index a80f5339c..a7c64fe7d 100644
--- a/nuttx/include/sys/boardctl.h
+++ b/nuttx/include/sys/boardctl.h
@@ -147,7 +147,7 @@ struct boardioc_graphics_s
*
* boardctl() is non-standard OS interface to alleviate the problem. It
* basically circumvents the normal device driver ioctl interlace and allows
- * the application to perform direction IOCTL-like calls to the board-specific
+ * the application to perform direct IOCTL-like calls to the board-specific
* logic. It is especially useful for setting up board operational and
* test configurations.
*