diff options
Diffstat (limited to 'src/target/firmware')
-rw-r--r-- | src/target/firmware/include/mtk/mt6139.h | 60 | ||||
-rw-r--r-- | src/target/firmware/rf/mt6139.c | 205 |
2 files changed, 265 insertions, 0 deletions
diff --git a/src/target/firmware/include/mtk/mt6139.h b/src/target/firmware/include/mtk/mt6139.h new file mode 100644 index 00000000..35458b5d --- /dev/null +++ b/src/target/firmware/include/mtk/mt6139.h @@ -0,0 +1,60 @@ +#ifndef _MTK_MT6139_H +#define _MTK_MT6139_H + +enum mt6139_band { + MTRF_BAND_GSM850 = 0, + MTRF_BAND_GSM900 = 1, + MTRF_BAND_GSM1800 = 2, + MTRF_BAND_GSM1900 = 3, +}; + +#define MT6139_CW0_SYNCP_SHIFT 0 +#define MT6139_CW0_SYNCPW (1 << 2) +#define MT6139_CW0_DIEN (1 << 3) +#define MT6139_CW0_FLT (1 << 4) +#define MT6139_CW0_AFC_SHIFT 5 +#define MT6139_CW0_VCO_SEL (1 << 11) +#define MT6139_CW0_GPO (1 << 12) +#define MT6139_CW0_POR (1 << 13) + +#define MT6139_CW1_NFRACT_SHIFT 0 +#define MT6139_CW1_NINT_SHIFT 8 +#define MT6139_CW1_BAND_SHIFT 16 +#define MT6139_CW1_TRX_850 (1 << 18) + +#define MT6139_CW2_GAINTBL_SHIFT 0 +#define MT6139_CW2_MODE_SHIFT 6 +#define MT6139_CW2_AUTO_CAL (1 << 9) +#define MT6139_CW2_DCD_AQ_SHIFT 10 +#define MT6139_CW2_DCD_AI_SHIFT 16 + +#define MT6139_CW9_DCD_CQ_SHIFT 0 +#define MT6139_CW9_DCD_BQ_SHIFT 7 +#define MT6139_CW9_PWR_DAC_C (1 << 14) +#define MT6139_CW9_PWR_DAC_B (1 << 15) +#define MT6139_CW9_PWR_DAC_A (1 << 16) +#define MT6139_CW9_AM_ENABLE (1 << 17) + +enum mt6139_cw2_mode { + MODE_SLEEP = 0x0, + MODE_WARM_UP = 0x1, + MODE_RECEIVE = 0x3, + MODE_TRANSMIT = 0x4, +}; + +#define MT6139_CW11_TX_CTL (1 << 0) +#define MT6139_CW11_TXG_IQM (1 << 1) +#define MT6139_CW11_TXD_IQM (1 << 2) +#define MT6139_CW11_TX_DIV2 (1 << 3) +#define MT6139_CW11_TX_DIV4 (1 << 4) +#define MT6139_CW11_TXG_BUF (1 << 5) +#define MT6139_CW11_TXD_BUF (1 << 6) +#define MT6139_CW11_TXMODGAIN_SHIFT 7 +#define MT6139_CW11_TX_FLT_SHIFT 10 +#define MT6139_CW11_TXAPC_SHIFT 14 +#define MT6139_CW11_TXPW_SHIFT 16 +#define MT6139_CW11_TXBIAST_SHIFT 18 +#define MT6139_CW11_TXDIV_GC0 (1 << 20) +#define MT6139_CW11_TXDIV_GC1 (1 << 21) + +#endif /* _MTK_MT6139_H */ diff --git a/src/target/firmware/rf/mt6139.c b/src/target/firmware/rf/mt6139.c new file mode 100644 index 00000000..6103646a --- /dev/null +++ b/src/target/firmware/rf/mt6139.c @@ -0,0 +1,205 @@ +/* Driver for RF Transceiver Circuit (MT6139) */ + +/* (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 <stdint.h> +#include <stdio.h> + +#include <debug.h> +#include <memory.h> +#include <keypad.h> +#include <osmocore/gsm_utils.h> + +#include <layer1/agc.h> +#include <rffe.h> + +#include <mtk/mt6139.h> + +static void mt6139_compute_pll(uint32_t f_vco_100khz, + uint16_t *nint, uint16_t *nfrac) +{ + /* To compute Nint, we assume Nfrac is zero */ + *nint = (fvco_100khz / (10 * 2 * 26)) - (0 / 130); + + if (nint > 127) + printf("VCO Frequency %u kHz is out of spec\n", f_vco_100khz); + + /* Compute Nfract using the pre-computed Nint */ + /* Nfrac = ( (Fvco/2*26) - Nint) * 130 */ + /* Nfrac = ( (Fvco*130)/(2*26) - (Nint * 130) */ + *nfrac = (f_vco_100khz*130)/(52*10) - (nint * 130); +} + +/* Set ARFCN. Takes 2 reg_write, i.e. 8 TPU instructions */ +void mt6139_set_arfcn(uint16_t arfcn, int uplink) +{ + uint32_t regval = 0; + uint32_t vco_mult; + uint32_t freq_khz, f_vco_100khz; + uint16_t nint, nfrac; + + freq_khz = gsm_arfcn2freq10(arfcn, uplink) * 100; + printd("ARFCN %u -> %u kHz\n", arfcn, freq_khz); + + switch (gsm_arfcn2band(arfcn)) { + case GSM_BAND_850: + if (uplink) + regval |= MT6139_CW1_TRX_850; + regval |= (0 << MT6139_CW1_BAND_SHIFT); + vco_mult = 4; + break; + case GSM_BAND_900: + regval |= (1 << MT6139_CW1_BAND_SHIFT); + vco_mult = 4; + break; + case GSM_BAND_1800: + regval |= (2 << MT6139_CW1_BAND_SHIFT); + vco_mult = 2; + break; + case GSM_BAND_1900: + regval |= (3 << MT6139_CW1_BAND_SHIFT); + vco_mult = 2; + break; + default: + printf("Unsupported rf_band.\n"); + break; + } + + /* Compute VCO frequency for channel frequency */ + f_vco_100khz = (freq_khz / 100) * vco_mult; + + /* Compute Nint and Nfract */ + mt6139_compute_pll(f_vco_100khz, &nint, &nfrac); + + /* mask-in the Nint / Nfrac bits in CW1 */ + regval |= (nfrac & 0xff) << MT6139_CW1_NFRACT_SHIFT; + regval |= (nint & 0x7f) << MT6139_CW1_NINT_SHIFT; + +} + +void mt6139_init() +{ + uint32_t val; + + /* reset and get it out of reset again */ + val = MT6139_CW0_DIEN | (0x20 << MT6139_CW0_AFC_SHIFT); + mt6139_reg_write(0, val | MT6139_CW0_POR); + mt6139_reg_write(0, val); + + /* Turn off AM and A loop calibration function (CM9) */ + val = (0x40 << MT6139_CW9_DCD_CQ_SHIFT) | + (0x40 << MT6139_CW9_DCD_BQ_SHIFT) | + MT6139_CW9_PWR_DAC_C | MT6139_CW9_PWR_DAC_B; + mt6139_reg_write(9, val); + + /* Move to SLEEP mode */ + val = (0x3e << MT6139_CW2_GAINTBL_SHIFT) | + (MODE_SLEEP << MT6139_CW2_MODE_SHIFT) | + MT6139_CW2_AUTO_CAL | + (0x20 << MT6139_CW2_DCD_AQ_SHIFT) | + (0x20 << MT6139_CW2_DCD_AI_SHIFT); + mt6139_reg_write(2, val); +} + +void mt6139_rx_burst() +{ + uint8_t pga_gain; + + /* Turn on the synthesizer and move into Warm-up mode */ + val = (0x3e << MT6139_CW2_GAINTBL_SHIFT) | + (MODE_WARM_UP << MT6139_CW2_MODE_SHIFT) | + MT6139_CW2_AUTO_CAL | + (0x20 << MT6139_CW2_DCD_AQ_SHIFT) | + (0x20 << MT6139_CW2_DCD_AI_SHIFT); + mt6139_reg_write(2, val); + + /* Program the frequency synthesizer N counter and band selection */ + /* FIXME: see above for mt6139_set_arfcn() */ + + /* Set receive mode, PGA gain */ + val = (pga_gain << MT6139_CW2_GAINTBL_SHIFT) | + (MODE_RECEIVE << MT6139_CW2_MODE_SHIFT) | + MT6139_CW2_AUTO_CAL | + (0x20 << MT6139_CW2_DCD_AQ_SHIFT) | + (0x20 << MT6139_CW2_DCD_AI_SHIFT); + mt6139_reg_write(2, val); + + /* FIXME: Do the actual burst Rx */ + + /* Set Sleep mode */ + val = (0x3e << MT6139_CW2_GAINTBL_SHIFT) | + (MODE_SLEEP << MT6139_CW2_MODE_SHIFT) | + MT6139_CW2_AUTO_CAL | + (0x20 << MT6139_CW2_DCD_AQ_SHIFT) | + (0x20 << MT6139_CW2_DCD_AI_SHIFT); + mt6139_reg_write(2, val); +} + +void mt6139_tx_burst() +{ + /* Turn on the synthesizer and move into Warm-up mode */ + val = (0x3e << MT6139_CW2_GAINTBL_SHIFT) | + (MODE_WARM_UP << MT6139_CW2_MODE_SHIFT) | + MT6139_CW2_AUTO_CAL | + (0x20 << MT6139_CW2_DCD_AQ_SHIFT) | + (0x20 << MT6139_CW2_DCD_AI_SHIFT); + mt6139_reg_write(2, val); + + /* Program the frequency synthesizer N counter and band selection */ + /* FIXME: see above for mt6139_set_arfcn() */ + + /* Send Tx setting */ + val = MT6139_CW11_TX_CTL | + MT6139_CW11_TXG_IQM | + MT6139_CW11_TXD_IQM | + MT6139_CW11_TX_DIV2 | + MT6139_CW11_TX_DIV4 | + MT6139_CW11_TXG_BUF | + MT6139_CW11_TXD_BUF | + (3 << MT6139_CW11_TX_FLT_SHIFT) | + (1 << MT6139_CW11_TXAPC_SHIFT) | + (3 << MT6139_CW11_TXPW_SHIFT) | + (2 << MT6139_CW11_TXBIAST_SHIFT) | + MT6139_CW11_TXDIV_GC0; + if (1) // low band + mt6139_reg_write(11, val | (0 << MT6139_CW11_TXMODGAIN_SHIFT)); + else + mt6139_reg_write(11, val | (4 << MT6139_CW11_TXMODGAIN_SHIFT)); + + /* Set Transmit mode */ + val = (0x3e << MT6139_CW2_GAINTBL_SHIFT) | + (MODE_TRANSMIT << MT6139_CW2_MODE_SHIFT) | + MT6139_CW2_AUTO_CAL | + (0x20 << MT6139_CW2_DCD_AQ_SHIFT) | + (0x20 << MT6139_CW2_DCD_AI_SHIFT); + mt6139_reg_write(2, val); + + /* FIXME: Do the actual burst Tx */ + + /* Set Sleep mode */ + val = (0x3e << MT6139_CW2_GAINTBL_SHIFT) | + (MODE_SLEEP << MT6139_CW2_MODE_SHIFT) | + MT6139_CW2_AUTO_CAL | + (0x20 << MT6139_CW2_DCD_AQ_SHIFT) | + (0x20 << MT6139_CW2_DCD_AI_SHIFT); + mt6139_reg_write(2, val); +} + |