src: use new libosmogsm and include/osmocom/[gsm|core] path to headers
[osmocom-bb.git] / src / target / firmware / rf / trf6151.c
1 /* Driver for RF Transceiver Circuit (TRF6151) */
2
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
4  *
5  * All Rights Reserved
6  *
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.
11  *
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.
16  *
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.
20  *
21  */
22
23 #include <stdint.h>
24 #include <stdio.h>
25
26 #include <debug.h>
27 #include <memory.h>
28 #include <keypad.h>
29 #include <osmocom/gsm/gsm_utils.h>
30
31 #include <calypso/tpu.h>
32 #include <calypso/tsp.h>
33 #include <layer1/agc.h>
34 #include <rffe.h>
35
36 #include <rf/trf6151.h>
37
38 enum trf6151_reg {
39         REG_RX          = 0,    /* RF general settings */
40         REG_PLL         = 1,    /* PLL settings */
41         REG_PWR         = 2,    /* Power on/off functional blocks */
42         REG_CFG         = 3,    /* Transceiver and PA controller settings */
43         REG_TEST1       = 4,
44         REG_TEST2       = 5,
45         REG_TEST3       = 6,
46         REG_TEST4       = 7,
47         _MAX_REG
48 };
49
50 /* REG_RX */
51 #define RX_READ_EN              (1 << 7)
52 #define RX_CAL_MODE             (1 << 8)
53 #define RX_RF_GAIN_HIGH         (3 << 9)
54 #define RX_VGA_GAIN_SHIFT       11
55
56 /* REG_PWR */
57 #define PWR_BANDGAP_SHIFT       3
58 #define PWR_BANDGAP_OFF         (0 << PWR_BANDGAP_SHIFT)
59 #define PWR_BANDGAP_ON_SPEEDUP  (2 << PWR_BANDGAP_SHIFT)
60 #define PWR_BANDGAP_ON          (3 << PWR_BANDGAP_SHIFT)
61 #define PWR_REGUL_ON            (1 << 5)
62 #define PWR_SYNTHE_OFF          (0)
63 #define PWR_SYNTHE_RX_ON        (1 << 9)
64 #define PWR_SYNTHE_TX_ON        (1 << 10)
65 #define PWR_RX_MODE             (1 << 11)
66 #define PWR_TX_MODE             (1 << 13)
67 #define PWR_PACTRL_APC          (1 << 14)
68 #define PWR_PACTRL_APCEN        (1 << 15)
69
70 /* REG_CFG */
71 #define CFG_TX_LOOP_MANU        (1 << 3)
72 #define CFG_PACTLR_IDIOD_30uA   (0 << 4)
73 #define CFG_PACTLR_IDIOD_300uA  (1 << 4)
74 #define CFG_PACTLR_RES_OPEN     (0 << 10)
75 #define CFG_PACTLR_RES_150k     (1 << 10)
76 #define CFG_PACTLR_RES_300k     (2 << 10)
77 #define CFG_PACTLR_CAP_0pF      (0 << 12)
78 #define CFG_PACTLR_CAP_12p5F    (1 << 12)
79 #define CFG_PACTLR_CAP_25pF     (3 << 12)
80 #define CFG_PACTLR_CAP_50pF     (2 << 12)
81 #define CFG_TEMP_SENSOR         (1 << 14)
82 #define CFG_ILOGIC_INIT_DIS     (1 << 15)
83
84 /* FIXME: This must be defined in the RFFE configuration */
85 #define TRF6151_TSP_UID         2
86 #define TRF6151_PACTRL_CFG      (CFG_PACTLR_RES_OPEN|CFG_PACTLR_CAP_0pF|CFG_PACTLR_IDIOD_30uA)
87
88 #define PLL_VAL(a, b)   ((a << 3) | (((b)-64) << 9))
89
90 /* All values in qbits unless otherwise specified */
91 #define TRF6151_LDO_DELAY_TS    6       /* six TDMA frames (at least 25ms) */
92 #define TRF6151_RX_PLL_DELAY    184     /* 170 us */
93 #define TRF6151_TX_PLL_DELAY    260     /* 240 us */
94
95 uint16_t rf_arfcn = 871;        /* TODO: this needs to be private */
96 static uint16_t rf_band;
97
98 static uint8_t trf6151_tsp_uid;
99 static uint8_t trf6151_vga_dbm = 40;
100 static int trf6151_gain_high = 1;
101
102 static uint16_t trf6151_reg_cache[_MAX_REG] = {
103         [REG_RX]        = 0x9E00,
104         [REG_PLL]       = 0x0000,
105         [REG_PWR]       = 0x0000,
106         [REG_CFG]       = 0x2980,
107 };
108
109 /* Write to a TRF6151 register (4 TPU instructions) */
110 static void trf6151_reg_write(uint16_t reg, uint16_t val)
111 {
112         printd("trf6151_reg_write(reg=%u, val=0x%04x)\n", reg, val);
113         /* each TSP write takes 4 TPU instructions */
114         tsp_write(trf6151_tsp_uid, 16, (reg | val));
115         trf6151_reg_cache[reg] = val;
116 }
117
118 int trf6151_set_gain(uint8_t dbm, int high)
119 {
120         uint16_t reg = trf6151_reg_cache[REG_RX] & 0x07ff;
121         printd("trf6151_set_gain(%u, %d)\n", dbm, high);
122
123         if (dbm < 14 || dbm > 40)
124                 return -1;
125
126         /* clear the gain bits first */
127         reg &= ~((0x1F) << RX_VGA_GAIN_SHIFT);
128         /* OR-in the new gain value */
129         reg |= (6 + (dbm-14)/2) << RX_VGA_GAIN_SHIFT;
130
131         if (high)
132                 reg |= RX_RF_GAIN_HIGH;
133         else
134                 reg &= ~RX_RF_GAIN_HIGH;
135
136         trf6151_reg_write(REG_RX, reg);
137
138         return 0;
139 }
140
141 #define SCALE_100KHZ    100
142
143 /* Compute TRF6151 PLL valuese for all 4 RX bands */
144 static uint16_t trf6151_pll_rx(uint32_t freq_khz)
145 {
146         uint32_t freq_100khz = freq_khz / SCALE_100KHZ; /* Scale from *1000 (k) to *100000 (0.1M) */
147         uint32_t fb_100khz;     /* frequency of B alone, without A (units of 100kHz) */
148         uint32_t l;
149         uint32_t a, b;  /* The PLL multipliers we want to compute */
150
151         /* L = 4 for low band, 2 for high band */
152         if (freq_khz < 1000000)
153                 l = 4;
154         else
155                 l = 2;
156
157         /* To compute B, we assume A is zero */
158         b = (freq_100khz * 65 * l) / (64 * 26 * 10);
159
160         if ((l == 4 && (b < 135 || b > 150)) ||
161             (l == 2 && (b < 141 || b > 155)))
162                 printf("Frequency %u kHz is out of spec\n", freq_khz);
163
164         /* Compute PLL frequency assuming A == 0 */
165         fb_100khz = (b * 64 * 26 * 10) / (65 * l);
166
167         /* Compute how many 100kHz units A needs to add */
168         a = freq_100khz - fb_100khz;
169
170         if (l == 2)
171                 a = a / 2;
172
173         /* since all frequencies are expanded a factor of 10, we don't need to multiply A */
174         printd("Freq %u kHz => A = %u, B = %u\n", freq_khz, a, b);
175
176         /* return value in trf6151 register layout form */
177         return PLL_VAL(a, b);
178 }
179
180 /* Compute TRF6151 PLL TX values for GSM900 and GSM1800 only! */
181 static uint16_t trf6151_pll_tx(uint32_t freq_khz)
182 {
183         uint32_t freq_100khz = freq_khz / SCALE_100KHZ; /* Scale from *1000 (k) to *100000 (0.1M) */
184         uint32_t fb_100khz;     /* frequency of B alone, without A (units of 100kHz) */
185         uint32_t l, r, m;
186         uint32_t a, b;  /* The PLL multipliers we want to compute */
187
188         /* L = 4 for low band, 2 for high band */
189         if (freq_khz < 1000000) {
190                 r = 35;
191                 l = 4;
192                 m = 52;
193         } else {
194                 r = 70;
195                 l = 2;
196                 m = 26;
197         }
198
199         /* To compute B, we assume A is zero */
200         b = (freq_100khz * r * l * m) / (64 * 26 * 10 * (m + l));
201
202         if ((l == 4 && (b <  68 || b >  71)) ||
203             (l == 2 && (b < 133 || b > 149)))
204                 printf("Frequency %u kHz is out of spec\n", freq_khz);
205
206         /* Compute PLL frequency assuming A == 0 */
207         fb_100khz = (b * 64 * 26 * 10 * (m + l)) / (r * l * m);
208
209         /* Compute how many 100kHz units A needs to add */
210         a = freq_100khz - fb_100khz;
211
212         a = a / 2;
213
214         /* since all frequencies are expanded a factor of 10, we don't need to multiply A */
215         printd("Freq %u kHz => A = %u, B = %u\n", freq_khz, a, b);
216
217         /* return value in trf6151 register layout form */
218         return PLL_VAL(a, b);
219 }
220
221 enum trf6151_pwr_unit {
222         TRF1651_PACTLR_APC,
223         TRF6151_PACTRL_APCEN,
224         TRF6151_TRANSMITTER,
225         TRF6151_REGULATORS,
226 };
227
228 enum trf6151_gsm_band {
229         GSM900          = 1,
230         GSM1800         = 2,
231         GSM850_LOW      = 4,
232         GSM850_HIGH     = 5,
233         GSM1900         = 6,
234 };
235
236 static inline void trf6151_reset(uint16_t reset_id)
237 {
238         /* pull the nRESET line low */
239         tsp_act_disable(reset_id);
240         tpu_enq_wait(50);
241         /* release nRESET */
242         tsp_act_enable(reset_id);
243 }
244
245 void trf6151_init(uint8_t tsp_uid, uint16_t tsp_reset_id)
246 {
247         trf6151_tsp_uid = tsp_uid;
248
249         /* Configure the TSPEN which is connected to TRF6151 STROBE */
250         tsp_setup(trf6151_tsp_uid, 0, 1, 1);
251
252         trf6151_reset(tsp_reset_id);
253
254         /* configure TRF6151 for operation */
255         trf6151_power(1);
256         trf6151_reg_write(REG_CFG, TRF6151_PACTRL_CFG | CFG_ILOGIC_INIT_DIS);
257
258         /* FIXME: Uplink / Downlink Calibration */
259 }
260
261 void trf6151_power(int on)
262 {
263         if (on) {
264                 trf6151_reg_write(REG_PWR, PWR_REGUL_ON | PWR_BANDGAP_ON);
265                 /* wait until regulators are stable (25ms == 27100 qbits) */
266                 tpu_enq_wait(5000);
267                 tpu_enq_wait(5000);
268                 tpu_enq_wait(5000);
269                 tpu_enq_wait(5000);
270                 tpu_enq_wait(5000);
271                 tpu_enq_wait(2100);
272         } else
273                 trf6151_reg_write(REG_PWR, PWR_BANDGAP_ON);
274 }
275
276 /* Set the operational mode of the TRF6151 chip */
277 void trf6151_set_mode(enum trf6151_mode mode)
278 {
279         uint16_t pwr = (PWR_REGUL_ON | PWR_BANDGAP_ON | (rf_band<<6));
280
281         switch (mode) {
282         case TRF6151_IDLE:
283                 /* should we switch of the RF gain for power saving? */
284                 break;
285         case TRF6151_RX:
286                 pwr |= (PWR_SYNTHE_RX_ON | PWR_RX_MODE);
287                 break;
288         case TRF6151_TX:
289 #if 0
290                 pwr |= (PWR_SYNTHE_TX_ON | PWR_TX_MODE);
291 #else // Dieter: we should turn power control on (for TPU: check timing and order !)
292                 pwr |= (PWR_SYNTHE_TX_ON | PWR_TX_MODE | PWR_PACTRL_APC | PWR_PACTRL_APCEN); // Dieter: TODO
293 #endif
294                 break;
295         }
296         trf6151_reg_write(REG_PWR, pwr);
297 }
298
299 static void trf6151_band_select(enum trf6151_gsm_band band)
300 {
301         uint16_t pwr = trf6151_reg_cache[REG_PWR];
302
303         pwr &= ~(3 << 6);
304         pwr |= (band << 6);
305
306         trf6151_reg_write(REG_PWR, pwr);
307 }
308
309 /* Set ARFCN.  Takes 2 reg_write, i.e. 8 TPU instructions */
310 void trf6151_set_arfcn(uint16_t arfcn, int uplink)
311 {
312         uint32_t freq_khz;
313
314         switch (gsm_arfcn2band(arfcn)) {
315         case GSM_BAND_850:
316                 rf_band = GSM850_LOW;   /* FIXME: what about HIGH */
317                 break;
318         case GSM_BAND_900:
319                 rf_band = GSM900;
320                 break;
321         case GSM_BAND_1800:
322                 rf_band = GSM1800;
323                 break;
324         case GSM_BAND_1900:
325                 rf_band = GSM1900;
326                 break;
327         case GSM_BAND_450:
328         case GSM_BAND_480:
329         case GSM_BAND_750:
330         case GSM_BAND_810:
331                 printf("Unsupported rf_band.\n");
332                 break;
333         }
334
335         trf6151_band_select(rf_band);
336
337         freq_khz = gsm_arfcn2freq10(arfcn, uplink) * 100;
338         printd("ARFCN %u -> %u kHz\n", arfcn, freq_khz);
339
340         if (uplink == 0)
341                 trf6151_reg_write(REG_PLL, trf6151_pll_rx(freq_khz));
342         else {
343                 if (rf_band != GSM900 && rf_band != GSM1800) {
344                         printf("TX only supports GSM900/1800\n");
345                         return;
346                 }
347                 trf6151_reg_write(REG_PLL, trf6151_pll_tx(freq_khz));
348         }
349
350         rf_arfcn = arfcn; // TODO: arfcn is referenced at other places
351 }
352
353 void trf6151_calib_dc_offs(void)
354 {
355         uint16_t rx = trf6151_reg_cache[REG_RX];
356
357         /* Set RX CAL Mode bit, it will re-set automatically */
358         trf6151_reg_write(REG_RX, rx | RX_CAL_MODE);
359         /* DC offset calibration can take up to 50us, i.e. 54.16 * 923ns*/
360         tpu_enq_wait(55);
361 }
362
363 /* Frontend gain can be switched high or low (dB) */
364 #define TRF6151_FE_GAIN_LOW     7
365 #define TRF6151_FE_GAIN_HIGH    27
366
367 /* VGA at baseband can be adjusted in this range (dB) */
368 #define TRF6151_VGA_GAIN_MIN    14
369 #define TRF6151_VGA_GAIN_MAX    40
370
371 uint8_t trf6151_get_gain(void)
372 {
373         uint16_t vga, reg_rx = trf6151_reg_cache[REG_RX];
374         uint8_t gain = 0;
375
376         switch ((reg_rx >> 9) & 3) {
377         case 0:
378                 gain += TRF6151_FE_GAIN_LOW;
379                 break;
380         case 3:
381                 gain += TRF6151_FE_GAIN_HIGH;
382                 break;
383         }
384
385         vga = (reg_rx >> RX_VGA_GAIN_SHIFT) & 0x1f;
386         if (vga < 6)
387                 vga = 6;
388
389         gain += TRF6151_VGA_GAIN_MIN + (vga - 6) * 2;
390
391         return gain;
392 }
393
394 void trf6151_test(uint16_t arfcn)
395 {
396         /* Select ARFCN 871 downlink */
397         trf6151_set_arfcn(arfcn, 0);
398
399         trf6151_set_mode(TRF6151_RX);
400         //trf6151_reg_write(REG_PWR, (PWR_SYNTHE_RX_ON | PWR_RX_MODE | PWR_REGUL_ON | (rf_band<<6) | PWR_BANDGAP_ON));
401         /* Wait for PLL stabilization (170us max) */
402         tpu_enq_wait(TRF6151_RX_PLL_DELAY);
403
404         /* Use DC offset calibration after RX mode has been switched on
405          * (might not be needed) */
406         trf6151_calib_dc_offs();
407
408         tpu_enq_sleep();
409         tpu_enable(1);
410         tpu_wait_idle();
411 }
412
413 void trf6151_tx_test(uint16_t arfcn)
414 {
415         /* Select ARFCN uplink */
416         trf6151_set_arfcn(arfcn, 1);
417
418         trf6151_set_mode(TRF6151_TX);
419         tpu_enq_wait(TRF6151_RX_PLL_DELAY);
420
421         tpu_enq_sleep();
422         tpu_enable(1);
423         tpu_wait_idle();
424 }
425
426 #define TRF6151_REGWR_QBITS     8       /* 4 GSM qbits + 4 TPU instructions */
427 #define TRF6151_RX_TPU_INSTR    4       /* set_gain(1), set_arfcn(2), set_mode(1) */
428
429 /* delay caused by this driver programming the TPU for RX mode */
430 #define TRF6151_RX_TPU_DELAY    (TRF6151_RX_TPU_INSTR * TRF6151_REGWR_QBITS)
431
432 /* prepare a Rx window with the TRF6151 finished at time 'start' (in qbits) */
433 void trf6151_rx_window(int16_t start_qbits, uint16_t arfcn)
434 {
435         int16_t start_pll_qbits;
436
437         /* power up at the right time _before_ the 'start_qbits' point in time */
438         start_pll_qbits = add_mod5000(start_qbits,  -(TRF6151_RX_PLL_DELAY + TRF6151_RX_TPU_DELAY));
439         tpu_enq_at(start_pll_qbits);
440
441         /* Set the AGC and PLL registers */
442         trf6151_set_arfcn(arfcn, 0);
443         trf6151_set_gain(trf6151_vga_dbm, trf6151_gain_high);
444         trf6151_set_mode(TRF6151_RX);
445
446         /* FIXME: power down at the right time again */
447 }
448
449 /* prepare a Tx window with the TRF6151 finished at time 'start' (in qbits) */
450 void trf6151_tx_window(int16_t start_qbits, uint16_t arfcn)
451 {
452 #ifdef CONFIG_TX_ENABLE
453         int16_t start_pll_qbits;
454
455         /* power up at the right time _before_ the 'start_qbits' point in time */
456         start_pll_qbits = add_mod5000(start_qbits,  -(TRF6151_TX_PLL_DELAY + TRF6151_RX_TPU_DELAY));
457         tpu_enq_at(start_pll_qbits);
458
459         trf6151_set_arfcn(arfcn, 1);
460         trf6151_set_mode(TRF6151_TX);
461
462         /* FIXME: power down at the right time again */
463 #endif
464 }
465
466 /* Given the expected input level of exp_inp dBm and the target of target_bb
467  * dBm, configure the RF Frontend with the respective gain */
468 void trf6151_compute_gain(int16_t exp_inp, int16_t target_bb)
469 {
470         /* TRF6151 VGA gain between 14 to 40 dB, plus 20db high/low */
471         int16_t exp_bb_dbm8, delta_dbm8;
472         int16_t exp_inp_dbm8 = to_dbm8(exp_inp);
473         int16_t target_bb_dbm8 = to_dbm8(target_bb);
474         int16_t vga_gain = TRF6151_VGA_GAIN_MIN;
475         int high = 0;
476
477         /* calculate the dBm8 that we expect at the baseband */
478         exp_bb_dbm8 = exp_inp_dbm8 + to_dbm8(system_inherent_gain);
479
480         /* calculate the error that we expect. */
481         delta_dbm8 = target_bb_dbm8 - exp_bb_dbm8;
482
483         /* If this is negative or less than TRF6151_GAIN_MIN, we are pretty
484          * much lost as we cannot reduce the system inherent gain.  If it is
485          * positive, it corresponds to the gain that we need to configure */
486         if (delta_dbm8 < to_dbm8(TRF6151_FE_GAIN_LOW + TRF6151_VGA_GAIN_MIN)) {
487                 printd("AGC Input level overflow\n");
488                 high = 0;
489                 vga_gain = TRF6151_VGA_GAIN_MIN;
490         } else if (delta_dbm8 > to_dbm8(TRF6151_FE_GAIN_HIGH +
491                                         TRF6151_VGA_GAIN_MIN)) {
492                 high = 1;
493                 delta_dbm8 -= to_dbm8(TRF6151_FE_GAIN_HIGH);
494         }
495         vga_gain = delta_dbm8/8;
496         if (vga_gain > TRF6151_VGA_GAIN_MAX)
497                 vga_gain = TRF6151_VGA_GAIN_MAX;
498
499         /* update the static global variables which are used when programming
500          * the window */
501         trf6151_vga_dbm = vga_gain;
502         trf6151_gain_high = high;
503 }