changeset 389:e60aecf23970

target-utils: ABB operations implemented (ported from OsmocomBB), linked into pirexplore
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Wed, 11 Jun 2014 06:50:46 +0000
parents 821a26f90968
children bb4814eb51e4
files target-utils/include/abbdefs.h target-utils/libcommon/Makefile target-utils/libcommon/abbcmd.c target-utils/libcommon/abbdrv.c target-utils/libcommon/spidrv.c target-utils/pirexplore/cmdtab.c
diffstat 6 files changed, 453 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/target-utils/include/abbdefs.h	Wed Jun 11 06:50:46 2014 +0000
@@ -0,0 +1,155 @@
+/* lifted from OsmocomBB */
+
+#ifndef _TWL3025_H
+#define _TWL3025_H
+
+#define PAGE(n)		(n << 7)
+enum twl3025_reg {
+	VRPCCFG		= PAGE(1) | 30,
+	VRPCDEV		= PAGE(0) | 30,
+	VRPCMSK		= PAGE(1) | 31,
+	VRPCMSKABB	= PAGE(1) | 29,
+	VRPCSTS		= PAGE(0) | 31,
+	/* Monitoring ADC Registers */
+	MADCTRL		= PAGE(0) | 13,
+	MADCSTAT	= PAGE(0) | 24,
+	VBATREG		= PAGE(0) | 15,
+	VCHGREG		= PAGE(0) | 16,
+	ICHGREG		= PAGE(0) | 17,
+	VBKPREG		= PAGE(0) | 18,
+	ADIN1REG	= PAGE(0) | 19,
+	ADIN2REG	= PAGE(0) | 20,
+	ADIN3REG	= PAGE(0) | 21,
+	ADIN4REG	= PAGE(0) | 22,
+	/* Clock Generator Registers */
+	TOGBR1		= PAGE(0) | 4,
+	TOGBR2		= PAGE(0) | 5,
+	PWDNRG		= PAGE(1) | 9,
+	TAPCTRL		= PAGE(1) | 19,
+	TAPREG		= PAGE(1) | 20,
+	/* Automatic Frequency Control (AFC) Registers */
+	AUXAFC1		= PAGE(0) | 7,
+	AUXAFC2		= PAGE(0) | 8,
+	AFCCTLADD	= PAGE(1) | 21,
+	AFCOUT		= PAGE(1) | 22,
+	/* Automatic Power Control (APC) Registers */
+	APCDEL1		= PAGE(0) | 2,
+	APCDEL2		= PAGE(1) | 26,
+	AUXAPC		= PAGE(0) | 9,
+	APCRAM		= PAGE(0) | 10,
+	APCOFF		= PAGE(0) | 11,
+	APCOUT		= PAGE(1) | 12,
+	/* Auxiliary DAC Control Register */
+	AUXDAC		= PAGE(0) | 12,
+	/* SimCard Control Register */
+	VRPCSIM		= PAGE(1) | 23,
+	/* LED Driver Register */
+	AUXLED		= PAGE(1) | 24,
+	/* Battery Charger Interface (BCI) Registers */
+	CHGREG		= PAGE(0) | 25,
+	BCICTL1		= PAGE(0) | 28,
+	BCICTL2		= PAGE(0) | 29,
+	BCICONF		= PAGE(1) | 13,
+	/* Interrupt and Bus Control (IBIC) Registers */
+	ITMASK		= PAGE(0) | 28,
+	ITSTATREG	= PAGE(0) | 27,	/* both pages! */
+	PAGEREG		= PAGE(0) | 1, 	/* both pages! */
+	/* Baseband Codec (BBC) Registers */
+	BULIOFF		= PAGE(1) | 2,
+	BULQOFF		= PAGE(1) | 3,
+	BULIDAC		= PAGE(1) | 5,
+	BULQDAC		= PAGE(1) | 4,
+	BULGCAL		= PAGE(1) | 14,
+	BULDATA1	= PAGE(0) | 3,	/* 16 words */
+	BBCTRL		= PAGE(1) | 6,
+	/* Voiceband Codec (VBC) Registers */
+	VBCTRL1		= PAGE(1) | 8,
+	VBCTRL2		= PAGE(1) | 11,
+	VBPOP		= PAGE(1) | 10,
+	VBUCTRL		= PAGE(1) | 7,
+	VBDCTRL		= PAGE(0) | 6,
+};
+#define BULDATA2	BULDATA1
+
+/* available ADC inputs on IOTA */
+enum twl3025_dac_inputs {/* === Signal ============================= */
+	MADC_VBAT=0,	/* battery voltage / 4                      */
+	MADC_VCHG=1,	/* charger voltage / 5                      */
+	MADC_ICHG=2,	/* I-sense amp or CHGREG DAC output         */
+	MADC_VBKP=3,	/* backup battery voltage / 4               */
+	MADC_ADIN1=4,	/* VADCID, sense battery type, not used     */
+	MADC_ADIN2=5,	/* Temperature sensor in Battery            */
+	MADC_ADIN3=6,	/* Mode_detect: sense 2.5mm jack insertion  */
+	MADC_ADIN4=7,	/* RITA: TEMP_SEN                           */
+	MADC_NUM_CHANNELS=8
+};
+
+enum madcstat_reg_bits { /* monitoring ADC status register */
+	ADCBUSY = 0x01  /* if set, a conversion is currently going on */
+};
+
+/* BCICTL1 register bits */
+enum bcictl1_reg_bits {
+	MESBAT	= 1<<0,	/* connect resistive divider for bat voltage */
+	DACNBUF	= 1<<1,	/* bypass DAC buffer */
+	THSENS0	= 1<<3,	/* thermal sensor bias current (ADIN2), bit 0 */
+	THSENS1	= 1<<4,	/* "" bit 1 */
+	THSENS2	= 1<<5,	/* "" bit 2 */
+	THEN	= 1<<6,	/* enable thermal sensor bias current (ADIN1) */ 
+	TYPEN	= 1<<7	/* enable bias current for battery type reading */
+};
+
+/* BCICTL1 register bits */
+enum bcictl2_reg_bits {
+	CHEN	= 1<<0,	/* enable charger */
+	CHIV	= 1<<1,	/* 1=constant current, 0=constant voltage */
+	CHBPASSPA=1<<2,	/* full charging of the battery during pulse radio */
+	CLIB	= 1<<3,	/* calibrate I-to-V amp (short input pins) */
+	CHDISPA	= 1<<4,	/* disabel charging during pulse radio (???) */
+	LEDC	= 1<<5,	/* enable LED during charge */
+	CGAIN4	= 1<<6,	/* if set, I-to-V amp gain is reduced from 10 to 4 */
+	PREOFF	= 1<<7	/* disable battery precharge */
+};
+
+enum vrpcsts_reg_bits {
+	ONBSTS = 1<<0,	/* button push switched on the mobile */
+	ONRSTS = 1<<1,	/* RPWON terminal switched on the mobile */
+	ITWSTS = 1<<2,	/* ITWAKEUP terminal switched on the mobile */
+	CHGSTS = 1<<3,	/* plugging in charger has switched on the mobile */
+	ONREFLT= 1<<4,	/* state of PWON terminal after debouncing */
+	ONMRFLT= 1<<5,	/* state of RPWON terminal after debouncing */
+	CHGPRES= 1<<6	/* charger is connected */
+};
+
+enum togbr2_bits {
+	TOGBR2_KEEPR	= (1 << 0),	/* Clear KEEPON bit */
+	TOGBR2_KEEPS	= (1 << 1),	/* Set KEEPON bit */
+	TOGBR2_ACTR	= (1 << 2),	/* Dectivate MCLK */
+	TOGBR2_ACTS	= (1 << 3),	/* Activate MCLK */
+	TOGBR2_IBUFPTR1	= (1 << 4),	/* Initialize pointer of burst buffer 1 */
+	TOGBR2_IBUFPTR2	= (1 << 5),	/* Initialize pointer of burst buffer 2 */
+	TOGBR2_IAPCPTR	= (1 << 6),	/* Initialize pointer of APC RAM */
+};
+
+/* How a RAMP value is encoded */
+#define ABB_RAMP_VAL(up, down)	( ((down & 0x1F) << 5) | (up & 0x1F) )
+
+enum twl3025_unit {
+	TWL3025_UNIT_AFC,
+	TWL3025_UNIT_MAD,
+	TWL3025_UNIT_ADA,
+	TWL3025_UNIT_VDL,
+	TWL3025_UNIT_VUL,
+};
+
+enum twl3025_tsp_bits {
+	BULON		= 0x80,
+	BULCAL		= 0x40,
+	BULENA		= 0x20,
+	BDLON		= 0x10,
+	BDLCAL		= 0x08,
+	BDLENA		= 0x04,
+	STARTADC	= 0x02,
+};
+
+#endif
--- a/target-utils/libcommon/Makefile	Tue Jun 10 20:59:32 2014 +0000
+++ b/target-utils/libcommon/Makefile	Wed Jun 11 06:50:46 2014 +0000
@@ -6,7 +6,7 @@
 
 OBJS=	cmdentry.o dispatch.o hexarg.o parseargs.o serio.o serflush.o uartsel.o\
 	cmd_baud_switch.o cmd_dieid.o cmd_jump.o cmd_r8.o cmd_r16.o cmd_r32.o \
-	cmd_w8.o cmd_w16.o cmd_w32.o osmodelay.o
+	cmd_w8.o cmd_w16.o cmd_w32.o abbcmd.o abbdrv.o osmodelay.o spidrv.o
 
 all:	libcommon.a
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/target-utils/libcommon/abbcmd.c	Wed Jun 11 06:50:46 2014 +0000
@@ -0,0 +1,49 @@
+/*
+ * abbr pg reg		-- read ABB register
+ * abbw pg reg val	-- write ABB register
+ */
+
+#include <sys/types.h>
+#include "types.h"
+#include "abbdefs.h"
+
+extern u16 abb_reg_read();
+extern void abb_reg_write();
+
+void
+cmd_abbr(argbulk)
+	char *argbulk;
+{
+	char *argv[3];
+	u32 pg, reg, val;
+
+	if (parse_args(argbulk, 2, 2, argv, 0) < 0)
+		return;
+	pg = strtoul(argv[0], 0, 0);
+	reg = strtoul(argv[1], 0, 0);
+	if (pg > 1 || reg > 31) {
+		printf("ERROR: argument(s) out of range\n");
+		return;
+	}
+	val = abb_reg_read(PAGE(pg) | reg);
+	printf("%03X\n", val);
+}
+
+void
+cmd_abbw(argbulk)
+	char *argbulk;
+{
+	char *argv[4];
+	u32 pg, reg, val;
+
+	if (parse_args(argbulk, 3, 3, argv, 0) < 0)
+		return;
+	pg = strtoul(argv[0], 0, 0);
+	reg = strtoul(argv[1], 0, 0);
+	val = strtoul(argv[2], 0, 16);
+	if (pg > 1 || reg > 31 || val > 0x3FF) {
+		printf("ERROR: argument(s) out of range\n");
+		return;
+	}
+	abb_reg_write(PAGE(pg) | reg, val);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/target-utils/libcommon/abbdrv.c	Wed Jun 11 06:50:46 2014 +0000
@@ -0,0 +1,101 @@
+/* Driver for Analog Baseband Circuit (TWL3025) */
+/* lifted from OsmocomBB and ported to FreeCalypso target-utils environment */
+
+/* (C) 2010 by Harald Welte <laforge@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 "types.h"
+#include "abbdefs.h"
+
+/* TWL3025 */
+#define REG_PAGE(n)	((n) >> 7)
+#define REG_ADDR(n)	((n) & 0x1f)
+
+#define TWL3025_DEV_IDX		0	/* On the SPI bus */
+#define TWL3025_TSP_DEV_IDX	0	/* On the TSP bus */
+
+int abb_state_initdone, abb_state_page;
+
+void
+abb_reg_write(reg, data)
+{
+	u16 tx;
+
+	if (reg != PAGEREG && REG_PAGE(reg) != abb_state_page)
+		abb_select_page(REG_PAGE(reg));
+
+	tx = ((data & 0x3ff) << 6) | (REG_ADDR(reg) << 1);
+
+	spi_xfer(TWL3025_DEV_IDX, 16, &tx, 0);
+}
+
+u16
+abb_reg_read(reg)
+{
+	u16 tx, rx;
+
+	if (REG_PAGE(reg) != abb_state_page)
+		abb_select_page(REG_PAGE(reg));
+
+	tx = (REG_ADDR(reg) << 1) | 1;
+
+	/* A read cycle contains two SPI transfers */
+	spi_xfer(TWL3025_DEV_IDX, 16, &tx, &rx);
+	osmo_delay_ms(1);
+	spi_xfer(TWL3025_DEV_IDX, 16, &tx, &rx);
+
+	rx >>= 6;
+
+	return rx;
+}
+
+/* Switch the register page of the TWL3025 */
+abb_select_page(page)
+{
+	if (page == 0)
+		abb_reg_write(PAGEREG, 1 << 0);
+	else
+		abb_reg_write(PAGEREG, 1 << 1);
+	abb_state_page = page;
+	return(0);
+}
+
+abb_init()
+{
+	if (abb_state_initdone)
+		return(0);
+	spi_init();
+	abb_select_page(0);
+	/* CLK13M enable */
+	abb_reg_write(TOGBR2, TOGBR2_ACTS);
+	osmo_delay_ms(1);
+	/* for whatever reason we need to do this twice */
+	abb_reg_write(TOGBR2, TOGBR2_ACTS);
+	osmo_delay_ms(1);
+	abb_state_initdone = 1;
+	return(1);
+}
+
+void
+abb_power_off()
+{
+	abb_init();
+	abb_reg_write(VRPCDEV, 0x01);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/target-utils/libcommon/spidrv.c	Wed Jun 11 06:50:46 2014 +0000
@@ -0,0 +1,139 @@
+/* Driver for SPI Master Controller inside TI Calypso */
+/* lifted from OsmocomBB and ported to FreeCalypso target-utils environment */
+
+/* (C) 2010 by Harald Welte <laforge@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 "types.h"
+
+#define	ASIC_CONF_REG	(*(volatile u16 *) 0xFFFEF008)
+
+struct spi_regs {
+	u16	reg_set1;
+	u16	reg_set2;
+	u16	reg_ctrl;
+	u16	reg_status;
+	u16	reg_tx_lsb;
+	u16	reg_tx_msb;
+	u16	reg_rx_lsb;
+	u16	reg_rx_msb;
+};
+
+#define	SPI_REGS	(*(volatile struct spi_regs *) 0xFFFE3000)
+
+#define BASE_ADDR_SPI	0xfffe3000
+#define SPI_REG(n)	(BASE_ADDR_SPI+(n))
+
+#define SPI_SET1_EN_CLK		(1 << 0)
+#define SPI_SET1_WR_IRQ_DIS	(1 << 4)
+#define SPI_SET1_RDWR_IRQ_DIS	(1 << 5)
+
+#define SPI_CTRL_RDWR		(1 << 0)
+#define SPI_CTRL_WR		(1 << 1)
+#define SPI_CTRL_NB_SHIFT	2
+#define SPI_CTRL_AD_SHIFT	7
+
+#define SPI_STATUS_RE		(1 << 0)	/* Read End */
+#define SPI_STATUS_WE		(1 << 1)	/* Write End */
+
+spi_init()
+{
+	static int initdone;
+
+	if (initdone)
+		return(0);
+	ASIC_CONF_REG |= 0x6000;
+	SPI_REGS.reg_set1 = SPI_SET1_EN_CLK | SPI_SET1_WR_IRQ_DIS |
+				SPI_SET1_RDWR_IRQ_DIS;
+	SPI_REGS.reg_set2 = 0x0001;
+	initdone = 1;
+	return(1);
+}
+
+spi_xfer(dev_idx, bitlen, dout, din)
+	void *dout, *din;
+{
+	int bytes_per_xfer;
+	u16 reg_status, reg_ctrl = 0;
+	u32 tmp;
+
+	if (bitlen <= 0)
+		return 0;
+
+	if (bitlen > 32)
+		return -1;
+
+	if (dev_idx > 4)
+		return -1;
+
+	bytes_per_xfer = bitlen / 8;
+	if (bitlen % 8)
+		bytes_per_xfer ++;
+
+	reg_ctrl |= (bitlen - 1) << SPI_CTRL_NB_SHIFT;
+	reg_ctrl |= (dev_idx & 0x7) << SPI_CTRL_AD_SHIFT;
+
+	if (bitlen <= 8) {
+		tmp = *(u8 *)dout;
+		tmp <<= 24 + (8-bitlen);	/* align to MSB */
+	} else if (bitlen <= 16) {
+		tmp = *(u16 *)dout;
+		tmp <<= 16 + (16-bitlen);	/* align to MSB */
+	} else {
+		tmp = *(u32 *)dout;
+		tmp <<= (32-bitlen);		/* align to MSB */
+	}
+
+	/* fill transmit registers */
+	SPI_REGS.reg_tx_msb = tmp >> 16;
+	SPI_REGS.reg_tx_lsb = tmp;
+
+	/* initiate transfer */
+	if (din)
+		reg_ctrl |= SPI_CTRL_RDWR;
+	else
+		reg_ctrl |= SPI_CTRL_WR;
+	SPI_REGS.reg_ctrl = reg_ctrl;
+
+	/* wait until the transfer is complete */
+	while (1) {
+		reg_status = SPI_REGS.reg_status;
+		if (din && (reg_status & SPI_STATUS_RE))
+			break;
+		else if (reg_status & SPI_STATUS_WE)
+			break;
+	}
+	/* FIXME: calibrate how much delay we really need (seven 13MHz cycles) */
+	osmo_delay_ms(1);
+
+	if (din) {
+		tmp = SPI_REGS.reg_rx_msb << 16;
+		tmp |= SPI_REGS.reg_rx_lsb;
+
+		if (bitlen <= 8)
+			*(u8 *)din = tmp & 0xff;
+		else if (bitlen <= 16)
+			*(u16 *)din = tmp & 0xffff;
+		else
+			*(u32 *)din = tmp;
+	}
+
+	return 0;
+}
--- a/target-utils/pirexplore/cmdtab.c	Tue Jun 10 20:59:32 2014 +0000
+++ b/target-utils/pirexplore/cmdtab.c	Wed Jun 11 06:50:46 2014 +0000
@@ -1,5 +1,7 @@
 #include "cmdtab.h"
 
+extern void cmd_abbr();
+extern void cmd_abbw();
 extern void cmd_baud_switch();
 extern void cmd_blit();
 extern void cmd_dieid();
@@ -20,10 +22,15 @@
 extern void cmd_w16();
 extern void cmd_w32();
 
+extern void abb_init();
+extern void abb_power_off();
 extern void cmd_memdump_human();
 extern void mpffs_init();
 
 const struct cmdtab cmdtab[] = {
+	{"abbinit", abb_init},
+	{"abbr", cmd_abbr},
+	{"abbw", cmd_abbw},
 	{"baud", cmd_baud_switch},
 	{"blit", cmd_blit},
 	{"dieid", cmd_dieid},
@@ -35,6 +42,7 @@
 	{"lcdfill", cmd_lcdfill},
 	{"lcdinit", cmd_lcdinit},
 	{"lcdtest", cmd_lcdtest},
+	{"poweroff", abb_power_off},
 	{"r8", cmd_r8},
 	{"r16", cmd_r16},
 	{"r32", cmd_r32},