target/rf: Make the trf6151_set_arfcn use ARFCN_UPLINK flag to select UL/DL
[osmocom-bb.git] / src / target / firmware / rf / trf6151.c
blob96210fc60406bb82a9abbedddc575d59a781dfaa
1 /* Driver for RF Transceiver Circuit (TRF6151) */
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
5 * All Rights Reserved
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include <stdint.h>
24 #include <stdio.h>
26 #include <debug.h>
27 #include <memory.h>
28 #include <keypad.h>
29 #include <osmocom/gsm/gsm_utils.h>
31 #include <calypso/tpu.h>
32 #include <calypso/tsp.h>
33 #include <layer1/agc.h>
34 #include <rffe.h>
36 #include <rf/trf6151.h>
38 /* #define WARN_OUT_OF_SPEC 1 */
40 enum trf6151_reg {
41 REG_RX = 0, /* RF general settings */
42 REG_PLL = 1, /* PLL settings */
43 REG_PWR = 2, /* Power on/off functional blocks */
44 REG_CFG = 3, /* Transceiver and PA controller settings */
45 REG_TEST1 = 4,
46 REG_TEST2 = 5,
47 REG_TEST3 = 6,
48 REG_TEST4 = 7,
49 _MAX_REG
52 /* REG_RX */
53 #define RX_READ_EN (1 << 7)
54 #define RX_CAL_MODE (1 << 8)
55 #define RX_RF_GAIN_HIGH (3 << 9)
56 #define RX_VGA_GAIN_SHIFT 11
58 /* REG_PWR */
59 #define PWR_BANDGAP_SHIFT 3
60 #define PWR_BANDGAP_OFF (0 << PWR_BANDGAP_SHIFT)
61 #define PWR_BANDGAP_ON_SPEEDUP (2 << PWR_BANDGAP_SHIFT)
62 #define PWR_BANDGAP_ON (3 << PWR_BANDGAP_SHIFT)
63 #define PWR_REGUL_ON (1 << 5)
64 #define PWR_SYNTHE_OFF (0)
65 #define PWR_SYNTHE_RX_ON (1 << 9)
66 #define PWR_SYNTHE_TX_ON (1 << 10)
67 #define PWR_RX_MODE (1 << 11)
68 #define PWR_TX_MODE (1 << 13)
69 #define PWR_PACTRL_APC (1 << 14)
70 #define PWR_PACTRL_APCEN (1 << 15)
72 /* REG_CFG */
73 #define CFG_TX_LOOP_MANU (1 << 3)
74 #define CFG_PACTLR_IDIOD_30uA (0 << 4)
75 #define CFG_PACTLR_IDIOD_300uA (1 << 4)
76 #define CFG_PACTLR_RES_OPEN (0 << 10)
77 #define CFG_PACTLR_RES_150k (1 << 10)
78 #define CFG_PACTLR_RES_300k (2 << 10)
79 #define CFG_PACTLR_CAP_0pF (0 << 12)
80 #define CFG_PACTLR_CAP_12p5F (1 << 12)
81 #define CFG_PACTLR_CAP_25pF (3 << 12)
82 #define CFG_PACTLR_CAP_50pF (2 << 12)
83 #define CFG_TEMP_SENSOR (1 << 14)
84 #define CFG_ILOGIC_INIT_DIS (1 << 15)
86 /* FIXME: This must be defined in the RFFE configuration */
87 #define TRF6151_TSP_UID 2
88 #define TRF6151_PACTRL_CFG (CFG_PACTLR_RES_OPEN|CFG_PACTLR_CAP_0pF|CFG_PACTLR_IDIOD_30uA)
90 #define PLL_VAL(a, b) ((a << 3) | (((b)-64) << 9))
92 /* All values in qbits unless otherwise specified */
93 #define TRF6151_LDO_DELAY_TS 6 /* six TDMA frames (at least 25ms) */
94 #define TRF6151_RX_PLL_DELAY 184 /* 170 us */
95 #define TRF6151_TX_PLL_DELAY 260 /* 240 us */
98 enum trf6151_pwr_unit {
99 TRF1651_PACTLR_APC,
100 TRF6151_PACTRL_APCEN,
101 TRF6151_TRANSMITTER,
102 TRF6151_REGULATORS,
105 enum trf6151_gsm_band {
106 GSM900 = 1,
107 GSM1800 = 2,
108 GSM850_LOW = 4,
109 GSM850_HIGH = 5,
110 GSM1900 = 6,
114 uint16_t rf_arfcn = 871; /* TODO: this needs to be private */
115 static uint16_t rf_band;
117 static uint8_t trf6151_tsp_uid;
118 static uint8_t trf6151_vga_dbm = 40;
119 static int trf6151_gain_high = 1;
121 static uint16_t trf6151_reg_cache[_MAX_REG] = {
122 [REG_RX] = 0x9E00,
123 [REG_PLL] = 0x0000,
124 [REG_PWR] = 0x0000,
125 [REG_CFG] = 0x2980,
128 /* Write to a TRF6151 register (4 TPU instructions) */
129 static void trf6151_reg_write(uint16_t reg, uint16_t val)
131 printd("trf6151_reg_write(reg=%u, val=0x%04x)\n", reg, val);
132 /* each TSP write takes 4 TPU instructions */
133 tsp_write(trf6151_tsp_uid, 16, (reg | val));
134 trf6151_reg_cache[reg] = val;
137 /* Frontend gain can be switched high or low (dB) */
138 #define TRF6151_FE_GAIN_LOW 7
139 #define TRF6151_FE_GAIN_HIGH 27
141 /* VGA at baseband can be adjusted in this range (dB) */
142 #define TRF6151_VGA_GAIN_MIN 14
143 #define TRF6151_VGA_GAIN_MAX 40
145 /* put current set (or computed) gain to register */
146 int trf6151_set_gain_reg(uint8_t dbm, int high)
148 uint16_t reg = trf6151_reg_cache[REG_RX] & 0x07ff;
149 printd("trf6151_set_gain_reg(%u, %d)\n", dbm, high);
151 if (dbm < TRF6151_VGA_GAIN_MIN || dbm > TRF6151_VGA_GAIN_MAX)
152 return -1;
154 /* clear the gain bits first */
155 reg &= ~((0x1F) << RX_VGA_GAIN_SHIFT);
156 /* OR-in the new gain value */
157 reg |= (6 + (dbm-TRF6151_VGA_GAIN_MIN)/2) << RX_VGA_GAIN_SHIFT;
159 if (high)
160 reg |= RX_RF_GAIN_HIGH;
161 else
162 reg &= ~RX_RF_GAIN_HIGH;
164 trf6151_reg_write(REG_RX, reg);
166 return 0;
169 int trf6151_set_gain(uint8_t dbm)
171 int high = 0;
173 printd("trf6151_set_gain(%u, %d)\n", dbm);
174 /* If this is negative or less than TRF6151_GAIN_MIN, we are pretty
175 * much lost as we cannot reduce the system inherent gain. If it is
176 * positive, it corresponds to the gain that we need to configure */
177 if (dbm < TRF6151_FE_GAIN_LOW + TRF6151_VGA_GAIN_MIN) {
178 printd("AGC Input level overflow\n");
179 trf6151_vga_dbm = TRF6151_VGA_GAIN_MIN;
180 trf6151_gain_high = 0;
181 return 0;
182 } else if (dbm >= TRF6151_FE_GAIN_HIGH + TRF6151_VGA_GAIN_MIN) {
183 high = 1;
184 dbm -= TRF6151_FE_GAIN_HIGH;
185 } else
186 dbm -= TRF6151_FE_GAIN_LOW;
187 if (dbm > TRF6151_VGA_GAIN_MAX)
188 dbm = TRF6151_VGA_GAIN_MAX;
190 /* update the static global variables which are used when programming
191 * the window */
192 trf6151_vga_dbm = dbm;
193 trf6151_gain_high = high;
195 return 0;
198 #define SCALE_100KHZ 100
200 /* Compute TRF6151 PLL valuese */
201 static void trf6151_pll_rx(uint32_t freq_khz,
202 uint16_t *pll_config, enum trf6151_gsm_band *band)
204 const uint32_t p=64, r=65;
205 uint32_t freq_100khz, vco_freq_100khz;
206 uint32_t l, n;
207 uint32_t a, b;
209 /* Scale into 100kHz unit (avoid overflow in intermediates) */
210 freq_100khz = freq_khz / SCALE_100KHZ;
212 /* L selects hi/lo band */
213 l = (freq_khz > 1350000) ? 2 : 4; /* cut at mid point :) */
215 /* VCO frequency */
216 vco_freq_100khz = freq_100khz * l;
218 /* vco_freq = 26MHz / R * N with R=65 and N=B*P+A */
219 n = (vco_freq_100khz * r) / 260;
220 a = n % p;
221 b = n / p;
223 *pll_config = PLL_VAL(a, b);
225 /* Out-of-spec tuning warning */
226 #ifdef WARN_OUT_OF_SPEC
227 if ((l == 4 && (b < 135 || b > 150)) ||
228 (l == 2 && (b < 141 || b > 155)))
229 printf("Frequency %u kHz is out of spec\n", (unsigned int)freq_khz);
230 #endif
232 /* Select band */
233 if (l==4) {
234 /* If in the low band, same port for both GSM850/GSM900, so we
235 * choose the best VCO (VCOMAIN1=3.37GHz, VCOMAIN2=3.8GHz) */
236 if (vco_freq_100khz < 35850) /* midpoint */
237 *band = GSM850_LOW;
238 else
239 *band = GSM900;
241 /* Out-of-spec freq check */
242 #ifdef WARN_OUT_OF_SPEC
243 if (!(freq_khz >= 869000 && freq_khz <= 894000) &&
244 !(freq_khz >= 921000 && freq_khz <= 960000)) /* include GSM-R */
245 printf("Frequency %u outside normal filter range for selected port\n", (unsigned int)freq_khz);
246 #endif
247 } else {
248 /* In the high band, different ports for DCS/PCS, so
249 * take what's best and available */
250 /* We're stuck to VCOMAIN2=3.8GHz though ... */
251 uint32_t rx_ports = rffe_get_rx_ports();
252 uint32_t port;
254 /* Select port */
255 port = (freq_khz < 1905000) ? (1 << PORT_DCS1800) : (1 << PORT_PCS1900);
256 port = (port & rx_ports) ? port : rx_ports;
258 /* Select band */
259 *band = (port & (1 << PORT_DCS1800)) ? GSM1800 : GSM1900;
261 /* Out-of-spec freq check */
262 #ifdef WARN_OUT_OF_SPEC
263 if ((*band == GSM1800 && (freq_khz < 1805000 || freq_khz > 1880000)) ||
264 (*band == GSM1900 && (freq_khz < 1930000 || freq_khz > 1990000)))
265 printf("Frequency %u outside normal filter range for selected port\n", (unsigned int)freq_khz);
266 #endif
269 /* Debug */
270 printd("RX Freq %u kHz => A = %u, B = %u, band = %d, vco_freq = %u kHz\n", freq_khz, a, b, *band, vco_freq_100khz*100);
272 /* All done */
273 return;
276 /* Compute TRF6151 PLL TX values */
277 static void trf6151_pll_tx(uint32_t freq_khz,
278 uint16_t *pll_config, enum trf6151_gsm_band *band)
280 const uint32_t p=64;
281 uint32_t r, l, m, m_op_l; /* m_op_l = m +/- l depending on mode */
282 uint32_t freq_100khz;
283 uint32_t n, a, b, b_min, b_max;
285 /* Scale into 100kHz unit (avoid overflow in intermediates) */
286 freq_100khz = freq_khz / SCALE_100KHZ;
288 /* Select band (and PLL mode) */
289 if (freq_khz > 1350000) {
290 /* High band, so only 1 real PLL mode. band doesn't matter
291 * that much (or at all) but we still do it :p */
292 *band = (freq_khz < 1817500) ? GSM1800 : GSM1900;
293 r = 70;
294 l = 2;
295 m = 26;
296 m_op_l = m + l;
297 b_min = 133;
298 b_max = 149;
299 } else {
300 /* Low band. We have 3 possible PLL modes that output on
301 * the right port: GSM900, GSM850_HIGH, GSM850_LOW.
303 * The transistion points have been chosen looking at the VCO
304 * and IF frequencies for various frequencies for theses modes
306 if (freq_khz < 837100) {
307 /* GSM850_LOW */
308 *band = GSM850_LOW;
309 r = 55;
310 l = 4;
311 m = 26;
312 m_op_l = m - l;
313 b_min = 128;
314 b_max = 130;
315 } else if (freq_khz < 850000) {
316 /* GSM850_HIGH */
317 *band = GSM850_HIGH;
318 r = 30;
319 l = 4;
320 m = 52;
321 m_op_l = m - l;
322 b_min = 65;
323 b_max = 66;
324 } else {
325 /* GSM900 */
326 *band = GSM900;
327 r = 35;
328 l = 4;
329 m = 52;
330 m_op_l = m + l;
331 b_min = 68;
332 b_max = 71;
336 /* vco_freq = f * M * L / (M +- L) */
337 /* = 26MHz / R * N with R=65 and N=B*P+A */
338 n = (freq_100khz * m * l * r) / (m_op_l * 260);
339 a = n % p;
340 b = n / p;
342 *pll_config = PLL_VAL(a, b);
344 /* Debug */
345 printd("TX Freq %u kHz => A = %u, B = %u, band = %d\n", freq_khz, a, b, *band);
347 /* Out-of-spec tuning warning */
348 #ifdef WARN_OUT_OF_SPEC
349 if (b < b_min || b > b_max)
350 printf("Frequency %u kHz is out of spec\n", (unsigned int)freq_khz);
351 #endif
353 /* All done */
354 return;
357 static inline void trf6151_reset(uint16_t reset_id)
359 /* pull the nRESET line low */
360 tsp_act_disable(reset_id);
361 tpu_enq_wait(50);
362 /* release nRESET */
363 tsp_act_enable(reset_id);
366 void trf6151_init(uint8_t tsp_uid, uint16_t tsp_reset_id)
368 trf6151_tsp_uid = tsp_uid;
370 /* Configure the TSPEN which is connected to TRF6151 STROBE */
371 tsp_setup(trf6151_tsp_uid, 0, 1, 1);
373 trf6151_reset(tsp_reset_id);
375 /* configure TRF6151 for operation */
376 trf6151_power(1);
377 trf6151_reg_write(REG_CFG, TRF6151_PACTRL_CFG | CFG_ILOGIC_INIT_DIS);
379 /* FIXME: Uplink / Downlink Calibration */
382 void trf6151_power(int on)
384 if (on) {
385 trf6151_reg_write(REG_PWR, PWR_REGUL_ON | PWR_BANDGAP_ON);
386 /* wait until regulators are stable (25ms == 27100 qbits) */
387 tpu_enq_wait(5000);
388 tpu_enq_wait(5000);
389 tpu_enq_wait(5000);
390 tpu_enq_wait(5000);
391 tpu_enq_wait(5000);
392 tpu_enq_wait(2100);
393 } else
394 trf6151_reg_write(REG_PWR, PWR_BANDGAP_ON);
397 /* Set the operational mode of the TRF6151 chip */
398 void trf6151_set_mode(enum trf6151_mode mode)
400 uint16_t pwr = (PWR_REGUL_ON | PWR_BANDGAP_ON | (rf_band<<6));
402 switch (mode) {
403 case TRF6151_IDLE:
404 /* should we switch of the RF gain for power saving? */
405 break;
406 case TRF6151_RX:
407 pwr |= (PWR_SYNTHE_RX_ON | PWR_RX_MODE);
408 break;
409 case TRF6151_TX:
410 #if 0
411 pwr |= (PWR_SYNTHE_TX_ON | PWR_TX_MODE);
412 #else // Dieter: we should turn power control on (for TPU: check timing and order !)
413 pwr |= (PWR_SYNTHE_TX_ON | PWR_TX_MODE | PWR_PACTRL_APC | PWR_PACTRL_APCEN); // Dieter: TODO
414 #endif
415 break;
417 trf6151_reg_write(REG_PWR, pwr);
420 static void trf6151_band_select(enum trf6151_gsm_band band)
422 uint16_t pwr = trf6151_reg_cache[REG_PWR];
424 pwr &= ~(3 << 6);
425 pwr |= (band << 6);
427 trf6151_reg_write(REG_PWR, pwr);
430 /* Set ARFCN. Takes 2 reg_write, i.e. 8 TPU instructions */
431 void trf6151_set_arfcn(uint16_t arfcn, int tx)
433 uint32_t freq_khz;
434 uint16_t pll_config;
435 int uplink;
436 enum trf6151_gsm_band pll_band;
438 uplink = !!(arfcn & ARFCN_UPLINK);
439 arfcn != ~ARFCN_UPLINK;
441 switch (gsm_arfcn2band(arfcn)) {
442 case GSM_BAND_850:
443 case GSM_BAND_900:
444 case GSM_BAND_1800:
445 case GSM_BAND_1900:
446 /* Supported */
447 break;
448 case GSM_BAND_450:
449 case GSM_BAND_480:
450 case GSM_BAND_750:
451 case GSM_BAND_810:
452 printf("Unsupported band ! YMMV.\n");
453 break;
456 freq_khz = gsm_arfcn2freq10(arfcn, uplink) * 100;
457 printd("ARFCN %u -> %u kHz\n", arfcn, freq_khz);
459 if (!tx)
460 trf6151_pll_rx(freq_khz, &pll_config, &pll_band);
461 else
462 trf6151_pll_tx(freq_khz, &pll_config, &pll_band);
464 trf6151_band_select(pll_band);
465 trf6151_reg_write(REG_PLL, pll_config);
467 rf_band = pll_band;
468 rf_arfcn = arfcn; // TODO: arfcn is referenced at other places
471 void trf6151_calib_dc_offs(void)
473 uint16_t rx = trf6151_reg_cache[REG_RX];
475 /* Set RX CAL Mode bit, it will re-set automatically */
476 trf6151_reg_write(REG_RX, rx | RX_CAL_MODE);
477 /* DC offset calibration can take up to 50us, i.e. 54.16 * 923ns*/
478 tpu_enq_wait(55);
481 uint8_t trf6151_get_gain_reg(void)
483 uint16_t vga, reg_rx = trf6151_reg_cache[REG_RX];
484 uint8_t gain = 0;
486 switch ((reg_rx >> 9) & 3) {
487 case 0:
488 gain += TRF6151_FE_GAIN_LOW;
489 break;
490 case 3:
491 gain += TRF6151_FE_GAIN_HIGH;
492 break;
495 vga = (reg_rx >> RX_VGA_GAIN_SHIFT) & 0x1f;
496 if (vga < 6)
497 vga = 6;
499 gain += TRF6151_VGA_GAIN_MIN + (vga - 6) * 2;
501 return gain;
504 uint8_t trf6151_get_gain(void)
506 uint8_t gain;
508 gain = trf6151_vga_dbm;
509 if (trf6151_gain_high)
510 gain += TRF6151_FE_GAIN_HIGH;
511 else
512 gain += TRF6151_FE_GAIN_LOW;
514 return gain;
517 void trf6151_test(uint16_t arfcn)
519 /* Select ARFCN downlink */
520 trf6151_set_arfcn(arfcn, 0);
522 trf6151_set_mode(TRF6151_RX);
523 //trf6151_reg_write(REG_PWR, (PWR_SYNTHE_RX_ON | PWR_RX_MODE | PWR_REGUL_ON | (rf_band<<6) | PWR_BANDGAP_ON));
524 /* Wait for PLL stabilization (170us max) */
525 tpu_enq_wait(TRF6151_RX_PLL_DELAY);
527 /* Use DC offset calibration after RX mode has been switched on
528 * (might not be needed) */
529 trf6151_calib_dc_offs();
531 tpu_enq_sleep();
532 tpu_enable(1);
533 tpu_wait_idle();
536 void trf6151_tx_test(uint16_t arfcn)
538 /* Select ARFCN uplink */
539 trf6151_set_arfcn(arfcn | ARFCN_UPLINK, 1);
541 trf6151_set_mode(TRF6151_TX);
542 tpu_enq_wait(TRF6151_RX_PLL_DELAY);
544 tpu_enq_sleep();
545 tpu_enable(1);
546 tpu_wait_idle();
549 #define TRF6151_REGWR_QBITS 8 /* 4 GSM qbits + 4 TPU instructions */
550 #define TRF6151_RX_TPU_INSTR 4 /* set_gain_reg(1), set_arfcn(2), set_mode(1) */
552 /* delay caused by this driver programming the TPU for RX mode */
553 #define TRF6151_RX_TPU_DELAY (TRF6151_RX_TPU_INSTR * TRF6151_REGWR_QBITS)
555 /* prepare a Rx window with the TRF6151 finished at time 'start' (in qbits) */
556 void trf6151_rx_window(int16_t start_qbits, uint16_t arfcn)
558 int16_t start_pll_qbits;
560 /* power up at the right time _before_ the 'start_qbits' point in time */
561 start_pll_qbits = add_mod5000(start_qbits, -(TRF6151_RX_PLL_DELAY + TRF6151_RX_TPU_DELAY));
562 tpu_enq_at(start_pll_qbits);
564 /* Set the AGC and PLL registers */
565 trf6151_set_arfcn(arfcn, 0);
566 trf6151_set_gain_reg(trf6151_vga_dbm, trf6151_gain_high);
567 trf6151_set_mode(TRF6151_RX);
569 /* FIXME: power down at the right time again */
572 /* prepare a Tx window with the TRF6151 finished at time 'start' (in qbits) */
573 void trf6151_tx_window(int16_t start_qbits, uint16_t arfcn)
575 #ifdef CONFIG_TX_ENABLE
576 int16_t start_pll_qbits;
578 /* power up at the right time _before_ the 'start_qbits' point in time */
579 start_pll_qbits = add_mod5000(start_qbits, -(TRF6151_TX_PLL_DELAY + TRF6151_RX_TPU_DELAY));
580 tpu_enq_at(start_pll_qbits);
582 trf6151_set_arfcn(arfcn, 1);
583 trf6151_set_mode(TRF6151_TX);
585 /* FIXME: power down at the right time again */
586 #endif
589 /* Given the expected input level of exp_inp dBm and the target of target_bb
590 * dBm, configure the RF Frontend with the respective gain */
591 void trf6151_compute_gain(int16_t exp_inp, int16_t target_bb)
593 /* TRF6151 VGA gain between 14 to 40 dB, plus 20db high/low */
594 int16_t exp_bb, delta;
596 /* calculate the dBm8 that we expect at the baseband */
597 exp_bb = exp_inp + system_inherent_gain;
599 /* calculate the error that we expect. */
600 delta = target_bb - exp_bb;
602 printd("computed gain %d\n", delta);
603 trf6151_set_gain(delta);