Imported Upstream version 3.2.2
[debian/gnuradio] / usrp2 / firmware / lib / hal_io.c
diff --git a/usrp2/firmware/lib/hal_io.c b/usrp2/firmware/lib/hal_io.c
new file mode 100644 (file)
index 0000000..1a37068
--- /dev/null
@@ -0,0 +1,323 @@
+/* -*- c -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+// conditionalized on HAL_IO_USES_DBOARD_PINS && HAL_IO_USES_UART
+
+#include "hal_io.h"
+#include "memory_map.h"
+#include "hal_uart.h"
+#include "bool.h"
+#include <stdio.h>
+#include <string.h>
+//#include <assert.h>
+
+/*
+ * ========================================================================
+ *                                 GPIOS
+ * ========================================================================
+ */
+void 
+hal_gpio_set_ddr(int bank, int value, int mask)
+{
+  bank &= 0x1;
+
+  if (bank == GPIO_TX_BANK){   // tx in top half
+    value <<= 16;
+    mask <<= 16;
+  }
+  else {
+    value &= 0xffff;
+    mask &= 0xffff;
+  }
+
+  int ei = hal_disable_ints();
+  gpio_base->ddr = (gpio_base->ddr & ~mask) | (value & mask);
+  hal_restore_ints(ei);
+}
+
+static bool
+code_to_int(char code, int *val)
+{
+  switch(code){
+  case 's':    *val = GPIO_SEL_SW;      return true;
+  case 'a':    *val = GPIO_SEL_ATR;     return true;
+  case '0':    *val = GPIO_SEL_DEBUG_0; return true;
+  case '1':    *val = GPIO_SEL_DEBUG_1; return true;
+  case '.':    
+  default:
+    return false;
+  }
+}
+
+void
+hal_gpio_set_sel(int bank, int bitno, char code)
+{
+  bank &= 0x1;
+  int  t;
+
+  if (!code_to_int(code, &t))
+    return;
+
+  int val  =   t << (2 * bitno);
+  int mask = 0x3 << (2 * bitno);
+
+  volatile uint32_t *sel = bank == GPIO_TX_BANK ? &gpio_base->tx_sel : &gpio_base->rx_sel;
+  int ei = hal_disable_ints();
+  int v = (*sel & ~mask) | (val & mask);
+  *sel = v;
+  hal_restore_ints(ei);
+
+  if (0)
+    printf("hal_gpio_set_sel(bank=%d, bitno=%d, code=%c) *sel = 0x%x\n",
+          bank, bitno, code, v);
+}
+
+void
+hal_gpio_set_sels(int bank, char *codes)
+{
+  //assert(strlen(codes) == 16);
+
+  int val = 0;
+  int mask = 0;
+  int i;
+
+  for (i = 15; i >= 0; i--){
+    val <<= 2;
+    mask <<= 2;
+    int t;
+    if (code_to_int(codes[i], &t)){
+      val  |= t;
+      mask |= 0x3;
+    }
+  }
+
+  volatile uint32_t *sel = bank == GPIO_TX_BANK ? &gpio_base->tx_sel : &gpio_base->rx_sel;
+  int ei = hal_disable_ints();
+  *sel = (*sel & ~mask) | (val & mask);
+  hal_restore_ints(ei);
+}
+
+
+/*!
+ * \brief write \p value to gpio pins specified by \p mask.
+ */
+void
+hal_gpio_write(int bank, int value, int mask)
+{
+  static uint32_t      _gpio_io_shadow;
+
+  bank &= 0x1;
+
+  if (bank == GPIO_TX_BANK){   // tx in top half
+    value <<= 16;
+    mask <<= 16;
+  }
+  else {
+    value &= 0xffff;
+    mask &= 0xffff;
+  }
+
+  //int ei = hal_disable_ints();
+  _gpio_io_shadow = (_gpio_io_shadow & ~mask) | (value & mask);
+  gpio_base->io = _gpio_io_shadow;
+  //hal_restore_ints(ei);
+}
+
+
+/*!
+ * \brief read GPIO bits
+ */
+int
+hal_gpio_read(int bank)
+{
+  bank &= 0x1;
+  int r = gpio_base->io;
+  if (bank == GPIO_TX_BANK)
+    r >>= 16;
+
+  return r & 0xffff;
+}
+
+/*
+ * ========================================================================
+ *                             leds
+ * ========================================================================
+ */
+
+static unsigned long leds_shadow = 0;
+static unsigned long led_src_shadow = 0;
+
+void 
+hal_set_leds(int value, int mask)
+{
+  int ei = hal_disable_ints();
+  leds_shadow = (leds_shadow & ~mask) | (value & mask);
+  output_regs->leds = leds_shadow;
+  hal_restore_ints(ei);
+}
+
+// Allow hardware control over leds.  1 = hardware, 0 = software
+void 
+hal_set_led_src(int value, int mask)
+{
+  int ei = hal_disable_ints();
+  led_src_shadow = (led_src_shadow & ~mask) | (value & mask);
+  output_regs->led_src = led_src_shadow;
+  hal_restore_ints(ei);
+}
+
+void 
+hal_toggle_leds(int mask)
+{
+  int ei = hal_disable_ints();
+  leds_shadow ^= mask;
+  output_regs->leds = leds_shadow;
+  hal_restore_ints(ei);
+}
+
+
+// ================================================================
+//                             primitives
+// ================================================================
+
+#if defined(HAL_IO_USES_DBOARD_PINS)
+//
+// Does i/o using high 9-bits of rx daughterboard pins.
+//
+//  1 1 1 1 1 1
+//  5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// |      char     |W|             |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//
+// 
+// Asserts W when writing char
+//
+
+#define W      0x0080
+
+void
+hal_io_init(void)
+{
+  // make high 9 bits of tx daughterboard outputs
+  hal_gpio_set_rx_mode(15, 7, GPIOM_OUTPUT);
+
+  // and set them to zero
+  hal_gpio_set_rx(0x0000, 0xff80);
+}
+
+void
+hal_finish(void)
+{
+  volatile unsigned long *p = (unsigned long *) 0xC2F0;
+  *p = 0;
+}
+
+// %c
+inline int
+putchar(int ch)
+{
+  hal_gpio_set_rx((s << 8) | W, 0xff80);
+  hal_gpio_set_rx(0, 0xff80);
+  return ch;
+}
+
+#elif defined(HAL_IO_USES_UART)
+
+void
+hal_io_init(void)
+{
+  hal_uart_init();
+}
+
+void
+hal_finish(void)
+{
+}
+
+// %c
+inline int
+putchar(int ch)
+{
+  hal_uart_putc(ch);
+  return ch;
+}
+
+int
+getchar(void)
+{
+  return hal_uart_getc();
+}
+
+#else  // nop all i/o
+
+void
+hal_io_init(void)
+{
+}
+
+void
+hal_finish(void)
+{
+}
+
+// %c
+inline int
+putchar(int ch)
+{
+  return ch;
+}
+
+int
+getchar(void)
+{
+  return EOF;
+}
+
+#endif
+
+// ================================================================
+//             (slightly) higher level functions
+//
+// These are here so we can inline the calls to putchar.
+// The rest of the stuff was moved to nonstdio.c
+// ================================================================
+
+// \n
+inline void 
+newline(void)
+{
+  putchar('\n');
+}
+
+int
+putstr(const char *s)
+{
+  while (*s)
+    putchar(*s++);
+
+  return 0;
+}
+
+int
+puts(const char *s)
+{
+  putstr(s);
+  putchar('\n');
+  return 0;
+}