/* -*- 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 .
*/
// conditionalized on HAL_IO_USES_DBOARD_PINS && HAL_IO_USES_UART
#include "hal_io.h"
#include "memory_map.h"
#include "hal_uart.h"
#include
#include
#include
//#include
/*
* ========================================================================
* 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;
}