[PATCH 2/4] Initial support for Nuttx on TI Calypso platform: Import clock and timer related files Osmocom Modify timer.c to Nuttx API

Stefan Richter ichgeh at l--putt.de
Tue May 24 19:13:49 UTC 2011


---
 nuttx/arch/arm/include/calypso/clock.h     |   67 +++++++++
 nuttx/arch/arm/include/calypso/timer.h     |   25 ++++
 nuttx/arch/arm/src/calypso/calypso_timer.c |  205
++++++++++++++++++++++++++++
 nuttx/arch/arm/src/calypso/clock.c         |  202
+++++++++++++++++++++++++++
 4 files changed, 499 insertions(+), 0 deletions(-)
 create mode 100644 nuttx/arch/arm/include/calypso/clock.h
 create mode 100644 nuttx/arch/arm/include/calypso/timer.h
 create mode 100644 nuttx/arch/arm/src/calypso/calypso_timer.c
 create mode 100644 nuttx/arch/arm/src/calypso/clock.c

diff --git a/nuttx/arch/arm/include/calypso/clock.h
b/nuttx/arch/arm/include/calypso/clock.h
new file mode 100644
index 0000000..abcfde1
--- /dev/null
+++ b/nuttx/arch/arm/include/calypso/clock.h
@@ -0,0 +1,67 @@
+#ifndef _CALYPSO_CLK_H
+#define _CALYPSO_CLK_H
+
+#include <stdint.h>
+
+#define CALYPSO_PLL26_52_MHZ	((2 << 8) | 0)
+#define CALYPSO_PLL26_86_7_MHZ	((10 << 8) | 2)
+#define CALYPSO_PLL26_87_MHZ	((3 << 8) | 0)
+#define CALYPSO_PLL13_104_MHZ	((8 << 8) | 0)
+
+enum mclk_div {
+	_ARM_MCLK_DIV_1		= 0,
+	ARM_MCLK_DIV_1		= 1,
+	ARM_MCLK_DIV_2		= 2,
+	ARM_MCLK_DIV_3		= 3,
+	ARM_MCLK_DIV_4		= 4,
+	ARM_MCLK_DIV_5		= 5,
+	ARM_MCLK_DIV_6		= 6,
+	ARM_MCLK_DIV_7		= 7,
+	ARM_MCLK_DIV_1_5	= 0x80 | 1,
+	ARM_MCLK_DIV_2_5	= 0x80 | 2,
+};
+
+void calypso_clock_set(uint8_t vtcxo_div2, uint16_t inp, enum mclk_div
mclk_div);
+void calypso_pll_set(uint16_t inp);
+void calypso_clk_dump(void);
+
+/* CNTL_RST */
+enum calypso_rst {
+	RESET_DSP	= (1 << 1),
+	RESET_EXT	= (1 << 2),
+	RESET_WDOG	= (1 << 3),
+};
+
+void calypso_reset_set(enum calypso_rst calypso_rst, int active);
+int calypso_reset_get(enum calypso_rst);
+
+enum calypso_bank {
+	CALYPSO_nCS0	= 0,
+	CALYPSO_nCS1	= 2,
+	CALYPSO_nCS2	= 4,
+	CALYPSO_nCS3	= 6,
+	CALYPSO_nCS7	= 8,
+	CALYPSO_CS4	= 0xa,
+	CALYPSO_nCS6	= 0xc,
+};
+
+enum calypso_mem_width {
+	CALYPSO_MEM_8bit	= 0,
+	CALYPSO_MEM_16bit	= 1,
+	CALYPSO_MEM_32bit	= 2,
+};
+
+void calypso_mem_cfg(enum calypso_bank bank, uint8_t ws,
+		     enum calypso_mem_width width, int we);
+
+/* Enable or disable the internal bootrom mapped to 0x0000'0000 */
+void calypso_bootrom(int enable);
+
+/* Enable or disable the debug unit */
+void calypso_debugunit(int enable);
+
+/* configure the RHEA bus bridge[s] */
+void calypso_rhea_cfg(uint8_t fac0, uint8_t fac1, uint8_t timeout,
+		      uint8_t ws_h, uint8_t ws_l, uint8_t w_en0, uint8_t w_en1);
+
+#endif /* _CALYPSO_CLK_H */
diff --git a/nuttx/arch/arm/include/calypso/timer.h
b/nuttx/arch/arm/include/calypso/timer.h
new file mode 100644
index 0000000..694e4eb
--- /dev/null
+++ b/nuttx/arch/arm/include/calypso/timer.h
@@ -0,0 +1,25 @@
+#ifndef _CAL_TIMER_H
+#define _CAL_TIMER_H
+
+/* Enable or Disable a timer */
+void hwtimer_enable(int num, int on);
+
+/* Configure pre-scaler and if timer is auto-reload */
+void hwtimer_config(int num, uint8_t pre_scale, int auto_reload);
+
+/* Load a timer with the given value */
+void hwtimer_load(int num, uint16_t val);
+
+/* Read the current timer value */
+uint16_t hwtimer_read(int num);
+
+/* Enable or disable the watchdog */
+void wdog_enable(int on);
+
+/* Reset cpu using watchdog */
+void wdog_reset(void);
+
+/* power up the timers */
+void hwtimer_init(void);
+
+#endif /* _CAL_TIMER_H */
diff --git a/nuttx/arch/arm/src/calypso/calypso_timer.c
b/nuttx/arch/arm/src/calypso/calypso_timer.c
new file mode 100644
index 0000000..0191c0c
--- /dev/null
+++ b/nuttx/arch/arm/src/calypso/calypso_timer.c
@@ -0,0 +1,205 @@
+/****************************************************************************
+ * arch/arm/src/calypso/calypso_timer.c
+ * Calypso DBB internal Timer Driver
+ *
+ * (C) 2010 by Harald Welte <laforge at gnumonks.org>
+ * (C) 2011 by Stefan Richter <ichgeh at l--putt.de>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+
****************************************************************************/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <nuttx/arch.h>
+
+#include <arch/calypso/defines.h>
+#include <arch/calypso/memory.h>
+#include <arch/calypso/timer.h>
+
+
+#define BASE_ADDR_TIMER		0xfffe3800
+#define TIMER2_OFFSET		0x3000
+
+#define TIMER_REG(n, m)		(((n)-1) ? (BASE_ADDR_TIMER + TIMER2_OFFSET +
(m)) : (BASE_ADDR_TIMER + (m)))
+
+enum timer_reg {
+	CNTL_TIMER	= 0x00,
+	LOAD_TIMER	= 0x02,
+	READ_TIMER	= 0x04,
+};
+
+enum timer_ctl {
+	CNTL_START		= (1 << 0),
+	CNTL_AUTO_RELOAD	= (1 << 1),
+	CNTL_CLOCK_ENABLE	= (1 << 5),
+};
+
+/* Regular Timers (1 and 2) */
+
+void hwtimer_enable(int num, int on)
+{
+	uint8_t ctl;
+
+	if (num < 1 || num > 2) {
+		printf("Unknown timer %u\n", num);
+		return;
+	}
+
+	ctl = readb(TIMER_REG(num, CNTL_TIMER));
+	if (on)
+		ctl |= CNTL_START|CNTL_CLOCK_ENABLE;
+	else
+		ctl &= ~CNTL_START;
+	writeb(ctl, TIMER_REG(num, CNTL_TIMER));
+}
+
+void hwtimer_config(int num, uint8_t pre_scale, int auto_reload)
+{
+	uint8_t ctl;
+
+	ctl = (pre_scale & 0x7) << 2;
+	if (auto_reload)
+		ctl |= CNTL_AUTO_RELOAD;
+
+	writeb(ctl, TIMER_REG(num, CNTL_TIMER));
+}
+
+void hwtimer_load(int num, uint16_t val)
+{
+	writew(val, TIMER_REG(num, LOAD_TIMER));
+}
+
+uint16_t hwtimer_read(int num)
+{
+	uint8_t ctl = readb(TIMER_REG(num, CNTL_TIMER));
+
+	/* somehow a read results in an abort */
+	if ((ctl & (CNTL_START|CNTL_CLOCK_ENABLE)) !=
(CNTL_START|CNTL_CLOCK_ENABLE))
+		return 0xFFFF;
+	return readw(TIMER_REG(num, READ_TIMER));
+}
+
+/************************************************************
+ * Watchdog Timer
+ ************************************************************/
+
+#define BASE_ADDR_WDOG		0xfffff800
+#define WDOG_REG(m)		(BASE_ADDR_WDOG + m)
+
+enum wdog_reg {
+	WD_CNTL_TIMER	= CNTL_TIMER,
+	WD_LOAD_TIMER	= LOAD_TIMER,
+	WD_READ_TIMER	= 0x02,
+	WD_MODE		= 0x04,
+};
+
+enum wdog_ctl {
+	WD_CTL_START = (1 << 7),
+	WD_CTL_AUTO_RELOAD = (1 << 8)
+};
+
+enum wdog_mode {
+	WD_MODE_DIS_ARM = 0xF5,
+	WD_MODE_DIS_CONFIRM = 0xA0,
+	WD_MODE_ENABLE = (1 << 15)
+};
+
+#define WD_CTL_PRESCALE(value) (((value)&0x07) << 9)
+
+static void wdog_irq(__unused enum irq_nr nr)
+{
+	puts("=> WATCHDOG\n");
+}
+
+void wdog_enable(int on)
+{
+	if (on) {
+#if 0
+		irq_config(IRQ_WATCHDOG, 0, 0, 0);
+		irq_register_handler(IRQ_WATCHDOG, &wdog_irq);
+		irq_enable(IRQ_WATCHDOG);
+		writew(WD_MODE_ENABLE, WDOG_REG(WD_MODE));
+#endif
+	} else {
+		writew(WD_MODE_DIS_ARM, WDOG_REG(WD_MODE));
+		writew(WD_MODE_DIS_CONFIRM, WDOG_REG(WD_MODE));
+	}
+}
+
+void wdog_reset(void)
+{
+#if 0
+	// XXX: this is supposed to reset immediately but does not seem to
+	writew(0xF5, WDOG_REG(WD_MODE));
+	writew(0xFF, WDOG_REG(WD_MODE));
+#else
+	// enable watchdog
+	writew(WD_MODE_ENABLE, WDOG_REG(WD_MODE));
+	// force expiration
+	writew(0x0000, WDOG_REG(WD_LOAD_TIMER));
+	writew(0x0000, WDOG_REG(WD_LOAD_TIMER));
+#endif
+}
+
+/************************************************************
+ * Global Functions
+ ************************************************************/
+
+/************************************************************
+ * Function:  up_timerisr
+ *
+ * Description:
+ *   The timer ISR will perform a variety of services for
+ *   various portions of the systems.
+ *
+ ************************************************************/
+
+int up_timerisr(int irq, uint32_t *regs)
+{
+   /* Process timer interrupt */
+
+   sched_process_timer();
+   return 0;
+}
+
+/************************************************************
+ * Function:  up_timerinit
+ *
+ * Description:
+ *   Setup Calypso HW timer 2 to cause system ticks.
+ *
+ *   This function is called during start-up to initialize
+ *   the timer interrupt.
+ *
+ ************************************************************/
+
+void up_timerinit(void)
+{
+  up_disable_irq(IRQ_SYSTIMER);
+
+  /* The timer runs at 13MHz / 32, i.e. 406.25kHz */
+  /* 4062 ticks until expiry yields 100Hz interrupt */
+  hwtimer_load(2, 4062);
+  hwtimer_config(2, 0, 1);
+  hwtimer_enable(2, 1);
+
+  /* Attach and enable the timer interrupt */
+  irq_attach(IRQ_SYSTIMER, (xcpt_t)up_timerisr);
+  up_enable_irq(IRQ_SYSTIMER);
+}
+
diff --git a/nuttx/arch/arm/src/calypso/clock.c
b/nuttx/arch/arm/src/calypso/clock.c
new file mode 100644
index 0000000..77b4ea5
--- /dev/null
+++ b/nuttx/arch/arm/src/calypso/clock.c
@@ -0,0 +1,202 @@
+/* Driver for Calypso clock management */
+
+/* (C) 2010 by Harald Welte <laforge at gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdio.h>
+
+//#define DEBUG
+#include <arch/calypso/debug.h>
+
+#include <arch/calypso/memory.h>
+#include <arch/calypso/clock.h>
+
+#define REG_DPLL		0xffff9800
+#define DPLL_LOCK		(1 << 0)
+#define DPLL_BREAKLN		(1 << 1)
+#define DPLL_BYPASS_DIV_SHIFT	2		/* 2 bits */
+#define DPLL_PLL_ENABLE		(1 << 4)
+#define DPLL_PLL_DIV_SHIFT	5		/* 2 bits */
+#define DPLL_PLL_MULT_SHIFT	7		/* 5 bits */
+#define DPLL_TEST		(1 << 12)
+#define DPLL_IOB		(1 << 13)	/* Initialize on break */
+#define DPLL_IAI		(1 << 14)	/* Initialize after Idle */
+
+#define BASE_ADDR_CLKM	0xfffffd00
+#define CLKM_REG(m)	(BASE_ADDR_CLKM+(m))
+
+enum clkm_reg {
+	CNTL_ARM_CLK	= 0,
+	CNTL_CLK	= 2,
+	CNTL_RST	= 4,
+	CNTL_ARM_DIV	= 8,
+};
+
+/* CNTL_ARM_CLK */
+#define ARM_CLK_BIG_SLEEP	(1 << 0)	/* MCU Master Clock enabled? */
+#define ARM_CLK_CLKIN_SEL0	(1 << 1)	/* MCU source clock (0 = DPLL
output, 1 = VTCXO or CLKIN */
+#define ARM_CLK_CLKIN_SEL	(1 << 2)	/* 0 = VTCXO or 1 = CLKIN */
+#define ARM_CLK_MCLK_DIV5	(1 << 3)	/* enable 1.5 or 2.5 division factor */
+#define ARM_CLK_MCLK_DIV_SHIFT	4		/* 3 bits */
+#define ARM_CLK_DEEP_POWER_SHIFT	8
+#define ARM_CLK_DEEP_SLEEP	12
+
+/* CNTL_CLK */
+#define CLK_IRQ_CLK_DIS		(1 << 0)	/* IRQ clock control (0 always, 1
according ARM_MCLK_EN) */
+#define CLK_BRIDGE_CLK_DIS	(1 << 1)
+#define CLK_TIMER_CLK_DIS	(1 << 2)
+#define CLK_DPLL_DIS		(1 << 3)	/* 0: DPLL is not stopped during SLEEP */
+#define CLK_CLKOUT_EN		(1 << 4)	/* Enable CLKOUT output pins */
+#define CLK_EN_IDLE3_FLG	(1 << 5)	/* DSP idle flag control (1 =
+						 * SAM/HOM register forced to HOM when DSP IDLE3) */
+#define CLK_VCLKOUT_DIV2	(1 << 6)	/* 1: VCLKOUT-FR is divided by 2 */
+#define CLK_VTCXO_DIV2		(1 << 7)	/* 1: VTCXO is dividied by 2 */
+
+#define BASE_ADDR_MEMIF		0xfffffb00
+#define MEMIF_REG(x)		(BASE_ADDR_MEMIF+(x))
+
+enum memif_reg {
+	API_RHEA_CTL	= 0x0e,
+	EXTRA_CONF	= 0x10,
+};
+
+static void dump_reg16(uint32_t addr, char *name)
+{
+	printf("%s=0x%04x\n", name, readw(addr));
+}
+
+void calypso_clk_dump(void)
+{
+	dump_reg16(REG_DPLL, "REG_DPLL");
+	dump_reg16(CLKM_REG(CNTL_ARM_CLK), "CNTL_ARM_CLK");
+	dump_reg16(CLKM_REG(CNTL_CLK), "CNTL_CLK");
+	dump_reg16(CLKM_REG(CNTL_RST), "CNTL_RST");
+	dump_reg16(CLKM_REG(CNTL_ARM_DIV), "CNTL_ARM_DIV");
+}
+
+void calypso_pll_set(uint16_t inp)
+{
+	uint8_t mult = inp >> 8;
+	uint8_t div = inp & 0xff;
+	uint16_t reg = readw(REG_DPLL);
+
+	reg &= ~0x0fe0;
+	reg |= (div & 0x3) << DPLL_PLL_DIV_SHIFT;
+	reg |= (mult & 0x1f) << DPLL_PLL_MULT_SHIFT;
+	reg |= DPLL_PLL_ENABLE;
+
+	writew(reg, REG_DPLL);
+}
+
+void calypso_reset_set(enum calypso_rst calypso_rst, int active)
+{
+	uint8_t reg = readb(CLKM_REG(CNTL_RST));
+
+	if (active)
+		reg |= calypso_rst;
+	else
+		reg &= ~calypso_rst;
+
+	writeb(reg, CLKM_REG(CNTL_RST));
+}
+
+int calypso_reset_get(enum calypso_rst calypso_rst)
+{
+	uint8_t reg = readb(CLKM_REG(CNTL_RST));
+
+	if (reg & calypso_rst)
+		return 1;
+	else
+		return 0;
+}
+
+void calypso_clock_set(uint8_t vtcxo_div2, uint16_t inp, enum mclk_div
mclk_div)
+{
+	uint16_t cntl_clock = readw(CLKM_REG(CNTL_CLK));
+	uint16_t cntl_arm_clk = readw(CLKM_REG(CNTL_ARM_CLK));
+
+	/* First set the vtcxo_div2 */
+	cntl_clock &= ~CLK_VCLKOUT_DIV2;
+	if (vtcxo_div2)
+		cntl_clock |= CLK_VTCXO_DIV2;
+	else
+		cntl_clock &= ~CLK_VTCXO_DIV2;
+	writew(cntl_clock, CLKM_REG(CNTL_CLK));
+
+	/* Then configure the MCLK divider */
+	cntl_arm_clk &= ~ARM_CLK_CLKIN_SEL0;
+	if (mclk_div & 0x80) {
+		mclk_div &= ~0x80;
+		cntl_arm_clk |= ARM_CLK_MCLK_DIV5;
+	} else
+		cntl_arm_clk &= ~ARM_CLK_MCLK_DIV5;
+	cntl_arm_clk &= ~(0x7 << ARM_CLK_MCLK_DIV_SHIFT);
+	cntl_arm_clk |= (mclk_div << ARM_CLK_MCLK_DIV_SHIFT);
+	writew(cntl_arm_clk, CLKM_REG(CNTL_ARM_CLK));
+
+	/* Then finally set the PLL */
+	calypso_pll_set(inp);
+}
+
+void calypso_mem_cfg(enum calypso_bank bank, uint8_t ws,
+		     enum calypso_mem_width width, int we)
+{
+	writew((ws & 0x1f) | ((width & 3) << 5) | ((we & 1) << 7),
+	       BASE_ADDR_MEMIF + bank);
+}
+
+void calypso_bootrom(int enable)
+{
+	uint16_t conf = readw(MEMIF_REG(EXTRA_CONF));
+
+	conf |= (3 << 8);
+
+	if (enable)
+		conf &= ~(1 << 9);
+
+	writew(conf, MEMIF_REG(EXTRA_CONF));
+}
+
+void calypso_debugunit(int enable)
+{
+	uint16_t conf = readw(MEMIF_REG(EXTRA_CONF));
+
+	if (enable)
+		conf &= ~(1 << 11);
+	else
+		conf |= (1 << 11);
+
+	writew(conf, MEMIF_REG(EXTRA_CONF));
+}
+
+#define REG_RHEA_CNTL	0xfffff900
+#define REG_API_CNTL	0xfffff902
+#define REG_ARM_RHEA	0xfffff904
+
+void calypso_rhea_cfg(uint8_t fac0, uint8_t fac1, uint8_t timeout,
+		      uint8_t ws_h, uint8_t ws_l, uint8_t w_en0, uint8_t w_en1)
+{
+	writew(fac0 | (fac1 << 4) | (timeout << 8), REG_RHEA_CNTL);
+	writew(ws_h | (ws_l << 5), REG_API_CNTL);
+	writew(w_en0 | (w_en1 << 1), REG_ARM_RHEA);
+}
-- 
1.7.1





More information about the baseband-devel mailing list