FreeCalypso > hg > freecalypso-tools
view target-utils/libbase/abbdrv.c @ 659:761e8b0c65b0
loadagent: first step in implementation of binary flash programming
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 03 Mar 2020 17:55:20 +0000 |
parents | a04a145098f1 |
children |
line wrap: on
line source
/* 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, modified for page 2 support */ #define REG_PAGE(n) ((n) >> 6) #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); /* delay of seven 13MHz cycles */ wait_ARM_cycles(7); spi_xfer(TWL3025_DEV_IDX, 16, &tx, &rx); rx >>= 6; return rx; } /* Switch the register page of the TWL3025 */ abb_select_page(page) { switch (page) { case 0: abb_reg_write(PAGEREG, 1 << 0); break; case 1: abb_reg_write(PAGEREG, 1 << 1); break; case 2: /* not documented in datasheet, learned from TCS211 code */ abb_reg_write(PAGEREG, 1 << 4); break; } 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); /* ABB_Wait_IBIC_Access() delay of 210 us */ wait_ARM_cycles(210 * 13); /* for whatever reason we need to do this twice */ abb_reg_write(TOGBR2, TOGBR2_ACTS); /* ABB_Wait_IBIC_Access() delay of 210 us */ wait_ARM_cycles(210 * 13); abb_state_initdone = 1; return(1); } void abb_unlock_page2() { abb_reg_write(TAPCTRL, 0x01); abb_reg_write(TAPREG, 0x1B); } void abb_power_off() { abb_init(); /* * If we booted via nTESTRESET, we need to clean up some state * in a secret undocumented Iota register before we do the DEVOFF, * otherwise subsequent switch-on via regular PWON button * won't work correctly. */ abb_unlock_page2(); abb_reg_write(VRPCAUX, 0x07); serial_flush(); abb_reg_write(VRPCDEV, 0x01); /* DEVOFF */ /* * TWL3025 datasheet seems to indicate that the time for the DEVOFF * command to take effect is 5 cycles of the 32.768 kHz clock. * We'll do an ARM-timed delay of 10 ms before returning from * this function. */ wait_ARM_cycles(13000 * 10); }