324 lines
8.8 KiB
C
324 lines
8.8 KiB
C
/****************************************************************************
|
|
* arch/arm/src/tms570/tms570_gio.c
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <stdint.h>
|
|
#include <time.h>
|
|
#include <errno.h>
|
|
#include <debug.h>
|
|
|
|
#include <nuttx/irq.h>
|
|
#include <nuttx/arch.h>
|
|
#include <arch/board/board.h>
|
|
|
|
#include "arm_internal.h"
|
|
#include "arm_arch.h"
|
|
|
|
#include "hardware/tms570_gio.h"
|
|
#include "tms570_gio.h"
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
#ifdef CONFIG_DEBUG_GPIO_INFO
|
|
static const char g_portchar[TMS570_NPORTS] =
|
|
{
|
|
'A'
|
|
#if TMS570_NPORTS > 1
|
|
, 'B'
|
|
#endif
|
|
#if TMS570_NPORTS > 2
|
|
, 'C'
|
|
#endif
|
|
#if TMS570_NPORTS > 3
|
|
, 'D'
|
|
#endif
|
|
#if TMS570_NPORTS > 4
|
|
, 'E'
|
|
#endif
|
|
#if TMS570_NPORTS > 5
|
|
, 'F'
|
|
#endif
|
|
#if TMS570_NPORTS > 6
|
|
, 'G'
|
|
#endif
|
|
#if TMS570_NPORTS > 7
|
|
, 'H'
|
|
#endif
|
|
};
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: tms570_gio_initialize
|
|
*
|
|
* Description:
|
|
* Take the GIO block out of reset and assure that it is ready for use.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int tms570_gio_initialize(void)
|
|
{
|
|
/* Take the GIO block out of reset */
|
|
|
|
putreg32(GIO_GCR0_RESET, TMS570_GIO_GCR0);
|
|
|
|
/* Disable all pin interrupts on the pin.
|
|
* Make sure they are all level 0.
|
|
*/
|
|
|
|
putreg32(0xffffffff, TMS570_GIO_ENACLR);
|
|
putreg32(0xffffffff, TMS570_GIO_LVLCLR);
|
|
return OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: tms570_configgio
|
|
*
|
|
* Description:
|
|
* Configure a GIO pin based on bit-encoded description of the pin.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int tms570_configgio(gio_pinset_t cfgset)
|
|
{
|
|
uint32_t port = tms570_gio_port(cfgset);
|
|
uintptr_t base = tms570_gio_base(cfgset);
|
|
uint32_t pin = tms570_gio_pin(cfgset);
|
|
uint32_t pinmask = tms570_gio_pinmask(cfgset);
|
|
uint32_t regval;
|
|
irqstate_t flags;
|
|
|
|
/* Disable interrupts to prohibit re-entrance. */
|
|
|
|
flags = enter_critical_section();
|
|
|
|
/* Force the pin to be an input for now */
|
|
|
|
regval = getreg32(base + TMS570_GIO_DIR_OFFSET);
|
|
regval &= ~pinmask;
|
|
putreg32(regval, base + TMS570_GIO_DIR_OFFSET);
|
|
|
|
/* Disable interrupts on the pin. Make sure this is a level 0 pin. */
|
|
|
|
putreg32(GIO_ENACLR_PORT_PIN(port, pin), TMS570_GIO_ENACLR);
|
|
putreg32(GIO_LVLCLR_PORT_PIN(port, pin), TMS570_GIO_LVLCLR);
|
|
|
|
/* Setup settings common to both input and output pins */
|
|
|
|
/* Enable/disable the pull-up/down as requested */
|
|
|
|
switch (cfgset & GIO_CFG_MASK)
|
|
{
|
|
case GIO_CFG_DEFAULT: /* Default, no attribute */
|
|
default:
|
|
{
|
|
/* Disable pull functionality */
|
|
|
|
regval = getreg32(base + TMS570_GIO_PULDIS_OFFSET);
|
|
regval &= ~pinmask;
|
|
putreg32(regval, base + TMS570_GIO_PULDIS_OFFSET);
|
|
}
|
|
break;
|
|
|
|
case GIO_CFG_PULLUP: /* Internal pull-up */
|
|
{
|
|
/* Select pull-up */
|
|
|
|
regval = getreg32(base + TMS570_GIO_PSL_OFFSET);
|
|
regval |= pinmask;
|
|
putreg32(regval, base + TMS570_GIO_PSL_OFFSET);
|
|
|
|
/* Enable pull functionality */
|
|
|
|
regval = getreg32(base + TMS570_GIO_PULDIS_OFFSET);
|
|
regval |= pinmask;
|
|
putreg32(regval, base + TMS570_GIO_PULDIS_OFFSET);
|
|
}
|
|
break;
|
|
|
|
case GIO_CFG_PULLDOWN: /* Internal pull-down */
|
|
{
|
|
/* Select pull-down */
|
|
|
|
regval = getreg32(base + TMS570_GIO_PSL_OFFSET);
|
|
regval |= pinmask;
|
|
putreg32(regval, base + TMS570_GIO_PSL_OFFSET);
|
|
|
|
/* Enable pull functionality */
|
|
|
|
regval = getreg32(base + TMS570_GIO_DIR_OFFSET);
|
|
regval |= pinmask;
|
|
putreg32(regval, base + TMS570_GIO_DIR_OFFSET);
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* Then do unique operations for an output pin */
|
|
|
|
if ((cfgset & GIO_MODE_MASK) == GIO_OUTPUT)
|
|
{
|
|
/* Enable the open drain driver if requested */
|
|
|
|
regval = getreg32(base + TMS570_GIO_PDR_OFFSET);
|
|
if ((cfgset & GIO_OPENDRAIN) != 0)
|
|
{
|
|
regval |= pinmask;
|
|
}
|
|
else
|
|
{
|
|
regval &= ~pinmask;
|
|
}
|
|
|
|
putreg32(regval, base + TMS570_GIO_PDR_OFFSET);
|
|
|
|
/* Set default output value */
|
|
|
|
if ((cfgset & GIO_OUTPUT_SET) != 0)
|
|
{
|
|
putreg32(pinmask, base + TMS570_GIO_DSET_OFFSET);
|
|
}
|
|
else
|
|
{
|
|
putreg32(pinmask, base + TMS570_GIO_DCLR_OFFSET);
|
|
}
|
|
|
|
/* Finally, configure the pin as an output */
|
|
|
|
regval = getreg32(base + TMS570_GIO_DIR_OFFSET);
|
|
regval |= pinmask;
|
|
putreg32(regval, base + TMS570_GIO_DIR_OFFSET);
|
|
}
|
|
|
|
leave_critical_section(flags);
|
|
return OK;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: tms570_giowrite
|
|
*
|
|
* Description:
|
|
* Write one or zero to the selected GIO pin
|
|
*
|
|
****************************************************************************/
|
|
|
|
void tms570_giowrite(gio_pinset_t pinset, bool value)
|
|
{
|
|
uintptr_t base = tms570_gio_base(pinset);
|
|
uint32_t pinmask = tms570_gio_pinmask(pinset);
|
|
|
|
if (value)
|
|
{
|
|
putreg32(pinmask, base + TMS570_GIO_DSET_OFFSET);
|
|
}
|
|
else
|
|
{
|
|
putreg32(pinmask, base + TMS570_GIO_DCLR_OFFSET);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: tms570_gioread
|
|
*
|
|
* Description:
|
|
* Read one or zero from the selected GIO pin
|
|
*
|
|
****************************************************************************/
|
|
|
|
bool tms570_gioread(gio_pinset_t pinset)
|
|
{
|
|
uintptr_t base = tms570_gio_base(pinset);
|
|
uint32_t pinmask = tms570_gio_pinmask(pinset);
|
|
uint32_t regval;
|
|
|
|
if ((pinset & GIO_MODE_MASK) == GIO_OUTPUT)
|
|
{
|
|
regval = getreg32(base + TMS570_GIO_DOUT_OFFSET);
|
|
}
|
|
else
|
|
{
|
|
regval = getreg32(base + TMS570_GIO_DIN_OFFSET);
|
|
}
|
|
|
|
return (regval & pinmask) != 0;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Function: tms570_dumpgio
|
|
*
|
|
* Description:
|
|
* Dump all GIO registers associated with the base address of the provided
|
|
* pinset.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#ifdef CONFIG_DEBUG_GPIO_INFO
|
|
int tms570_dumpgio(uint32_t pinset, const char *msg)
|
|
{
|
|
irqstate_t flags;
|
|
uintptr_t base;
|
|
unsigned int port;
|
|
|
|
_info("GIO%c pinset: %08x base: %08x -- %s\n",
|
|
g_portchar[port], pinset, base, msg);
|
|
|
|
/* Get the base address associated with the GIO port */
|
|
|
|
port = (pinset & GIO_PORT_MASK) >> GIO_PORT_SHIFT;
|
|
base = TMS570_GIO_PORTBASE(port);
|
|
|
|
/* The following requires exclusive access to the GIO registers */
|
|
|
|
flags = enter_critical_section();
|
|
|
|
/* Show global GIO registers */
|
|
|
|
_info(" GCR0: %08x INTDET: %08x POL: %08x ENA: %08x\n",
|
|
getreg32(TMS570_GIO_GCR0), getreg32(TMS570_GIO_INTDET),
|
|
getreg32(TMS570_GIO_POL), getreg32(TMS570_GIO_ENASET));
|
|
_info(" LVL: %08x FLG: %08x EMU1: %08x EMU2: %08x\n",
|
|
getreg32(TMS570_GIO_LVLSET), getreg32(TMS570_GIO_FLG),
|
|
getreg32(TMS570_GIO_EMU1), getreg32(TMS570_GIO_EMU2));
|
|
|
|
/* Port specific registers */
|
|
|
|
_info(" DIR: %08x DIN: %08x DOUT: %08x PDR: %08x\n",
|
|
getreg32(base + TMS570_GIO_DIR_OFFSET),
|
|
getreg32(base + TMS570_GIO_DIN_OFFSET),
|
|
getreg32(base + TMS570_GIO_DOUT_OFFSET),
|
|
getreg32(base + TMS570_GIO_PDR_OFFSET));
|
|
_info(" PULDIS: %08x PSL: %08x\n",
|
|
getreg32(base + TMS570_GIO_PULDIS_OFFSET),
|
|
getreg32(base + TMS570_GIO_PSL_OFFSET));
|
|
|
|
leave_critical_section(flags);
|
|
return OK;
|
|
}
|
|
#endif
|