1 /* Calypso DBB internal TPU (Time Processing Unit) Driver */
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
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.
29 #include <calypso/tpu.h>
30 #include <calypso/tsp.h>
32 #define BASE_ADDR_TPU 0xffff1000
33 #define TPU_REG(x) (BASE_ADDR_TPU+(x))
35 #define BASE_ADDR_TPU_RAM 0xffff9000
36 #define TPU_RAM_END 0xffff97ff
39 TPU_CTRL = 0x0, /* Control & Status Register */
40 INT_CTRL = 0x2, /* Interrupt Control Register */
41 INT_STAT = 0x4, /* Interrupt Status Register */
42 TPU_OFFSET = 0xC, /* Offset operand value register */
43 TPU_SYNCHRO = 0xE, /* synchro operand value register */
48 TPU_CTRL_RESET = (1 << 0),
49 TPU_CTRL_PAGE = (1 << 1),
50 TPU_CTRL_EN = (1 << 2),
52 TPU_CTRL_DSP_EN = (1 << 4),
54 TPU_CTRL_MCU_RAM_ACC = (1 << 6),
55 TPU_CTRL_TSP_RESET = (1 << 7),
56 TPU_CTRL_IDLE = (1 << 8),
57 TPU_CTRL_WAIT = (1 << 9),
58 TPU_CTRL_CK_ENABLE = (1 << 10),
59 TPU_CTRL_FULL_WRITE = (1 << 11),
62 enum tpu_int_ctrl_bits {
63 ICTRL_MCU_FRAME = (1 << 0),
64 ICTRL_MCU_PAGE = (1 << 1),
65 ICTRL_DSP_FRAME = (1 << 2),
66 ICTRL_DSP_FRAME_FORCE = (1 << 3),
72 /* wait for a certain control bit to be set */
73 static int tpu_wait_ctrl_bit(uint16_t bit, int set)
75 int timeout = 10*1000;
78 uint16_t reg = readw(TPU_REG(TPU_CTRL));
88 puts("Timeout while waiting for TPU ctrl bit!\n");
96 /* assert or de-assert TPU reset */
97 void tpu_reset(int active)
101 printd("tpu_reset(%u)\n", active);
102 reg = readw(TPU_REG(TPU_CTRL));
104 reg |= (TPU_CTRL_RESET|TPU_CTRL_TSP_RESET);
105 writew(reg, TPU_REG(TPU_CTRL));
106 tpu_wait_ctrl_bit(TPU_CTRL_RESET, BIT_SET);
108 reg &= ~(TPU_CTRL_RESET|TPU_CTRL_TSP_RESET);
109 writew(reg, TPU_REG(TPU_CTRL));
110 tpu_wait_ctrl_bit(TPU_CTRL_RESET, BIT_CLEAR);
114 /* Enable or Disable a new scenario loaded into the TPU */
115 void tpu_enable(int active)
117 uint16_t reg = readw(TPU_REG(TPU_CTRL));
119 printd("tpu_enable(%u)\n", active);
124 writew(reg, TPU_REG(TPU_CTRL));
126 /* After the new scenario is loaded, TPU switches the MCU-visible memory
127 * page, i.e. we can write without any danger */
134 for (i = 0; i < 100000; i++) {
135 reg = readw(TPU_REG(TPU_CTRL));
136 if (i == 0 || oldreg != reg) {
137 printd("%d TPU state: 0x%04x\n", i, reg);
145 /* Enable or Disable the clock of teh TPU Module */
146 void tpu_clk_enable(int active)
148 uint16_t reg = readw(TPU_REG(TPU_CTRL));
150 printd("tpu_clk_enable(%u)\n", active);
152 reg |= TPU_CTRL_CK_ENABLE;
153 writew(reg, TPU_REG(TPU_CTRL));
154 tpu_wait_ctrl_bit(TPU_CTRL_CK_ENABLE, BIT_SET);
156 reg &= ~TPU_CTRL_CK_ENABLE;
157 writew(reg, TPU_REG(TPU_CTRL));
158 tpu_wait_ctrl_bit(TPU_CTRL_CK_ENABLE, BIT_CLEAR);
162 /* Enable Frame Interrupt generation on next frame. DSP will reset it */
163 void tpu_dsp_frameirq_enable(void)
165 uint16_t reg = readw(TPU_REG(TPU_CTRL));
166 reg |= TPU_CTRL_DSP_EN;
167 writew(reg, TPU_REG(TPU_CTRL));
169 tpu_wait_ctrl_bit(TPU_CTRL_DSP_EN, BIT_SET);
172 /* Is a Frame interrupt still pending for the DSP ? */
173 int tpu_dsp_fameirq_pending(void)
175 uint16_t reg = readw(TPU_REG(TPU_CTRL));
177 if (reg & TPU_CTRL_DSP_EN)
183 static uint16_t *tpu_ptr;
185 void tpu_rewind(void)
187 dputs("tpu_rewind()\n");
188 tpu_ptr = (uint16_t *) BASE_ADDR_TPU_RAM;
191 void tpu_enqueue(uint16_t instr)
193 printd("tpu_enqueue(tpu_ptr=%p, instr=0x%04x\n", tpu_ptr, instr);
195 if (tpu_ptr > (uint16_t *) TPU_RAM_END)
196 puts("TPU enqueue beyond end of TPU memory\n");
201 /* Get TPU out of reset */
205 /* Disable all interrupts */
206 writeb(0x7, TPU_REG(INT_CTRL));
217 /* program a sequence of TSPACT events into the TPU */
218 for (i = 0; i < 10; i++) {
219 puts("TSP ACT enable: ");
220 tsp_act_enable(0x0001);
222 puts("TSP ACT disable: ");
223 tsp_act_disable(0x0001);
228 /* tell the chip to execute the scenario */
232 void tpu_wait_idle(void)
234 dputs("Waiting for TPU Idle ");
235 /* Wait until TPU is doing something */
237 /* Wait until TPU is idle */
238 while (readw(TPU_REG(TPU_CTRL)) & TPU_CTRL_IDLE)
243 void tpu_frame_irq_en(int mcu, int dsp)
245 uint8_t reg = readb(TPU_REG(INT_CTRL));
247 reg &= ~ICTRL_MCU_FRAME;
249 reg |= ICTRL_MCU_FRAME;
252 reg &= ~ICTRL_DSP_FRAME;
254 reg |= ICTRL_DSP_FRAME;
256 writeb(reg, TPU_REG(INT_CTRL));
259 void tpu_force_dsp_frame_irq(void)
261 uint8_t reg = readb(TPU_REG(INT_CTRL));
262 reg |= ICTRL_DSP_FRAME_FORCE;
263 writeb(reg, TPU_REG(INT_CTRL));
266 uint16_t tpu_get_offset(void)
268 return readw(TPU_REG(TPU_OFFSET));
271 uint16_t tpu_get_synchro(void)
273 return readw(TPU_REG(TPU_SYNCHRO));
276 /* add two numbers, modulo 5000, and ensure the result is positive */
277 uint16_t add_mod5000(uint16_t a, uint16_t b)
279 int32_t sum = (uint32_t)a + (uint32_t)b;
283 /* wrap around zero */