From 4fee67676c775475e786abb97ab10eaf5b28f453 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 2 Apr 2015 13:00:10 -0600 Subject: Add a very basic driver for the CS2100-CP Fractional-N Multipler chip. --- nuttx/Documentation/NuttxPortingGuide.html | 2 +- nuttx/configs/samv71-xult/README.txt | 15 + nuttx/drivers/timers/Kconfig | 20 + nuttx/drivers/timers/Make.defs | 6 + nuttx/drivers/timers/cs2100-cp.c | 836 +++++++++++++++++++++++++++++ nuttx/include/nuttx/timers/cs2100-cp.h | 86 ++- nuttx/include/sys/boardctl.h | 2 +- 7 files changed, 964 insertions(+), 3 deletions(-) create mode 100755 nuttx/drivers/timers/cs2100-cp.c 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);

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 logic. + It basically circumvents the normal device driver ioctl() 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.

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 + * + * 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 + +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 = ®addr; + msgs[0].length = 1; + + msgs[1].addr = config->i2caddr; + msgs[1].flags = I2C_M_NORESTART; + msgs[1].buffer = ®val; + 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 = ®addr; + 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, ®val); + 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, ®val); + 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, ®val); + 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, ®val); + 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, ®val); + 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, ®val); + 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, ®val); + 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 #include +#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. * -- cgit v1.2.3