mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
Merge c82a48d45b into 83ac26ba1c
This commit is contained in:
commit
b5a5187724
31 changed files with 3268 additions and 59 deletions
|
|
@ -18,10 +18,11 @@ Features
|
|||
* Four user LEDs
|
||||
* Gigabit Ethernet, USB, Wi-Fi, and Bluetooth hardware on the board
|
||||
|
||||
Current NuttX support is limited to early boot, the 16550 serial console,
|
||||
interactive NSH, and ``procfs`` mount during board bring-up. GPIO, LEDs,
|
||||
I2C, SPI, MMC/SD, Ethernet, Wi-Fi, Bluetooth, and USB runtime support are
|
||||
not implemented yet.
|
||||
Current NuttX support includes early boot, the 16550 serial console,
|
||||
interactive NSH, ``procfs`` mount during board bring-up, AM62x TISCI
|
||||
initialization, main-domain GPIO, and I2C0/I2C1 controller support in the
|
||||
``beagleplay:i2c`` configuration. SPI, MMC/SD, Ethernet, Wi-Fi, Bluetooth,
|
||||
and USB runtime support are not implemented yet.
|
||||
|
||||
Buttons and LEDs
|
||||
================
|
||||
|
|
@ -37,8 +38,8 @@ USR2 GPIO1_24 Red user LED
|
|||
USR3 GPIO1_25 Blue user LED
|
||||
====== ======== ==================
|
||||
|
||||
The current NuttX port does not yet provide functional GPIO-backed LED
|
||||
control. The ``CONFIG_ARCH_LEDS`` hooks are present as placeholders only.
|
||||
The current NuttX port initializes the AM62x GPIO controller. Automatic
|
||||
``CONFIG_ARCH_LEDS`` LED hooks remain placeholders only.
|
||||
|
||||
Serial Console
|
||||
==============
|
||||
|
|
@ -57,7 +58,9 @@ Interface SoC signal Notes
|
|||
=========== ====================== =======================================
|
||||
DEBUG USB-C UART0 Default NuttX serial console
|
||||
microSD MMC1 Validated boot media for ``nuttx.bin``
|
||||
USR0-3 GPIO1_22 through 1_25 User LEDs, not yet driven by NuttX
|
||||
USR0-3 GPIO1_22 through 1_25 User LEDs on the main GPIO block
|
||||
I2C0 I2C0 Available in ``beagleplay:i2c``
|
||||
I2C1 I2C1 Available in ``beagleplay:i2c``
|
||||
=========== ====================== =======================================
|
||||
|
||||
Power Supply
|
||||
|
|
@ -113,8 +116,23 @@ microSD using the BeaglePlay U-Boot prompt.
|
|||
Configurations
|
||||
==============
|
||||
|
||||
``beagleplay:nsh``
|
||||
Interactive NSH configuration for serial bring-up and shell access.
|
||||
Configure NuttX with ``beagleplay:<config-name>``.
|
||||
|
||||
``beagleplay:ostest``
|
||||
Hardware validation configuration that boots directly into ``ostest_main``.
|
||||
.. code:: console
|
||||
|
||||
$ ./tools/configure.sh beagleplay:nsh
|
||||
|
||||
nsh
|
||||
---
|
||||
|
||||
Interactive NSH configuration for serial bring-up and shell access.
|
||||
|
||||
i2c
|
||||
---
|
||||
|
||||
NSH configuration with AM62x I2C0/I2C1 and the ``i2c`` tool enabled.
|
||||
|
||||
ostest
|
||||
------
|
||||
|
||||
Hardware validation configuration that boots directly into ``ostest_main``.
|
||||
|
|
|
|||
|
|
@ -17,10 +17,11 @@ Features
|
|||
* Expansion headers for GPIO, I2C, SPI, UART, PWM, and ADC
|
||||
* User LEDs exposed by the board port
|
||||
|
||||
Current NuttX support is limited to early boot, the 16550 serial console,
|
||||
interactive NSH, and ``procfs`` mount during board bring-up. GPIO, functional
|
||||
LED control, I2C, SPI, MMC/SD runtime support, Ethernet, and USB runtime
|
||||
support are not implemented yet.
|
||||
Current NuttX support includes early boot, the 16550 serial console,
|
||||
interactive NSH, ``procfs`` mount during board bring-up, AM62x TISCI
|
||||
initialization, main-domain GPIO, and I2C0/I2C2 controller support in the
|
||||
``pocketbeagle2:i2c`` configuration. SPI, MMC/SD runtime support, Ethernet,
|
||||
and USB runtime support are not implemented yet.
|
||||
|
||||
Buttons and LEDs
|
||||
================
|
||||
|
|
@ -35,7 +36,8 @@ USR1 Amber ``CONFIG_ARCH_LEDS`` placeholder
|
|||
USR2 Red ``CONFIG_ARCH_LEDS`` placeholder
|
||||
====== ======== =====================
|
||||
|
||||
These LEDs are not driven yet because AM62x GPIO support has not been added.
|
||||
The AM62x GPIO controller is initialized by the board port. Automatic
|
||||
``CONFIG_ARCH_LEDS`` LED hooks remain placeholders only.
|
||||
|
||||
Serial Console
|
||||
==============
|
||||
|
|
@ -54,7 +56,9 @@ Interface SoC signal Notes
|
|||
=========== ====================== =======================================
|
||||
USB-C debug UART6 Default NuttX serial console
|
||||
microSD MMC1 Validated boot media for ``nuttx.bin``
|
||||
USR0-2 Board user LEDs Not yet driven by NuttX GPIO support
|
||||
USR0-2 Board user LEDs Available through the main GPIO block
|
||||
I2C0 I2C0 Available in ``pocketbeagle2:i2c``
|
||||
I2C2 Header I2C2 Available in ``pocketbeagle2:i2c``
|
||||
=========== ====================== =======================================
|
||||
|
||||
Power Supply
|
||||
|
|
@ -103,8 +107,23 @@ present in on-board flash.
|
|||
Configurations
|
||||
==============
|
||||
|
||||
``pocketbeagle2:nsh``
|
||||
Interactive NSH configuration for serial bring-up and shell access.
|
||||
Configure NuttX with ``pocketbeagle2:<config-name>``.
|
||||
|
||||
``pocketbeagle2:ostest``
|
||||
Hardware validation configuration that boots directly into ``ostest_main``.
|
||||
.. code:: console
|
||||
|
||||
$ ./tools/configure.sh pocketbeagle2:nsh
|
||||
|
||||
nsh
|
||||
---
|
||||
|
||||
Interactive NSH configuration for serial bring-up and shell access.
|
||||
|
||||
i2c
|
||||
---
|
||||
|
||||
NSH configuration with AM62x I2C0/I2C2 and the ``i2c`` tool enabled.
|
||||
|
||||
ostest
|
||||
------
|
||||
|
||||
Hardware validation configuration that boots directly into ``ostest_main``.
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ Texas Instruments featuring:
|
|||
- **Boot:** ROM → R5 SYSFW (TIFS) → U-Boot SPL → U-Boot → NuttX
|
||||
- **Memory:** External DDR4/LPDDR4 (512 MB – 2 GB depending on board)
|
||||
- **UART:** Seven 16550-compatible UARTs (48 MHz clock)
|
||||
- **GPIO:** Main-domain GPIO controller support
|
||||
- **I2C:** Main-domain I2C controller support
|
||||
|
||||
Supported Boards
|
||||
================
|
||||
|
|
|
|||
|
|
@ -102,4 +102,16 @@
|
|||
#define AM62X_IRQ_UART5 215 /* GIC_SPI 183 */
|
||||
#define AM62X_IRQ_UART6 216 /* GIC_SPI 184 */
|
||||
|
||||
/* GPIO */
|
||||
|
||||
#define AM62X_IRQ_GPIO0 57
|
||||
#define AM62X_IRQ_GPIO1 58
|
||||
|
||||
/* I2C */
|
||||
|
||||
#define AM62X_IRQ_I2C0 193 /* GIC_SPI 161 */
|
||||
#define AM62X_IRQ_I2C1 194 /* GIC_SPI 162 */
|
||||
#define AM62X_IRQ_I2C2 195 /* GIC_SPI 163 */
|
||||
#define AM62X_IRQ_I2C3 196 /* GIC_SPI 164 */
|
||||
|
||||
#endif /* __ARCH_ARM64_INCLUDE_AM62X_IRQ_H */
|
||||
|
|
|
|||
|
|
@ -24,6 +24,21 @@
|
|||
|
||||
list(APPEND SRCS am62x_boot.c am62x_16550serial.c)
|
||||
|
||||
if(CONFIG_AM62X_GPIO)
|
||||
list(APPEND SRCS am62x_gpio.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_AM62X_I2C0
|
||||
OR CONFIG_AM62X_I2C1
|
||||
OR CONFIG_AM62X_I2C2
|
||||
OR CONFIG_AM62X_I2C3)
|
||||
list(APPEND SRCS am62x_i2c.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_AM62X_TISCI)
|
||||
list(APPEND SRCS am62x_tisci.c)
|
||||
endif()
|
||||
|
||||
# Early UART assembly (needed for CONFIG_ARCH_EARLY_PRINT / semihosting console
|
||||
# before the full serial driver is up)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,89 @@
|
|||
|
||||
if ARCH_CHIP_AM62X
|
||||
|
||||
comment "AM62x peripheral selection is provided by board defconfig for now."
|
||||
menu "AM62x peripheral support"
|
||||
|
||||
config AM62X_TISCI
|
||||
bool "TISCI system controller (DM/TIFS) client"
|
||||
default n
|
||||
---help---
|
||||
Enable the AM62x TISCI client. On K3 SoCs the A53 does not own
|
||||
device power, clocks, resets, or interrupt routing; those are
|
||||
requested from the DM/TIFS firmware over the TISCI protocol via the
|
||||
secure-proxy mailbox. This driver provides the request helpers used
|
||||
by peripheral drivers to power on a block, enable its functional
|
||||
clock, release resets, and route its interrupt to the GIC.
|
||||
|
||||
if AM62X_TISCI
|
||||
|
||||
config AM62X_TISCI_HOST_ID
|
||||
int "TISCI host ID"
|
||||
default 12
|
||||
---help---
|
||||
Host ID this core presents to the DM/TIFS firmware. Must match the
|
||||
host allocation in the firmware boardcfg. 12 is the standard A53
|
||||
HLOS host on AM62x.
|
||||
|
||||
config AM62X_TISCI_RX_THREAD
|
||||
int "Secure proxy RX (response) thread"
|
||||
default 12
|
||||
---help---
|
||||
Secure-proxy thread the firmware uses to send responses back to this
|
||||
host.
|
||||
|
||||
config AM62X_TISCI_TX_THREAD
|
||||
int "Secure proxy TX (request) thread"
|
||||
default 13
|
||||
---help---
|
||||
Secure-proxy thread this host uses to send requests to the firmware.
|
||||
|
||||
endif # AM62X_TISCI
|
||||
|
||||
config AM62X_GPIO
|
||||
bool "GPIO support"
|
||||
default n
|
||||
---help---
|
||||
Enable the AM62x main-domain GPIO controller driver, including
|
||||
basic GPIO input/output operations, pad-mux helper support, and
|
||||
per-pin interrupt callback dispatch for GPIO0/GPIO1.
|
||||
|
||||
config AM62X_GPIO_IRQ
|
||||
bool "GPIO interrupt (GIC) delivery"
|
||||
depends on AM62X_GPIO
|
||||
default n
|
||||
---help---
|
||||
Enable per-bank GPIO interrupt delivery through the GIC. On AM62x
|
||||
the GPIO bank interrupts are routed through the main GPIO interrupt
|
||||
router, which must be programmed over TISCI (RM_IRQ_SET) before the
|
||||
GIC input line is valid. Until that routing is implemented, leave
|
||||
this disabled: enabling an unrouted GIC line faults at boot. GPIO
|
||||
input/output and the callback API still work without it.
|
||||
|
||||
config AM62X_I2C0
|
||||
bool "I2C0 support"
|
||||
depends on I2C
|
||||
default n
|
||||
|
||||
config AM62X_I2C1
|
||||
bool "I2C1 support"
|
||||
depends on I2C
|
||||
default n
|
||||
|
||||
config AM62X_I2C2
|
||||
bool "I2C2 support"
|
||||
depends on I2C
|
||||
default n
|
||||
|
||||
config AM62X_I2C3
|
||||
bool "I2C3 support"
|
||||
depends on I2C
|
||||
default n
|
||||
|
||||
config AM62X_I2CTIMEOMS
|
||||
int "I2C transfer timeout milliseconds"
|
||||
default 500
|
||||
depends on AM62X_I2C0 || AM62X_I2C1 || AM62X_I2C2 || AM62X_I2C3
|
||||
|
||||
endmenu
|
||||
|
||||
endif # ARCH_CHIP_AM62X
|
||||
|
|
|
|||
|
|
@ -30,6 +30,24 @@ include common/Make.defs
|
|||
CHIP_CSRCS = am62x_boot.c
|
||||
CHIP_CSRCS += am62x_16550serial.c
|
||||
|
||||
ifeq ($(CONFIG_AM62X_GPIO),y)
|
||||
CHIP_CSRCS += am62x_gpio.c
|
||||
endif
|
||||
|
||||
AM62X_I2C_CONFIGS := $(CONFIG_AM62X_I2C0)
|
||||
AM62X_I2C_CONFIGS += $(CONFIG_AM62X_I2C1)
|
||||
AM62X_I2C_CONFIGS += $(CONFIG_AM62X_I2C2)
|
||||
AM62X_I2C_CONFIGS += $(CONFIG_AM62X_I2C3)
|
||||
|
||||
ifneq ($(AM62X_I2C_CONFIGS),)
|
||||
CHIP_CSRCS += am62x_i2c.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_AM62X_TISCI),y)
|
||||
CHIP_CSRCS += am62x_tisci.c
|
||||
endif
|
||||
|
||||
|
||||
# Early UART assembly (only when CONFIG_ARCH_EARLY_PRINT is set, which
|
||||
# is selected automatically when CONFIG_ARCH_HAVE_LOWPUTC is enabled
|
||||
# and the common arch layer needs early console output).
|
||||
|
|
|
|||
368
arch/arm64/src/am62x/am62x_gpio.c
Normal file
368
arch/arm64/src/am62x/am62x_gpio.c
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/am62x/am62x_gpio.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "arm64_arch.h"
|
||||
#include "arm64_internal.h"
|
||||
#include "hardware/am62x_gpio.h"
|
||||
#include "hardware/am62x_memorymap.h"
|
||||
#include "am62x_gpio.h"
|
||||
#include "am62x_tisci.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct am62x_gpio_callback_s
|
||||
{
|
||||
xcpt_t handler;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const uintptr_t g_gpiobase[AM62X_GPIO_NBANKS] =
|
||||
{
|
||||
AM62X_GPIO0_BASE,
|
||||
AM62X_GPIO1_BASE,
|
||||
};
|
||||
|
||||
static const int g_gpioirq[AM62X_GPIO_NBANKS] =
|
||||
{
|
||||
AM62X_IRQ_GPIO0,
|
||||
AM62X_IRQ_GPIO1,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_AM62X_TISCI
|
||||
/* TISCI power-domain / device id for each GPIO bank. The bank must be
|
||||
* powered on through the system firmware before its registers are touched.
|
||||
*/
|
||||
|
||||
static const uint32_t g_gpiopd[AM62X_GPIO_NBANKS] =
|
||||
{
|
||||
AM62X_DEV_GPIO0,
|
||||
AM62X_DEV_GPIO1,
|
||||
};
|
||||
|
||||
static const uint32_t g_gpioclk[AM62X_GPIO_NBANKS] =
|
||||
{
|
||||
0,
|
||||
0,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct am62x_gpio_callback_s
|
||||
g_callbacks[AM62X_GPIO_NBANKS][AM62X_GPIO_NPINS];
|
||||
|
||||
static bool g_gpio_initialized;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int am62x_gpio_decode(gpio_pinset_t pinset, unsigned int *bank,
|
||||
unsigned int *line)
|
||||
{
|
||||
*bank = AM62X_GPIO_BANK(pinset);
|
||||
*line = AM62X_GPIO_LINE(pinset);
|
||||
|
||||
if (*bank >= AM62X_GPIO_NBANKS || *line >= AM62X_GPIO_NPINS)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int am62x_gpio_interrupt(int irq, void *context, void *arg)
|
||||
{
|
||||
unsigned int bank = (uintptr_t)arg;
|
||||
uintptr_t base = g_gpiobase[bank];
|
||||
uint32_t pending;
|
||||
unsigned int line;
|
||||
|
||||
pending = getreg32(AM62X_GPIO_INTSTAT(base, 0));
|
||||
putreg32(pending, AM62X_GPIO_INTSTAT(base, 0));
|
||||
|
||||
for (line = 0; line < AM62X_GPIO_NPINS; line++)
|
||||
{
|
||||
if ((pending & AM62X_GPIO_BIT(line)) != 0 &&
|
||||
g_callbacks[bank][line].handler != NULL)
|
||||
{
|
||||
g_callbacks[bank][line].handler(irq, context,
|
||||
g_callbacks[bank][line].arg);
|
||||
}
|
||||
}
|
||||
|
||||
putreg32(0, AM62X_GPIO_BINTEN(base));
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int am62x_gpio_initialize(void)
|
||||
{
|
||||
unsigned int bank;
|
||||
int ret;
|
||||
|
||||
if (g_gpio_initialized)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
for (bank = 0; bank < AM62X_GPIO_NBANKS; bank++)
|
||||
{
|
||||
uintptr_t base = g_gpiobase[bank];
|
||||
|
||||
#ifdef CONFIG_AM62X_TISCI
|
||||
/* Power, release reset, and clock the GPIO bank before any register
|
||||
* access. On K3 an access to a gated block faults the bus.
|
||||
*/
|
||||
|
||||
ret = am62x_tisci_module_enable(g_gpiopd[bank], g_gpioclk[bank]);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
putreg32(0xffffffff, AM62X_GPIO_CLR_RIS_TRIG(base, 0));
|
||||
putreg32(0xffffffff, AM62X_GPIO_CLR_FAL_TRIG(base, 0));
|
||||
putreg32(0xffffffff, AM62X_GPIO_INTSTAT(base, 0));
|
||||
putreg32(0, AM62X_GPIO_BINTEN(base));
|
||||
|
||||
ret = irq_attach(g_gpioirq[bank], am62x_gpio_interrupt,
|
||||
(void *)(uintptr_t)bank);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* GPIO bank interrupts on AM62x are not delivered directly to the GIC:
|
||||
* they pass through the main GPIO interrupt router, which must be
|
||||
* programmed via TISCI (RM_IRQ_SET) before the GIC input is valid.
|
||||
* Until that routing is wired up, enabling the GIC line delivers a
|
||||
* spurious/unrouted interrupt and faults. GPIO input/output works
|
||||
* without it; gate the enable behind CONFIG_AM62X_GPIO_IRQ.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_AM62X_GPIO_IRQ
|
||||
#ifdef CONFIG_ARCH_IRQPRIO
|
||||
(void)up_prioritize_irq(g_gpioirq[bank], 0);
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_HAVE_IRQTRIGGER
|
||||
(void)up_set_irq_type(g_gpioirq[bank], IRQ_HIGH_LEVEL);
|
||||
#endif
|
||||
up_enable_irq(g_gpioirq[bank]);
|
||||
#endif
|
||||
}
|
||||
|
||||
g_gpio_initialized = true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
int am62x_configgpio(gpio_pinset_t cfgset)
|
||||
{
|
||||
irqstate_t flags;
|
||||
uintptr_t base;
|
||||
uint32_t bit;
|
||||
uint32_t regval;
|
||||
unsigned int bank;
|
||||
unsigned int line;
|
||||
int ret;
|
||||
|
||||
ret = am62x_gpio_decode(cfgset, &bank, &line);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
base = g_gpiobase[bank];
|
||||
bit = AM62X_GPIO_BIT(line);
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
if (!AM62X_GPIO_IS_INPUT(cfgset))
|
||||
{
|
||||
putreg32(bit, AM62X_GPIO_INITVAL(cfgset) ?
|
||||
AM62X_GPIO_SET_DATA(base, 0) :
|
||||
AM62X_GPIO_CLR_DATA(base, 0));
|
||||
}
|
||||
|
||||
regval = getreg32(AM62X_GPIO_DIR(base, 0));
|
||||
if (AM62X_GPIO_IS_INPUT(cfgset))
|
||||
{
|
||||
regval |= bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
regval &= ~bit;
|
||||
}
|
||||
|
||||
putreg32(regval, AM62X_GPIO_DIR(base, 0));
|
||||
|
||||
putreg32(bit, AM62X_GPIO_CLR_RIS_TRIG(base, 0));
|
||||
putreg32(bit, AM62X_GPIO_CLR_FAL_TRIG(base, 0));
|
||||
|
||||
if (AM62X_GPIO_IRQMODE(cfgset) == AM62X_GPIO_IRQ_RISING ||
|
||||
AM62X_GPIO_IRQMODE(cfgset) == AM62X_GPIO_IRQ_BOTH)
|
||||
{
|
||||
putreg32(bit, AM62X_GPIO_SET_RIS_TRIG(base, 0));
|
||||
}
|
||||
|
||||
if (AM62X_GPIO_IRQMODE(cfgset) == AM62X_GPIO_IRQ_FALLING ||
|
||||
AM62X_GPIO_IRQMODE(cfgset) == AM62X_GPIO_IRQ_BOTH)
|
||||
{
|
||||
putreg32(bit, AM62X_GPIO_SET_FAL_TRIG(base, 0));
|
||||
}
|
||||
|
||||
putreg32(bit, AM62X_GPIO_INTSTAT(base, 0));
|
||||
|
||||
leave_critical_section(flags);
|
||||
return OK;
|
||||
}
|
||||
|
||||
void am62x_gpiowrite(gpio_pinset_t pinset, bool value)
|
||||
{
|
||||
irqstate_t flags;
|
||||
uintptr_t base;
|
||||
unsigned int bank;
|
||||
unsigned int line;
|
||||
|
||||
if (am62x_gpio_decode(pinset, &bank, &line) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
base = g_gpiobase[bank];
|
||||
flags = enter_critical_section();
|
||||
putreg32(AM62X_GPIO_BIT(line), value ? AM62X_GPIO_SET_DATA(base, 0) :
|
||||
AM62X_GPIO_CLR_DATA(base, 0));
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
bool am62x_gpioread(gpio_pinset_t pinset)
|
||||
{
|
||||
irqstate_t flags;
|
||||
uintptr_t base;
|
||||
bool value;
|
||||
unsigned int bank;
|
||||
unsigned int line;
|
||||
|
||||
if (am62x_gpio_decode(pinset, &bank, &line) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
base = g_gpiobase[bank];
|
||||
flags = enter_critical_section();
|
||||
value = (getreg32(AM62X_GPIO_IN_DATA(base, 0)) &
|
||||
AM62X_GPIO_BIT(line)) != 0;
|
||||
leave_critical_section(flags);
|
||||
return value;
|
||||
}
|
||||
|
||||
bool am62x_gpiooutread(gpio_pinset_t pinset)
|
||||
{
|
||||
irqstate_t flags;
|
||||
uintptr_t base;
|
||||
bool value;
|
||||
unsigned int bank;
|
||||
unsigned int line;
|
||||
|
||||
if (am62x_gpio_decode(pinset, &bank, &line) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
base = g_gpiobase[bank];
|
||||
flags = enter_critical_section();
|
||||
value = (getreg32(AM62X_GPIO_OUT_DATA(base, 0)) &
|
||||
AM62X_GPIO_BIT(line)) != 0;
|
||||
leave_critical_section(flags);
|
||||
return value;
|
||||
}
|
||||
|
||||
int am62x_gpio_irq_attach(gpio_pinset_t pinset, xcpt_t isr, void *arg)
|
||||
{
|
||||
irqstate_t flags;
|
||||
unsigned int bank;
|
||||
unsigned int line;
|
||||
int ret;
|
||||
|
||||
ret = am62x_gpio_decode(pinset, &bank, &line);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = am62x_gpio_initialize();
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
g_callbacks[bank][line].handler = isr;
|
||||
g_callbacks[bank][line].arg = arg;
|
||||
leave_critical_section(flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void am62x_gpio_irq_detach(gpio_pinset_t pinset)
|
||||
{
|
||||
irqstate_t flags;
|
||||
unsigned int bank;
|
||||
unsigned int line;
|
||||
|
||||
if (am62x_gpio_decode(pinset, &bank, &line) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
g_callbacks[bank][line].handler = NULL;
|
||||
g_callbacks[bank][line].arg = NULL;
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
int am62x_pinmux_configure(uintptr_t offset, uint32_t value)
|
||||
{
|
||||
putreg32(value, AM62X_PADCFG_BASE + offset);
|
||||
return OK;
|
||||
}
|
||||
98
arch/arm64/src/am62x/am62x_gpio.h
Normal file
98
arch/arm64/src/am62x/am62x_gpio.h
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/am62x/am62x_gpio.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM64_SRC_AM62X_AM62X_GPIO_H
|
||||
#define __ARCH_ARM64_SRC_AM62X_AM62X_GPIO_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
typedef uint32_t gpio_pinset_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define AM62X_GPIO_LINE_SHIFT 0
|
||||
#define AM62X_GPIO_LINE_MASK (0xffu << AM62X_GPIO_LINE_SHIFT)
|
||||
#define AM62X_GPIO_BANK_SHIFT 8
|
||||
#define AM62X_GPIO_BANK_MASK (0x03u << AM62X_GPIO_BANK_SHIFT)
|
||||
#define AM62X_GPIO_INPUT (1u << 10)
|
||||
#define AM62X_GPIO_OUTPUT_ONE (1u << 11)
|
||||
#define AM62X_GPIO_PULL_SHIFT 12
|
||||
#define AM62X_GPIO_PULL_MASK (0x03u << AM62X_GPIO_PULL_SHIFT)
|
||||
# define AM62X_GPIO_PULL_NONE (0u << AM62X_GPIO_PULL_SHIFT)
|
||||
# define AM62X_GPIO_PULL_UP (1u << AM62X_GPIO_PULL_SHIFT)
|
||||
# define AM62X_GPIO_PULL_DOWN (2u << AM62X_GPIO_PULL_SHIFT)
|
||||
#define AM62X_GPIO_IRQ_SHIFT 14
|
||||
#define AM62X_GPIO_IRQ_MASK (0x07u << AM62X_GPIO_IRQ_SHIFT)
|
||||
# define AM62X_GPIO_IRQ_NONE (0u << AM62X_GPIO_IRQ_SHIFT)
|
||||
# define AM62X_GPIO_IRQ_RISING (1u << AM62X_GPIO_IRQ_SHIFT)
|
||||
# define AM62X_GPIO_IRQ_FALLING (2u << AM62X_GPIO_IRQ_SHIFT)
|
||||
# define AM62X_GPIO_IRQ_BOTH (3u << AM62X_GPIO_IRQ_SHIFT)
|
||||
# define AM62X_GPIO_IRQ_HIGH (4u << AM62X_GPIO_IRQ_SHIFT)
|
||||
# define AM62X_GPIO_IRQ_LOW (5u << AM62X_GPIO_IRQ_SHIFT)
|
||||
|
||||
#define AM62X_GPIO_OUTPUT 0u
|
||||
|
||||
#define AM62X_GPIO_PIN(b,l) ((((uint32_t)(b) << AM62X_GPIO_BANK_SHIFT) & \
|
||||
AM62X_GPIO_BANK_MASK) | \
|
||||
(((uint32_t)(l) << AM62X_GPIO_LINE_SHIFT) & \
|
||||
AM62X_GPIO_LINE_MASK))
|
||||
#define AM62X_GPIO_BANK(p) (((p) & AM62X_GPIO_BANK_MASK) >> \
|
||||
AM62X_GPIO_BANK_SHIFT)
|
||||
#define AM62X_GPIO_LINE(p) (((p) & AM62X_GPIO_LINE_MASK) >> \
|
||||
AM62X_GPIO_LINE_SHIFT)
|
||||
#define AM62X_GPIO_IS_INPUT(p) (((p) & AM62X_GPIO_INPUT) != 0)
|
||||
#define AM62X_GPIO_INITVAL(p) (((p) & AM62X_GPIO_OUTPUT_ONE) != 0)
|
||||
#define AM62X_GPIO_IRQMODE(p) ((p) & AM62X_GPIO_IRQ_MASK)
|
||||
|
||||
#define AM62X_PADCFG_RXACTIVE (1 << 18)
|
||||
#define AM62X_PADCFG_PULL_DISABLE (1 << 16)
|
||||
#define AM62X_PADCFG_PULL_UP (1 << 17)
|
||||
#define AM62X_PADCFG_MUXMODE(n) ((n) & 0x0f)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
int am62x_gpio_initialize(void);
|
||||
int am62x_configgpio(gpio_pinset_t cfgset);
|
||||
void am62x_gpiowrite(gpio_pinset_t pinset, bool value);
|
||||
bool am62x_gpioread(gpio_pinset_t pinset);
|
||||
bool am62x_gpiooutread(gpio_pinset_t pinset);
|
||||
int am62x_gpio_irq_attach(gpio_pinset_t pinset, xcpt_t isr, void *arg);
|
||||
void am62x_gpio_irq_detach(gpio_pinset_t pinset);
|
||||
int am62x_pinmux_configure(uintptr_t offset, uint32_t value);
|
||||
|
||||
#endif /* __ARCH_ARM64_SRC_AM62X_AM62X_GPIO_H */
|
||||
767
arch/arm64/src/am62x/am62x_i2c.c
Normal file
767
arch/arm64/src/am62x/am62x_i2c.c
Normal file
|
|
@ -0,0 +1,767 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/am62x/am62x_i2c.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/debug.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/mutex.h>
|
||||
#include <nuttx/semaphore.h>
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
|
||||
#include "arm64_arch.h"
|
||||
#include "arm64_internal.h"
|
||||
#include "hardware/am62x_i2c.h"
|
||||
#include "hardware/am62x_memorymap.h"
|
||||
#include "am62x_i2c.h"
|
||||
#include "am62x_tisci.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define AM62X_I2C_INPUT_CLOCK 96000000
|
||||
#define AM62X_I2C_INTERNAL_CLK 12000000
|
||||
|
||||
#ifndef CONFIG_AM62X_I2CTIMEOMS
|
||||
# define CONFIG_AM62X_I2CTIMEOMS 500
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_AM62X_I2CTIMEOTICKS
|
||||
# define CONFIG_AM62X_I2CTIMEOTICKS MSEC2TICK(CONFIG_AM62X_I2CTIMEOMS)
|
||||
#endif
|
||||
|
||||
/* The transmit underflow is left masked, the module raises it while it
|
||||
* holds the bus between the messages of a register read.
|
||||
*/
|
||||
|
||||
#define AM62X_I2C_INTERRUPTS (I2C_IRQ_AL | I2C_IRQ_NACK | I2C_IRQ_ARDY | \
|
||||
I2C_IRQ_RRDY | I2C_IRQ_XRDY)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
enum am62x_i2c_state_e
|
||||
{
|
||||
INTSTATE_IDLE = 0,
|
||||
INTSTATE_WAITING,
|
||||
INTSTATE_DONE,
|
||||
};
|
||||
|
||||
struct am62x_i2c_config_s
|
||||
{
|
||||
uintptr_t base;
|
||||
int irq;
|
||||
uint32_t devid; /* TISCI device id (power/clock domain) */
|
||||
uint32_t clkid; /* TISCI functional clock id */
|
||||
};
|
||||
|
||||
struct am62x_i2c_priv_s
|
||||
{
|
||||
const struct i2c_ops_s *ops;
|
||||
const struct am62x_i2c_config_s *config;
|
||||
int refs;
|
||||
mutex_t lock;
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
sem_t sem_isr;
|
||||
#endif
|
||||
volatile uint8_t intstate;
|
||||
struct i2c_msg_s *msgv;
|
||||
int msgc;
|
||||
int msgidx;
|
||||
uint8_t *ptr;
|
||||
int dcnt;
|
||||
uint16_t flags;
|
||||
uint32_t frequency;
|
||||
uint32_t status;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int am62x_i2c_transfer(struct i2c_master_s *dev,
|
||||
struct i2c_msg_s *msgs, int count);
|
||||
#ifdef CONFIG_I2C_RESET
|
||||
static int am62x_i2c_reset(struct i2c_master_s *dev);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct i2c_ops_s g_i2c_ops =
|
||||
{
|
||||
.transfer = am62x_i2c_transfer,
|
||||
#ifdef CONFIG_I2C_RESET
|
||||
.reset = am62x_i2c_reset,
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_AM62X_I2C0
|
||||
static const struct am62x_i2c_config_s g_i2c0_config =
|
||||
{
|
||||
.base = AM62X_I2C0_BASE,
|
||||
.irq = AM62X_IRQ_I2C0,
|
||||
.devid = AM62X_DEV_I2C0,
|
||||
.clkid = 2,
|
||||
};
|
||||
|
||||
static struct am62x_i2c_priv_s g_i2c0_priv =
|
||||
{
|
||||
.ops = &g_i2c_ops,
|
||||
.config = &g_i2c0_config,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.sem_isr = SEM_INITIALIZER(0),
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AM62X_I2C1
|
||||
static const struct am62x_i2c_config_s g_i2c1_config =
|
||||
{
|
||||
.base = AM62X_I2C1_BASE,
|
||||
.irq = AM62X_IRQ_I2C1,
|
||||
.devid = AM62X_DEV_I2C1,
|
||||
.clkid = 2,
|
||||
};
|
||||
|
||||
static struct am62x_i2c_priv_s g_i2c1_priv =
|
||||
{
|
||||
.ops = &g_i2c_ops,
|
||||
.config = &g_i2c1_config,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.sem_isr = SEM_INITIALIZER(0),
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AM62X_I2C2
|
||||
static const struct am62x_i2c_config_s g_i2c2_config =
|
||||
{
|
||||
.base = AM62X_I2C2_BASE,
|
||||
.irq = AM62X_IRQ_I2C2,
|
||||
.devid = AM62X_DEV_I2C2,
|
||||
.clkid = 2,
|
||||
};
|
||||
|
||||
static struct am62x_i2c_priv_s g_i2c2_priv =
|
||||
{
|
||||
.ops = &g_i2c_ops,
|
||||
.config = &g_i2c2_config,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.sem_isr = SEM_INITIALIZER(0),
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AM62X_I2C3
|
||||
static const struct am62x_i2c_config_s g_i2c3_config =
|
||||
{
|
||||
.base = AM62X_I2C3_BASE,
|
||||
.irq = AM62X_IRQ_I2C3,
|
||||
.devid = AM62X_DEV_I2C3,
|
||||
.clkid = 2,
|
||||
};
|
||||
|
||||
static struct am62x_i2c_priv_s g_i2c3_priv =
|
||||
{
|
||||
.ops = &g_i2c_ops,
|
||||
.config = &g_i2c3_config,
|
||||
.lock = NXMUTEX_INITIALIZER,
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
.sem_isr = SEM_INITIALIZER(0),
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint32_t am62x_i2c_getreg(struct am62x_i2c_priv_s *priv,
|
||||
uint16_t offset)
|
||||
{
|
||||
return getreg32(priv->config->base + offset);
|
||||
}
|
||||
|
||||
static inline void am62x_i2c_putreg(struct am62x_i2c_priv_s *priv,
|
||||
uint16_t offset, uint32_t value)
|
||||
{
|
||||
putreg32(value, priv->config->base + offset);
|
||||
}
|
||||
|
||||
static inline void am62x_i2c_modifyreg(struct am62x_i2c_priv_s *priv,
|
||||
uint16_t offset, uint32_t clearbits,
|
||||
uint32_t setbits)
|
||||
{
|
||||
modifyreg32(priv->config->base + offset, clearbits, setbits);
|
||||
}
|
||||
|
||||
static bool am62x_i2c_wait_bus_free(struct am62x_i2c_priv_s *priv)
|
||||
{
|
||||
clock_t start = clock_systime_ticks();
|
||||
|
||||
do
|
||||
{
|
||||
if ((am62x_i2c_getreg(priv, AM62X_I2C_IRQSTATUS_RAW_OFFSET) &
|
||||
I2C_IRQ_BB) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
while ((clock_systime_ticks() - start) < CONFIG_AM62X_I2CTIMEOTICKS);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void am62x_i2c_flush_fifo(struct am62x_i2c_priv_s *priv)
|
||||
{
|
||||
uint32_t buf = am62x_i2c_getreg(priv, AM62X_I2C_BUF_OFFSET);
|
||||
|
||||
/* Pulse the clear bits only, the thresholds must be preserved. */
|
||||
|
||||
buf |= I2C_BUF_RXFIFO_CLR | I2C_BUF_TXFIFO_CLR;
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_BUF_OFFSET, buf);
|
||||
}
|
||||
|
||||
static int am62x_i2c_softreset(struct am62x_i2c_priv_s *priv)
|
||||
{
|
||||
clock_t start;
|
||||
|
||||
/* The module must be enabled for the reset to progress. */
|
||||
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_CON_OFFSET, 0);
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_SYSC_OFFSET, I2C_SYSC_SRST);
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_CON_OFFSET, I2C_CON_EN);
|
||||
|
||||
start = clock_systime_ticks();
|
||||
do
|
||||
{
|
||||
if ((am62x_i2c_getreg(priv, AM62X_I2C_SYSS_OFFSET) &
|
||||
I2C_SYSS_RST_DONE) != 0)
|
||||
{
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_CON_OFFSET, 0);
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
while ((clock_systime_ticks() - start) < CONFIG_AM62X_I2CTIMEOTICKS);
|
||||
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_CON_OFFSET, 0);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static void am62x_i2c_setclock(struct am62x_i2c_priv_s *priv,
|
||||
uint32_t frequency)
|
||||
{
|
||||
uint32_t internal;
|
||||
uint32_t psc;
|
||||
uint32_t divider;
|
||||
uint32_t scll;
|
||||
uint32_t sclh;
|
||||
uint32_t enabled;
|
||||
|
||||
if (frequency == 0)
|
||||
{
|
||||
frequency = 100000;
|
||||
}
|
||||
|
||||
if (frequency == priv->frequency)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
enabled = am62x_i2c_getreg(priv, AM62X_I2C_CON_OFFSET) & I2C_CON_EN;
|
||||
if (enabled != 0)
|
||||
{
|
||||
am62x_i2c_modifyreg(priv, AM62X_I2C_CON_OFFSET, I2C_CON_EN, 0);
|
||||
}
|
||||
|
||||
psc = (AM62X_I2C_INPUT_CLOCK / AM62X_I2C_INTERNAL_CLK) - 1;
|
||||
internal = AM62X_I2C_INPUT_CLOCK / (psc + 1);
|
||||
divider = internal / frequency;
|
||||
|
||||
if (divider < 14)
|
||||
{
|
||||
divider = 14;
|
||||
}
|
||||
|
||||
scll = (divider / 2) - 7;
|
||||
sclh = (divider - (divider / 2)) - 5;
|
||||
|
||||
if (scll > 255)
|
||||
{
|
||||
scll = 255;
|
||||
}
|
||||
|
||||
if (sclh > 255)
|
||||
{
|
||||
sclh = 255;
|
||||
}
|
||||
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_PSC_OFFSET, psc);
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_SCLL_OFFSET, scll);
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_SCLH_OFFSET, sclh);
|
||||
|
||||
if (enabled != 0)
|
||||
{
|
||||
am62x_i2c_modifyreg(priv, AM62X_I2C_CON_OFFSET, 0, I2C_CON_EN);
|
||||
}
|
||||
|
||||
priv->frequency = frequency;
|
||||
}
|
||||
|
||||
static void am62x_i2c_recover(struct am62x_i2c_priv_s *priv)
|
||||
{
|
||||
uint32_t frequency = priv->frequency;
|
||||
|
||||
/* A transfer aborted while the bus was held keeps the lines driven. */
|
||||
|
||||
am62x_i2c_modifyreg(priv, AM62X_I2C_CON_OFFSET, 0, I2C_CON_STP);
|
||||
am62x_i2c_flush_fifo(priv);
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_IRQSTATUS_OFFSET, I2C_IRQ_CLEARMASK);
|
||||
|
||||
if ((am62x_i2c_getreg(priv, AM62X_I2C_IRQSTATUS_RAW_OFFSET) &
|
||||
I2C_IRQ_BB) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* The bus is still held, only a soft reset gets the module out. */
|
||||
|
||||
if (am62x_i2c_softreset(priv) == OK)
|
||||
{
|
||||
priv->frequency = 0;
|
||||
am62x_i2c_setclock(priv, frequency);
|
||||
am62x_i2c_flush_fifo(priv);
|
||||
am62x_i2c_modifyreg(priv, AM62X_I2C_CON_OFFSET, 0, I2C_CON_EN);
|
||||
am62x_i2c_modifyreg(priv, AM62X_I2C_SYSTEST_OFFSET, 0,
|
||||
I2C_SYSTEST_FREE);
|
||||
}
|
||||
}
|
||||
|
||||
static void am62x_i2c_start_message(struct am62x_i2c_priv_s *priv)
|
||||
{
|
||||
struct i2c_msg_s *msg = &priv->msgv[priv->msgidx];
|
||||
uint32_t con = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT;
|
||||
bool last = (priv->msgidx + 1) >= priv->msgc;
|
||||
|
||||
priv->ptr = msg->buffer;
|
||||
priv->dcnt = msg->length;
|
||||
priv->flags = msg->flags;
|
||||
|
||||
if ((msg->flags & I2C_M_READ) == 0)
|
||||
{
|
||||
con |= I2C_CON_TRX;
|
||||
}
|
||||
|
||||
if ((msg->flags & I2C_M_TEN) != 0)
|
||||
{
|
||||
con |= I2C_CON_XSA;
|
||||
}
|
||||
|
||||
if (last && (msg->flags & I2C_M_NOSTOP) == 0)
|
||||
{
|
||||
con |= I2C_CON_STP;
|
||||
}
|
||||
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_SA_OFFSET, msg->addr);
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_CNT_OFFSET, msg->length);
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_CON_OFFSET, con);
|
||||
}
|
||||
|
||||
static void am62x_i2c_complete(struct am62x_i2c_priv_s *priv)
|
||||
{
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_IRQENABLE_CLR_OFFSET,
|
||||
I2C_IRQ_CLEARMASK);
|
||||
if (priv->intstate == INTSTATE_WAITING)
|
||||
{
|
||||
priv->intstate = INTSTATE_DONE;
|
||||
nxsem_post(&priv->sem_isr);
|
||||
}
|
||||
#else
|
||||
priv->intstate = INTSTATE_DONE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int am62x_i2c_isr_process(struct am62x_i2c_priv_s *priv)
|
||||
{
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
uint32_t status = am62x_i2c_getreg(priv, AM62X_I2C_IRQSTATUS_OFFSET);
|
||||
#else
|
||||
uint32_t status = am62x_i2c_getreg(priv, AM62X_I2C_IRQSTATUS_RAW_OFFSET);
|
||||
#endif
|
||||
|
||||
if (status == 0)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
priv->status = status;
|
||||
|
||||
if ((status & I2C_IRQ_ERRORMASK) != 0)
|
||||
{
|
||||
am62x_i2c_modifyreg(priv, AM62X_I2C_CON_OFFSET, 0, I2C_CON_STP);
|
||||
am62x_i2c_complete(priv);
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_IRQSTATUS_OFFSET, status);
|
||||
return OK;
|
||||
}
|
||||
|
||||
if ((status & I2C_IRQ_XRDY) != 0 && (priv->flags & I2C_M_READ) == 0)
|
||||
{
|
||||
if (priv->dcnt > 0)
|
||||
{
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_DATA_OFFSET, *priv->ptr++);
|
||||
priv->dcnt--;
|
||||
}
|
||||
}
|
||||
|
||||
if ((status & I2C_IRQ_RRDY) != 0 && (priv->flags & I2C_M_READ) != 0)
|
||||
{
|
||||
if (priv->dcnt > 0)
|
||||
{
|
||||
*priv->ptr++ = am62x_i2c_getreg(priv, AM62X_I2C_DATA_OFFSET) &
|
||||
I2C_DATA_MASK;
|
||||
priv->dcnt--;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)am62x_i2c_getreg(priv, AM62X_I2C_DATA_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
/* Acknowledge before starting the next message, clearing the status
|
||||
* afterwards would drop the events raised by that message.
|
||||
*/
|
||||
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_IRQSTATUS_OFFSET, status);
|
||||
|
||||
if ((status & I2C_IRQ_ARDY) != 0)
|
||||
{
|
||||
if (priv->msgidx + 1 < priv->msgc)
|
||||
{
|
||||
priv->msgidx++;
|
||||
am62x_i2c_start_message(priv);
|
||||
}
|
||||
else
|
||||
{
|
||||
am62x_i2c_complete(priv);
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
static int am62x_i2c_isr(int irq, void *context, void *arg)
|
||||
{
|
||||
struct am62x_i2c_priv_s *priv = arg;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
return am62x_i2c_isr_process(priv);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int am62x_i2c_waitdone(struct am62x_i2c_priv_s *priv)
|
||||
{
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
int ret;
|
||||
|
||||
priv->intstate = INTSTATE_WAITING;
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_IRQENABLE_SET_OFFSET,
|
||||
AM62X_I2C_INTERRUPTS);
|
||||
am62x_i2c_start_message(priv);
|
||||
|
||||
do
|
||||
{
|
||||
ret = nxsem_tickwait(&priv->sem_isr, CONFIG_AM62X_I2CTIMEOTICKS);
|
||||
}
|
||||
while (ret == -EINTR && priv->intstate != INTSTATE_DONE);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_IRQENABLE_CLR_OFFSET,
|
||||
I2C_IRQ_CLEARMASK);
|
||||
am62x_i2c_recover(priv);
|
||||
priv->intstate = INTSTATE_IDLE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->intstate = INTSTATE_IDLE;
|
||||
return OK;
|
||||
#else
|
||||
clock_t start = clock_systime_ticks();
|
||||
|
||||
priv->intstate = INTSTATE_WAITING;
|
||||
am62x_i2c_start_message(priv);
|
||||
|
||||
while (priv->intstate != INTSTATE_DONE &&
|
||||
(clock_systime_ticks() - start) < CONFIG_AM62X_I2CTIMEOTICKS)
|
||||
{
|
||||
am62x_i2c_isr_process(priv);
|
||||
}
|
||||
|
||||
if (priv->intstate != INTSTATE_DONE)
|
||||
{
|
||||
am62x_i2c_recover(priv);
|
||||
priv->intstate = INTSTATE_IDLE;
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
priv->intstate = INTSTATE_IDLE;
|
||||
return OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int am62x_i2c_init(struct am62x_i2c_priv_s *priv)
|
||||
{
|
||||
#ifdef CONFIG_AM62X_TISCI
|
||||
/* Power, release reset, and clock I2C before any register access. */
|
||||
|
||||
int pret = am62x_tisci_module_enable(priv->config->devid,
|
||||
priv->config->clkid);
|
||||
if (pret < 0)
|
||||
{
|
||||
return pret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The bootloader may have left the module holding the bus. */
|
||||
|
||||
am62x_i2c_softreset(priv);
|
||||
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_CON_OFFSET, 0);
|
||||
am62x_i2c_modifyreg(priv, AM62X_I2C_SYSC_OFFSET, I2C_SYSC_AUTOIDLE, 0);
|
||||
priv->frequency = 0;
|
||||
am62x_i2c_setclock(priv, 100000);
|
||||
am62x_i2c_flush_fifo(priv);
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_IRQSTATUS_OFFSET, I2C_IRQ_CLEARMASK);
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_IRQENABLE_CLR_OFFSET,
|
||||
I2C_IRQ_CLEARMASK);
|
||||
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
int ret = irq_attach(priv->config->irq, am62x_i2c_isr, priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_IRQPRIO
|
||||
(void)up_prioritize_irq(priv->config->irq, 0);
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_HAVE_IRQTRIGGER
|
||||
(void)up_set_irq_type(priv->config->irq, IRQ_HIGH_LEVEL);
|
||||
#endif
|
||||
up_enable_irq(priv->config->irq);
|
||||
#endif
|
||||
|
||||
am62x_i2c_modifyreg(priv, AM62X_I2C_CON_OFFSET, 0, I2C_CON_EN);
|
||||
am62x_i2c_modifyreg(priv, AM62X_I2C_SYSTEST_OFFSET, 0, I2C_SYSTEST_FREE);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int am62x_i2c_deinit(struct am62x_i2c_priv_s *priv)
|
||||
{
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_IRQENABLE_CLR_OFFSET,
|
||||
I2C_IRQ_CLEARMASK);
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_CON_OFFSET, 0);
|
||||
|
||||
#ifndef CONFIG_I2C_POLLED
|
||||
up_disable_irq(priv->config->irq);
|
||||
irq_detach(priv->config->irq);
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int am62x_i2c_transfer(struct i2c_master_s *dev,
|
||||
struct i2c_msg_s *msgs, int count)
|
||||
{
|
||||
struct am62x_i2c_priv_s *priv = (struct am62x_i2c_priv_s *)dev;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(priv != NULL && msgs != NULL && count > 0);
|
||||
|
||||
ret = nxmutex_lock(&priv->lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* A previous transfer may have left the bus held. Recover instead of
|
||||
* refusing every transfer from now on.
|
||||
*/
|
||||
|
||||
if (!am62x_i2c_wait_bus_free(priv))
|
||||
{
|
||||
am62x_i2c_recover(priv);
|
||||
|
||||
if (!am62x_i2c_wait_bus_free(priv))
|
||||
{
|
||||
nxmutex_unlock(&priv->lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
am62x_i2c_putreg(priv, AM62X_I2C_IRQSTATUS_OFFSET, I2C_IRQ_CLEARMASK);
|
||||
am62x_i2c_flush_fifo(priv);
|
||||
am62x_i2c_setclock(priv, msgs[0].frequency);
|
||||
|
||||
priv->msgv = msgs;
|
||||
priv->msgc = count;
|
||||
priv->msgidx = 0;
|
||||
priv->ptr = NULL;
|
||||
priv->dcnt = 0;
|
||||
priv->flags = msgs[0].flags;
|
||||
priv->status = 0;
|
||||
|
||||
ret = am62x_i2c_waitdone(priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
else if ((priv->status & I2C_IRQ_AL) != 0)
|
||||
{
|
||||
ret = -EAGAIN;
|
||||
}
|
||||
else if ((priv->status & I2C_IRQ_NACK) != 0)
|
||||
{
|
||||
ret = -ENXIO;
|
||||
}
|
||||
else if ((priv->status & (I2C_IRQ_AERR | I2C_IRQ_ROVR)) != 0)
|
||||
{
|
||||
ret = -EIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = OK;
|
||||
}
|
||||
|
||||
/* Do not leave the bus held, the next transfer would fail too. */
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
am62x_i2c_recover(priv);
|
||||
}
|
||||
|
||||
priv->ptr = NULL;
|
||||
priv->dcnt = 0;
|
||||
nxmutex_unlock(&priv->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_I2C_RESET
|
||||
static int am62x_i2c_reset(struct i2c_master_s *dev)
|
||||
{
|
||||
struct am62x_i2c_priv_s *priv = (struct am62x_i2c_priv_s *)dev;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
return am62x_i2c_init(priv);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
struct i2c_master_s *am62x_i2cbus_initialize(int port)
|
||||
{
|
||||
struct am62x_i2c_priv_s *priv = NULL;
|
||||
|
||||
switch (port)
|
||||
{
|
||||
#ifdef CONFIG_AM62X_I2C0
|
||||
case 0:
|
||||
priv = &g_i2c0_priv;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_AM62X_I2C1
|
||||
case 1:
|
||||
priv = &g_i2c1_priv;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_AM62X_I2C2
|
||||
case 2:
|
||||
priv = &g_i2c2_priv;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_AM62X_I2C3
|
||||
case 3:
|
||||
priv = &g_i2c3_priv;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nxmutex_lock(&priv->lock);
|
||||
if (priv->refs++ == 0)
|
||||
{
|
||||
if (am62x_i2c_init(priv) < 0)
|
||||
{
|
||||
priv->refs--;
|
||||
nxmutex_unlock(&priv->lock);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
nxmutex_unlock(&priv->lock);
|
||||
return (struct i2c_master_s *)priv;
|
||||
}
|
||||
|
||||
int am62x_i2cbus_uninitialize(struct i2c_master_s *dev)
|
||||
{
|
||||
struct am62x_i2c_priv_s *priv = (struct am62x_i2c_priv_s *)dev;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
|
||||
nxmutex_lock(&priv->lock);
|
||||
if (priv->refs == 0)
|
||||
{
|
||||
nxmutex_unlock(&priv->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (--priv->refs == 0)
|
||||
{
|
||||
am62x_i2c_deinit(priv);
|
||||
}
|
||||
|
||||
nxmutex_unlock(&priv->lock);
|
||||
return OK;
|
||||
}
|
||||
|
||||
40
arch/arm64/src/am62x/am62x_i2c.h
Normal file
40
arch/arm64/src/am62x/am62x_i2c.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/am62x/am62x_i2c.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM64_SRC_AM62X_AM62X_I2C_H
|
||||
#define __ARCH_ARM64_SRC_AM62X_AM62X_I2C_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
struct i2c_master_s *am62x_i2cbus_initialize(int port);
|
||||
int am62x_i2cbus_uninitialize(struct i2c_master_s *dev);
|
||||
|
||||
#endif /* __ARCH_ARM64_SRC_AM62X_AM62X_I2C_H */
|
||||
528
arch/arm64/src/am62x/am62x_tisci.c
Normal file
528
arch/arm64/src/am62x/am62x_tisci.c
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/am62x/am62x_tisci.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <nuttx/debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/mutex.h>
|
||||
|
||||
#include "arm64_arch.h"
|
||||
#include "arm64_internal.h"
|
||||
#include "hardware/am62x_memorymap.h"
|
||||
#include "hardware/am62x_secure_proxy.h"
|
||||
#include "hardware/am62x_tisci_proto.h"
|
||||
#include "am62x_tisci.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Host id and secure-proxy thread assignment (Kconfig-tunable; defaults
|
||||
* match the A53 HLOS host on a standard AM62x DM/TIFS boardcfg).
|
||||
*/
|
||||
|
||||
#define AM62X_TISCI_HOST_ID CONFIG_AM62X_TISCI_HOST_ID
|
||||
#define AM62X_TISCI_RX_THREAD CONFIG_AM62X_TISCI_RX_THREAD
|
||||
#define AM62X_TISCI_TX_THREAD CONFIG_AM62X_TISCI_TX_THREAD
|
||||
|
||||
/* Bounded poll: up to ~1 s waiting on a secure-proxy thread credit */
|
||||
|
||||
#define AM62X_TISCI_POLL_US 1
|
||||
#define AM62X_TISCI_POLL_MAX 1000000
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* Serialises the single outstanding request/response transaction */
|
||||
|
||||
static mutex_t g_tisci_lock = NXMUTEX_INITIALIZER;
|
||||
|
||||
/* Rolling sequence number used to match responses to requests */
|
||||
|
||||
static uint8_t g_tisci_seq;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_sproxy_wait
|
||||
*
|
||||
* Description:
|
||||
* Wait until the given secure-proxy thread has a non-zero credit count
|
||||
* (a free slot for TX, or a pending message for RX), or report a thread
|
||||
* error / timeout.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int am62x_sproxy_wait(uintptr_t status_reg)
|
||||
{
|
||||
int retries = AM62X_TISCI_POLL_MAX;
|
||||
uint32_t status;
|
||||
|
||||
do
|
||||
{
|
||||
status = getreg32(status_reg);
|
||||
if ((status & AM62X_SEC_PROXY_RT_ERR) != 0)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if ((status & AM62X_SEC_PROXY_RT_CNT_MASK) != 0)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
up_udelay(AM62X_TISCI_POLL_US);
|
||||
}
|
||||
while (--retries > 0);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_sproxy_send
|
||||
*
|
||||
* Description:
|
||||
* Push a message (up to 60 bytes) onto the TX thread. The message is
|
||||
* zero-padded to the full 15-word window; the write to the final word
|
||||
* (offset 0x3c) commits the transfer to the firmware.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int am62x_sproxy_send(const void *msg, size_t len)
|
||||
{
|
||||
uintptr_t data = AM62X_SEC_PROXY_DATA(AM62X_TISCI_TX_THREAD);
|
||||
uintptr_t status = AM62X_SEC_PROXY_RT(AM62X_TISCI_TX_THREAD) +
|
||||
AM62X_SEC_PROXY_RT_STATUS;
|
||||
uint32_t buf[AM62X_SEC_PROXY_MSG_WORDS];
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (len > AM62X_SEC_PROXY_MAX_MSG_SIZE)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = am62x_sproxy_wait(status);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memcpy(buf, msg, len);
|
||||
|
||||
/* Write all 15 words in ascending order; the last (offset 0x3c) commits. */
|
||||
|
||||
for (i = 0; i < AM62X_SEC_PROXY_MSG_WORDS; i++)
|
||||
{
|
||||
putreg32(buf[i], data + AM62X_SEC_PROXY_DATA_START + i * 4);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_sproxy_recv
|
||||
*
|
||||
* Description:
|
||||
* Read a response from the RX thread. All 15 words are read so the
|
||||
* final-word read marks the message consumed.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int am62x_sproxy_recv(void *msg, size_t len)
|
||||
{
|
||||
uintptr_t data = AM62X_SEC_PROXY_DATA(AM62X_TISCI_RX_THREAD);
|
||||
uintptr_t status = AM62X_SEC_PROXY_RT(AM62X_TISCI_RX_THREAD) +
|
||||
AM62X_SEC_PROXY_RT_STATUS;
|
||||
uint32_t buf[AM62X_SEC_PROXY_MSG_WORDS];
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (len > AM62X_SEC_PROXY_MAX_MSG_SIZE)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = am62x_sproxy_wait(status);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < AM62X_SEC_PROXY_MSG_WORDS; i++)
|
||||
{
|
||||
buf[i] = getreg32(data + AM62X_SEC_PROXY_DATA_START + i * 4);
|
||||
}
|
||||
|
||||
memcpy(msg, buf, len);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_sproxy_drain
|
||||
*
|
||||
* Description:
|
||||
* Discard any stale message pending on the RX thread before a new
|
||||
* transaction, so an orphaned response cannot desynchronise sequencing.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void am62x_sproxy_drain(void)
|
||||
{
|
||||
uintptr_t data = AM62X_SEC_PROXY_DATA(AM62X_TISCI_RX_THREAD);
|
||||
uintptr_t status = AM62X_SEC_PROXY_RT(AM62X_TISCI_RX_THREAD) +
|
||||
AM62X_SEC_PROXY_RT_STATUS;
|
||||
int guard = AM62X_SEC_PROXY_MSG_WORDS + 1;
|
||||
uint32_t s;
|
||||
int i;
|
||||
|
||||
while (guard-- > 0)
|
||||
{
|
||||
s = getreg32(status);
|
||||
if ((s & AM62X_SEC_PROXY_RT_ERR) != 0 ||
|
||||
(s & AM62X_SEC_PROXY_RT_CNT_MASK) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < AM62X_SEC_PROXY_MSG_WORDS; i++)
|
||||
{
|
||||
getreg32(data + AM62X_SEC_PROXY_DATA_START + i * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_tisci_xfer
|
||||
*
|
||||
* Description:
|
||||
* Run one synchronous TISCI request/response. Fills the header host, seq,
|
||||
* and ACK-on-processed flag, sends the request, reads the response, and
|
||||
* validates the ACK and matching sequence number.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int am62x_tisci_xfer(struct ti_sci_msg_hdr *req, size_t req_sz,
|
||||
struct ti_sci_msg_hdr *resp, size_t resp_sz)
|
||||
{
|
||||
uint8_t seq;
|
||||
int ret;
|
||||
|
||||
ret = nxmutex_lock(&g_tisci_lock);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
seq = ++g_tisci_seq;
|
||||
req->host = AM62X_TISCI_HOST_ID;
|
||||
req->seq = seq;
|
||||
req->flags |= TI_SCI_FLAG_REQ_ACK_ON_PROCESSED;
|
||||
|
||||
am62x_sproxy_drain();
|
||||
|
||||
ret = am62x_sproxy_send(req, req_sz);
|
||||
if (ret == OK)
|
||||
{
|
||||
ret = am62x_sproxy_recv(resp, resp_sz);
|
||||
}
|
||||
|
||||
nxmutex_unlock(&g_tisci_lock);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((resp->flags & TI_SCI_FLAG_RESP_GENERIC_ACK) == 0)
|
||||
{
|
||||
return -EIO; /* firmware NAK */
|
||||
}
|
||||
|
||||
if (resp->seq != seq)
|
||||
{
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_tisci_clkid
|
||||
*
|
||||
* Description:
|
||||
* Encode a clock id into the 8-bit clk_id / 32-bit clk_id_32 pair used by
|
||||
* the clock messages.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void am62x_tisci_clkid(uint32_t clkid, uint8_t *clk_id,
|
||||
uint32_t *clk_id_32)
|
||||
{
|
||||
if (clkid < TI_SCI_CLOCK_ID_INDIRECT)
|
||||
{
|
||||
*clk_id = (uint8_t)clkid;
|
||||
*clk_id_32 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*clk_id = TI_SCI_CLOCK_ID_INDIRECT;
|
||||
*clk_id_32 = clkid;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int am62x_tisci_get_version(struct am62x_tisci_version_s *ver)
|
||||
{
|
||||
struct ti_sci_msg_hdr req;
|
||||
struct ti_sci_msg_resp_version resp;
|
||||
int ret;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.type = TI_SCI_MSG_VERSION;
|
||||
|
||||
ret = am62x_tisci_xfer(&req, sizeof(req), &resp.hdr, sizeof(resp));
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ver != NULL)
|
||||
{
|
||||
ver->firmware_revision = resp.firmware_revision;
|
||||
ver->abi_major = resp.abi_major;
|
||||
ver->abi_minor = resp.abi_minor;
|
||||
memcpy(ver->firmware_description, resp.firmware_description,
|
||||
sizeof(resp.firmware_description));
|
||||
ver->firmware_description[sizeof(resp.firmware_description) - 1] =
|
||||
'\0';
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int am62x_tisci_set_device_state(uint32_t devid, uint8_t state)
|
||||
{
|
||||
struct ti_sci_msg_req_set_device_state req;
|
||||
struct ti_sci_msg_hdr resp;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.hdr.type = TI_SCI_MSG_SET_DEVICE_STATE;
|
||||
req.id = devid;
|
||||
req.state = state;
|
||||
|
||||
return am62x_tisci_xfer(&req.hdr, sizeof(req), &resp, sizeof(resp));
|
||||
}
|
||||
|
||||
int am62x_tisci_get_device_state(uint32_t devid, uint8_t *current_state)
|
||||
{
|
||||
struct ti_sci_msg_req_get_device_state req;
|
||||
struct ti_sci_msg_resp_get_device_state resp;
|
||||
int ret;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.hdr.type = TI_SCI_MSG_GET_DEVICE_STATE;
|
||||
req.id = devid;
|
||||
|
||||
ret = am62x_tisci_xfer(&req.hdr, sizeof(req), &resp.hdr, sizeof(resp));
|
||||
if (ret == OK && current_state != NULL)
|
||||
{
|
||||
*current_state = resp.current_state;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int am62x_tisci_module_enable(uint32_t devid, uint32_t clkid)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = am62x_tisci_set_device_state(devid, MSG_DEVICE_SW_STATE_ON);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = am62x_tisci_set_device_resets(devid, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = am62x_tisci_clk_enable(devid, clkid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int am62x_tisci_set_device_resets(uint32_t devid, uint32_t resets)
|
||||
{
|
||||
struct ti_sci_msg_req_set_device_resets req;
|
||||
struct ti_sci_msg_hdr resp;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.hdr.type = TI_SCI_MSG_SET_DEVICE_RESETS;
|
||||
req.id = devid;
|
||||
req.resets = resets;
|
||||
|
||||
return am62x_tisci_xfer(&req.hdr, sizeof(req), &resp, sizeof(resp));
|
||||
}
|
||||
|
||||
int am62x_tisci_set_clock_state(uint32_t devid, uint32_t clkid,
|
||||
uint8_t state)
|
||||
{
|
||||
struct ti_sci_msg_req_set_clock_state req;
|
||||
struct ti_sci_msg_hdr resp;
|
||||
uint8_t clk_id;
|
||||
uint32_t clk_id_32;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.hdr.type = TI_SCI_MSG_SET_CLOCK_STATE;
|
||||
req.dev_id = devid;
|
||||
req.request_state = state;
|
||||
am62x_tisci_clkid(clkid, &clk_id, &clk_id_32);
|
||||
req.clk_id = clk_id;
|
||||
req.clk_id_32 = clk_id_32;
|
||||
|
||||
return am62x_tisci_xfer(&req.hdr, sizeof(req), &resp, sizeof(resp));
|
||||
}
|
||||
|
||||
int am62x_tisci_clk_enable(uint32_t devid, uint32_t clkid)
|
||||
{
|
||||
return am62x_tisci_set_clock_state(devid, clkid, MSG_CLOCK_SW_STATE_REQ);
|
||||
}
|
||||
|
||||
int am62x_tisci_set_clock_freq(uint32_t devid, uint32_t clkid,
|
||||
uint64_t freq_hz)
|
||||
{
|
||||
struct ti_sci_msg_req_set_clock_freq req;
|
||||
struct ti_sci_msg_hdr resp;
|
||||
uint8_t clk_id;
|
||||
uint32_t clk_id_32;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.hdr.type = TI_SCI_MSG_SET_CLOCK_FREQ;
|
||||
req.dev_id = devid;
|
||||
req.min_freq_hz = freq_hz;
|
||||
req.target_freq_hz = freq_hz;
|
||||
req.max_freq_hz = freq_hz;
|
||||
am62x_tisci_clkid(clkid, &clk_id, &clk_id_32);
|
||||
req.clk_id = clk_id;
|
||||
req.clk_id_32 = clk_id_32;
|
||||
|
||||
return am62x_tisci_xfer(&req.hdr, sizeof(req), &resp, sizeof(resp));
|
||||
}
|
||||
|
||||
int am62x_tisci_get_clock_freq(uint32_t devid, uint32_t clkid,
|
||||
uint64_t *freq_hz)
|
||||
{
|
||||
struct ti_sci_msg_req_get_clock_freq req;
|
||||
struct ti_sci_msg_resp_get_clock_freq resp;
|
||||
uint8_t clk_id;
|
||||
uint32_t clk_id_32;
|
||||
int ret;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.hdr.type = TI_SCI_MSG_GET_CLOCK_FREQ;
|
||||
req.dev_id = devid;
|
||||
am62x_tisci_clkid(clkid, &clk_id, &clk_id_32);
|
||||
req.clk_id = clk_id;
|
||||
req.clk_id_32 = clk_id_32;
|
||||
|
||||
ret = am62x_tisci_xfer(&req.hdr, sizeof(req), &resp.hdr, sizeof(resp));
|
||||
if (ret == OK && freq_hz != NULL)
|
||||
{
|
||||
*freq_hz = resp.freq_hz;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int am62x_tisci_irq_set(uint16_t src_id, uint16_t src_index,
|
||||
uint16_t dst_id, uint16_t dst_host_irq)
|
||||
{
|
||||
struct ti_sci_msg_req_manage_irq req;
|
||||
struct ti_sci_msg_hdr resp;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.hdr.type = TI_SCI_MSG_RM_IRQ_SET;
|
||||
req.valid_params = MSG_FLAG_DST_ID_VALID | MSG_FLAG_DST_HOST_IRQ_VALID;
|
||||
req.src_id = src_id;
|
||||
req.src_index = src_index;
|
||||
req.dst_id = dst_id;
|
||||
req.dst_host_irq = dst_host_irq;
|
||||
|
||||
return am62x_tisci_xfer(&req.hdr, sizeof(req), &resp, sizeof(resp));
|
||||
}
|
||||
|
||||
int am62x_tisci_irq_release(uint16_t src_id, uint16_t src_index,
|
||||
uint16_t dst_id, uint16_t dst_host_irq)
|
||||
{
|
||||
struct ti_sci_msg_req_manage_irq req;
|
||||
struct ti_sci_msg_hdr resp;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.hdr.type = TI_SCI_MSG_RM_IRQ_RELEASE;
|
||||
req.valid_params = MSG_FLAG_DST_ID_VALID | MSG_FLAG_DST_HOST_IRQ_VALID;
|
||||
req.src_id = src_id;
|
||||
req.src_index = src_index;
|
||||
req.dst_id = dst_id;
|
||||
req.dst_host_irq = dst_host_irq;
|
||||
|
||||
return am62x_tisci_xfer(&req.hdr, sizeof(req), &resp, sizeof(resp));
|
||||
}
|
||||
|
||||
int am62x_tisci_initialize(void)
|
||||
{
|
||||
struct am62x_tisci_version_s ver;
|
||||
int ret;
|
||||
|
||||
ret = am62x_tisci_get_version(&ver);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
_err("ERROR: TISCI version handshake failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
_info("AM62x TISCI: firmware \"%s\" rev %u ABI %u.%u\n",
|
||||
ver.firmware_description, ver.firmware_revision,
|
||||
ver.abi_major, ver.abi_minor);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
189
arch/arm64/src/am62x/am62x_tisci.h
Normal file
189
arch/arm64/src/am62x/am62x_tisci.h
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/am62x/am62x_tisci.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* AM62x TISCI system-controller client.
|
||||
*
|
||||
* On K3 SoCs the A53 cluster does not directly own device power, clocks,
|
||||
* resets, or interrupt routing. Those are managed by the DM/TIFS firmware
|
||||
* on the R5 and requested over the TISCI protocol via the secure-proxy
|
||||
* mailbox. This client provides the minimal request helpers other AM62x
|
||||
* drivers use to power on a device, enable/set a functional clock, release
|
||||
* resets, and route an interrupt through the interrupt router.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM64_SRC_AM62X_AM62X_TISCI_H
|
||||
#define __ARCH_ARM64_SRC_AM62X_AM62X_TISCI_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Selected TISCI device IDs (ti,sci-dev-id).
|
||||
* Source: Linux arch/arm64/boot/dts/ti/k3-am62-main.dtsi. Extend as drivers
|
||||
* are added; the full list is in the TISCI device documentation for AM62x.
|
||||
*/
|
||||
|
||||
#define AM62X_DEV_GPIOMUX_INTROUTER0 3 /* main_gpiomux_introuter0 */
|
||||
#define AM62X_DEV_GPIO0 77 /* main_gpio0 @ 0x00600000 */
|
||||
#define AM62X_DEV_GPIO1 78 /* main_gpio1 @ 0x00601000 */
|
||||
#define AM62X_DEV_I2C0 102 /* main_i2c0 @ 0x20000000 */
|
||||
#define AM62X_DEV_I2C1 103 /* main_i2c1 @ 0x20010000 */
|
||||
#define AM62X_DEV_I2C2 104 /* main_i2c2 @ 0x20020000 */
|
||||
#define AM62X_DEV_I2C3 105 /* main_i2c3 @ 0x20030000 */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
struct am62x_tisci_version_s
|
||||
{
|
||||
uint16_t firmware_revision;
|
||||
uint8_t abi_major;
|
||||
uint8_t abi_minor;
|
||||
char firmware_description[33]; /* 32 chars + NUL terminator */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_tisci_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialise the TISCI client and verify the secure-proxy link by
|
||||
* issuing a version handshake with the DM/TIFS firmware. Must be called
|
||||
* once, before any other am62x_tisci_* helper, early in board bring-up.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int am62x_tisci_initialize(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_tisci_get_version
|
||||
*
|
||||
* Description:
|
||||
* Query the running system firmware ABI version and description.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int am62x_tisci_get_version(struct am62x_tisci_version_s *ver);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_tisci_set_device_state / am62x_tisci_get_device_state
|
||||
*
|
||||
* Description:
|
||||
* Set or query the software power state of a device (one of
|
||||
* MSG_DEVICE_SW_STATE_*). get returns the current hardware state in
|
||||
* *current_state (one of MSG_DEVICE_HW_STATE_*).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int am62x_tisci_set_device_state(uint32_t devid, uint8_t state);
|
||||
int am62x_tisci_get_device_state(uint32_t devid, uint8_t *current_state);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_tisci_module_enable
|
||||
*
|
||||
* Description:
|
||||
* Power on a device, release all device-local resets, and request its
|
||||
* functional clock. This is the normal sequence before a driver touches
|
||||
* AM62x/K3 peripheral registers.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int am62x_tisci_module_enable(uint32_t devid, uint32_t clkid);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_tisci_set_device_resets
|
||||
*
|
||||
* Description:
|
||||
* Program the device-local reset lines (bitmask; 0 releases all resets).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int am62x_tisci_set_device_resets(uint32_t devid, uint32_t resets);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_tisci_set_clock_state / am62x_tisci_clk_enable
|
||||
*
|
||||
* Description:
|
||||
* Set a clock's software state (one of MSG_CLOCK_SW_STATE_*).
|
||||
* am62x_tisci_clk_enable is a wrapper that requests the clock on.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int am62x_tisci_set_clock_state(uint32_t devid, uint32_t clkid,
|
||||
uint8_t state);
|
||||
int am62x_tisci_clk_enable(uint32_t devid, uint32_t clkid);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_tisci_set_clock_freq / am62x_tisci_get_clock_freq
|
||||
*
|
||||
* Description:
|
||||
* Request a target frequency for a clock, or read its current frequency.
|
||||
* set accepts the target in Hz and asks the firmware to honour it exactly.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int am62x_tisci_set_clock_freq(uint32_t devid, uint32_t clkid,
|
||||
uint64_t freq_hz);
|
||||
int am62x_tisci_get_clock_freq(uint32_t devid, uint32_t clkid,
|
||||
uint64_t *freq_hz);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: am62x_tisci_irq_set / am62x_tisci_irq_release
|
||||
*
|
||||
* Description:
|
||||
* Program (or release) a route through an interrupt router so a peripheral
|
||||
* output interrupt reaches the A53 GIC. src_id is the router's device id,
|
||||
* src_index its input line, dst_id the destination IRQ-controller device
|
||||
* id (the GIC), and dst_host_irq the destination GIC interrupt input.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int am62x_tisci_irq_set(uint16_t src_id, uint16_t src_index,
|
||||
uint16_t dst_id, uint16_t dst_host_irq);
|
||||
int am62x_tisci_irq_release(uint16_t src_id, uint16_t src_index,
|
||||
uint16_t dst_id, uint16_t dst_host_irq);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_ARM64_SRC_AM62X_AM62X_TISCI_H */
|
||||
79
arch/arm64/src/am62x/hardware/am62x_gpio.h
Normal file
79
arch/arm64/src/am62x/hardware/am62x_gpio.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/am62x/hardware/am62x_gpio.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM64_SRC_AM62X_HARDWARE_AM62X_GPIO_H
|
||||
#define __ARCH_ARM64_SRC_AM62X_HARDWARE_AM62X_GPIO_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "hardware/am62x_memorymap.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define AM62X_GPIO_NBANKS 2
|
||||
#define AM62X_GPIO_NPINS 32
|
||||
|
||||
#define AM62X_GPIO_BINTEN_OFFSET 0x0008
|
||||
|
||||
/* AM62x main GPIO uses the Davinci/Keystone register layout. The Linux
|
||||
* binding for k3-am62-main.dtsi advertises compatible = "ti,am64-gpio",
|
||||
* "ti,keystone-gpio" and a 0x100-byte register window.
|
||||
*/
|
||||
|
||||
#define AM62X_GPIO_BANK_STRIDE 0x0028
|
||||
#define AM62X_GPIO_BANK_OFFSET(n) (0x0010 + \
|
||||
(n) * AM62X_GPIO_BANK_STRIDE)
|
||||
#define AM62X_GPIO_DIR_OFFSET(n) (AM62X_GPIO_BANK_OFFSET(n) + 0x00)
|
||||
#define AM62X_GPIO_OUT_DATA_OFFSET(n) (AM62X_GPIO_BANK_OFFSET(n) + 0x04)
|
||||
#define AM62X_GPIO_SET_DATA_OFFSET(n) (AM62X_GPIO_BANK_OFFSET(n) + 0x08)
|
||||
#define AM62X_GPIO_CLR_DATA_OFFSET(n) (AM62X_GPIO_BANK_OFFSET(n) + 0x0c)
|
||||
#define AM62X_GPIO_IN_DATA_OFFSET(n) (AM62X_GPIO_BANK_OFFSET(n) + 0x10)
|
||||
#define AM62X_GPIO_SET_RIS_TRIG_OFFSET(n) \
|
||||
(AM62X_GPIO_BANK_OFFSET(n) + 0x14)
|
||||
#define AM62X_GPIO_CLR_RIS_TRIG_OFFSET(n) \
|
||||
(AM62X_GPIO_BANK_OFFSET(n) + 0x18)
|
||||
#define AM62X_GPIO_SET_FAL_TRIG_OFFSET(n) \
|
||||
(AM62X_GPIO_BANK_OFFSET(n) + 0x1c)
|
||||
#define AM62X_GPIO_CLR_FAL_TRIG_OFFSET(n) \
|
||||
(AM62X_GPIO_BANK_OFFSET(n) + 0x20)
|
||||
#define AM62X_GPIO_INTSTAT_OFFSET(n) (AM62X_GPIO_BANK_OFFSET(n) + 0x24)
|
||||
|
||||
#define AM62X_GPIO_BINTEN(b) ((b) + AM62X_GPIO_BINTEN_OFFSET)
|
||||
#define AM62X_GPIO_DIR(b, n) ((b) + AM62X_GPIO_DIR_OFFSET(n))
|
||||
#define AM62X_GPIO_OUT_DATA(b, n) ((b) + AM62X_GPIO_OUT_DATA_OFFSET(n))
|
||||
#define AM62X_GPIO_SET_DATA(b, n) ((b) + AM62X_GPIO_SET_DATA_OFFSET(n))
|
||||
#define AM62X_GPIO_CLR_DATA(b, n) ((b) + AM62X_GPIO_CLR_DATA_OFFSET(n))
|
||||
#define AM62X_GPIO_IN_DATA(b, n) ((b) + AM62X_GPIO_IN_DATA_OFFSET(n))
|
||||
#define AM62X_GPIO_SET_RIS_TRIG(b, n) ((b) + AM62X_GPIO_SET_RIS_TRIG_OFFSET(n))
|
||||
#define AM62X_GPIO_CLR_RIS_TRIG(b, n) ((b) + AM62X_GPIO_CLR_RIS_TRIG_OFFSET(n))
|
||||
#define AM62X_GPIO_SET_FAL_TRIG(b, n) ((b) + AM62X_GPIO_SET_FAL_TRIG_OFFSET(n))
|
||||
#define AM62X_GPIO_CLR_FAL_TRIG(b, n) ((b) + AM62X_GPIO_CLR_FAL_TRIG_OFFSET(n))
|
||||
#define AM62X_GPIO_INTSTAT(b, n) ((b) + AM62X_GPIO_INTSTAT_OFFSET(n))
|
||||
|
||||
#define AM62X_GPIO_BIT(n) (1u << ((n) & 31))
|
||||
|
||||
#endif /* __ARCH_ARM64_SRC_AM62X_HARDWARE_AM62X_GPIO_H */
|
||||
107
arch/arm64/src/am62x/hardware/am62x_i2c.h
Normal file
107
arch/arm64/src/am62x/hardware/am62x_i2c.h
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/am62x/hardware/am62x_i2c.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM64_SRC_AM62X_HARDWARE_AM62X_I2C_H
|
||||
#define __ARCH_ARM64_SRC_AM62X_HARDWARE_AM62X_I2C_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "hardware/am62x_memorymap.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define AM62X_I2C_REVNB_LO_OFFSET 0x0000
|
||||
#define AM62X_I2C_REVNB_HI_OFFSET 0x0004
|
||||
#define AM62X_I2C_SYSC_OFFSET 0x0010
|
||||
#define AM62X_I2C_IRQSTATUS_RAW_OFFSET 0x0024
|
||||
#define AM62X_I2C_IRQSTATUS_OFFSET 0x0028
|
||||
#define AM62X_I2C_IRQENABLE_SET_OFFSET 0x002c
|
||||
#define AM62X_I2C_IRQENABLE_CLR_OFFSET 0x0030
|
||||
#define AM62X_I2C_WE_OFFSET 0x0034
|
||||
#define AM62X_I2C_SYSS_OFFSET 0x0090
|
||||
#define AM62X_I2C_BUF_OFFSET 0x0094
|
||||
#define AM62X_I2C_CNT_OFFSET 0x0098
|
||||
#define AM62X_I2C_DATA_OFFSET 0x009c
|
||||
#define AM62X_I2C_CON_OFFSET 0x00a4
|
||||
#define AM62X_I2C_OA_OFFSET 0x00a8
|
||||
#define AM62X_I2C_SA_OFFSET 0x00ac
|
||||
#define AM62X_I2C_PSC_OFFSET 0x00b0
|
||||
#define AM62X_I2C_SCLL_OFFSET 0x00b4
|
||||
#define AM62X_I2C_SCLH_OFFSET 0x00b8
|
||||
#define AM62X_I2C_SYSTEST_OFFSET 0x00bc
|
||||
#define AM62X_I2C_BUFSTAT_OFFSET 0x00c0
|
||||
|
||||
#define I2C_SYSC_AUTOIDLE (1 << 0)
|
||||
#define I2C_SYSC_SRST (1 << 1)
|
||||
#define I2C_SYSS_RST_DONE (1 << 0)
|
||||
|
||||
#define I2C_BUF_TXFIFO_CLR (1 << 6)
|
||||
#define I2C_BUF_RXFIFO_CLR (1 << 14)
|
||||
|
||||
#define I2C_IRQ_AL (1 << 0)
|
||||
#define I2C_IRQ_NACK (1 << 1)
|
||||
#define I2C_IRQ_ARDY (1 << 2)
|
||||
#define I2C_IRQ_RRDY (1 << 3)
|
||||
#define I2C_IRQ_XRDY (1 << 4)
|
||||
#define I2C_IRQ_GC (1 << 5)
|
||||
#define I2C_IRQ_STC (1 << 6)
|
||||
#define I2C_IRQ_AERR (1 << 7)
|
||||
#define I2C_IRQ_BF (1 << 8)
|
||||
#define I2C_IRQ_AAS (1 << 9)
|
||||
#define I2C_IRQ_XUDF (1 << 10)
|
||||
#define I2C_IRQ_ROVR (1 << 11)
|
||||
#define I2C_IRQ_BB (1 << 12)
|
||||
#define I2C_IRQ_RDR (1 << 13)
|
||||
#define I2C_IRQ_XDR (1 << 14)
|
||||
|
||||
/* A transmit underflow is not fatal, it is signalled while the module holds
|
||||
* the bus between the messages of a transfer.
|
||||
*/
|
||||
|
||||
#define I2C_IRQ_ERRORMASK (I2C_IRQ_AL | I2C_IRQ_NACK | \
|
||||
I2C_IRQ_AERR | I2C_IRQ_ROVR)
|
||||
|
||||
#define I2C_IRQ_CLEARMASK (I2C_IRQ_AL | I2C_IRQ_NACK | \
|
||||
I2C_IRQ_ARDY | I2C_IRQ_RRDY | \
|
||||
I2C_IRQ_XRDY | I2C_IRQ_GC | \
|
||||
I2C_IRQ_STC | I2C_IRQ_AERR | \
|
||||
I2C_IRQ_BF | I2C_IRQ_AAS | \
|
||||
I2C_IRQ_XUDF | I2C_IRQ_ROVR | \
|
||||
I2C_IRQ_RDR | I2C_IRQ_XDR)
|
||||
|
||||
#define I2C_DATA_MASK 0xff
|
||||
|
||||
#define I2C_CON_STT (1 << 0)
|
||||
#define I2C_CON_STP (1 << 1)
|
||||
#define I2C_CON_XSA (1 << 8)
|
||||
#define I2C_CON_TRX (1 << 9)
|
||||
#define I2C_CON_MST (1 << 10)
|
||||
#define I2C_CON_EN (1 << 15)
|
||||
|
||||
#define I2C_SYSTEST_FREE (1 << 14)
|
||||
|
||||
#endif /* __ARCH_ARM64_SRC_AM62X_HARDWARE_AM62X_I2C_H */
|
||||
|
|
@ -83,6 +83,21 @@
|
|||
#define AM62X_SPI1_BASE 0x20110000ul
|
||||
#define AM62X_SPI2_BASE 0x20120000ul
|
||||
|
||||
/* Secure Proxy (TISCI transport to the DM/TIFS system firmware).
|
||||
* Three 512 KB regions of per-thread 0x1000-stride windows.
|
||||
* Source: Linux k3-am62-main.dtsi (secure_proxy_main).
|
||||
*/
|
||||
|
||||
#define AM62X_SEC_PROXY_DATA_BASE 0x4d000000ul /* "target_data" region */
|
||||
#define AM62X_SEC_PROXY_RT_BASE 0x4a600000ul /* "rt" (status) region */
|
||||
#define AM62X_SEC_PROXY_SCFG_BASE 0x4a400000ul /* "scfg" (config) region */
|
||||
|
||||
/* DMSC / TIFS system controller (TISCI message target).
|
||||
* Source: Linux k3-am62-main.dtsi (dmsc: system-controller@44043000).
|
||||
*/
|
||||
|
||||
#define AM62X_DMSC_BASE 0x44043000ul
|
||||
|
||||
/* USB */
|
||||
|
||||
#define AM62X_USB0_BASE 0x31100000ul
|
||||
|
|
@ -99,10 +114,10 @@
|
|||
#define AM62X_WDT0_BASE 0x23100000ul
|
||||
#define AM62X_WDT1_BASE 0x23110000ul
|
||||
|
||||
/* CTRL_MMR (Pad config / system control) */
|
||||
/* CTRL_MMR (system control) and main-domain pad config */
|
||||
|
||||
#define AM62X_CTRLMMR_BASE 0x000f0000ul
|
||||
#define AM62X_PADCFG_BASE 0x000f0000ul
|
||||
#define AM62X_PADCFG_BASE 0x000f4000ul
|
||||
|
||||
/* DDR Base (512 MB on PocketBeagle 2 / BeaglePlay) */
|
||||
|
||||
|
|
|
|||
88
arch/arm64/src/am62x/hardware/am62x_secure_proxy.h
Normal file
88
arch/arm64/src/am62x/hardware/am62x_secure_proxy.h
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/am62x/hardware/am62x_secure_proxy.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* AM62x Secure Proxy register layout.
|
||||
*
|
||||
* The secure proxy is the mailbox transport used to exchange TISCI messages
|
||||
* between the A53 (running NuttX) and the DM/TIFS system firmware on the R5.
|
||||
* Each "thread" is a unidirectional message queue. A thread occupies a
|
||||
* 0x1000-stride window in each of two regions used here:
|
||||
*
|
||||
* - "target_data" : the message payload, 15 data words per thread
|
||||
* (registers 0..14 at byte offsets 0x4..0x3c). Writing
|
||||
* the last word (offset 0x3c) commits the message;
|
||||
* an RX thread consumes its message by reading it.
|
||||
* - "rt" : per-thread status; bits[7:0] hold the credit/message
|
||||
* count and bit31 flags a thread error.
|
||||
*
|
||||
* The "scfg" region carries per-thread direction config and is not needed
|
||||
* for fixed-direction synchronous request/response operation, so it is
|
||||
* omitted.
|
||||
*
|
||||
* Source: Linux drivers/mailbox/ti-msgmgr.c (k3_secure_proxy_desc and the
|
||||
* SPROXY_THREAD_* macros) and U-Boot drivers/mailbox/k3-sec-proxy.c.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM64_SRC_AM62X_HARDWARE_AM62X_SECURE_PROXY_H
|
||||
#define __ARCH_ARM64_SRC_AM62X_HARDWARE_AM62X_SECURE_PROXY_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "hardware/am62x_memorymap.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Per-thread window stride within each region */
|
||||
|
||||
#define AM62X_SEC_PROXY_THREAD_STRIDE 0x1000ul
|
||||
|
||||
/* target_data region: 15 message words (registers 0..14).
|
||||
* Word "reg" of thread "tid" lives at:
|
||||
* AM62X_SEC_PROXY_DATA_BASE + tid*0x1000 + 0x4 + reg*4
|
||||
* giving the data window 0x4 .. 0x3c (60 bytes maximum per message).
|
||||
*/
|
||||
|
||||
#define AM62X_SEC_PROXY_MSG_WORDS 15
|
||||
#define AM62X_SEC_PROXY_MAX_MSG_SIZE 60
|
||||
#define AM62X_SEC_PROXY_DATA_START 0x4ul /* offset of word 0 */
|
||||
#define AM62X_SEC_PROXY_DATA_END 0x3cul /* offset of word 14 (commit)*/
|
||||
|
||||
/* rt region: per-thread status register at the thread base */
|
||||
|
||||
#define AM62X_SEC_PROXY_RT_STATUS 0x0ul
|
||||
#define AM62X_SEC_PROXY_RT_CNT_MASK 0xfful /* [7:0] credit count */
|
||||
#define AM62X_SEC_PROXY_RT_ERR (1ul << 31) /* [31] thread error */
|
||||
|
||||
/* Region base for a given thread id */
|
||||
|
||||
#define AM62X_SEC_PROXY_DATA(tid) \
|
||||
(AM62X_SEC_PROXY_DATA_BASE + (uintptr_t)(tid) * AM62X_SEC_PROXY_THREAD_STRIDE)
|
||||
#define AM62X_SEC_PROXY_RT(tid) \
|
||||
(AM62X_SEC_PROXY_RT_BASE + (uintptr_t)(tid) * AM62X_SEC_PROXY_THREAD_STRIDE)
|
||||
|
||||
#endif /* __ARCH_ARM64_SRC_AM62X_HARDWARE_AM62X_SECURE_PROXY_H */
|
||||
225
arch/arm64/src/am62x/hardware/am62x_tisci_proto.h
Normal file
225
arch/arm64/src/am62x/hardware/am62x_tisci_proto.h
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/am62x/hardware/am62x_tisci_proto.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* TISCI (Texas Instruments System Control Interface) message protocol
|
||||
* definitions for AM62x. Only the subset used by the NuttX TISCI client is
|
||||
* declared here. Message IDs, flag bits, and on-the-wire structure layouts
|
||||
* mirror the canonical definitions in Linux drivers/firmware/ti_sci.h.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM64_SRC_AM62X_HARDWARE_AM62X_TISCI_PROTO_H
|
||||
#define __ARCH_ARM64_SRC_AM62X_HARDWARE_AM62X_TISCI_PROTO_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/compiler.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* TISCI message type IDs */
|
||||
|
||||
#define TI_SCI_MSG_VERSION 0x0002
|
||||
#define TI_SCI_MSG_SET_CLOCK_STATE 0x0100
|
||||
#define TI_SCI_MSG_GET_CLOCK_STATE 0x0101
|
||||
#define TI_SCI_MSG_SET_CLOCK_FREQ 0x010c
|
||||
#define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e
|
||||
#define TI_SCI_MSG_SET_DEVICE_STATE 0x0200
|
||||
#define TI_SCI_MSG_GET_DEVICE_STATE 0x0201
|
||||
#define TI_SCI_MSG_SET_DEVICE_RESETS 0x0202
|
||||
#define TI_SCI_MSG_RM_IRQ_SET 0x1000
|
||||
#define TI_SCI_MSG_RM_IRQ_RELEASE 0x1001
|
||||
|
||||
/* Message header flags */
|
||||
|
||||
#define TI_SCI_MSG_FLAG(val) (1u << (val))
|
||||
#define TI_SCI_FLAG_REQ_GENERIC_NORESP 0x0
|
||||
#define TI_SCI_FLAG_REQ_ACK_ON_RECEIVED TI_SCI_MSG_FLAG(0)
|
||||
#define TI_SCI_FLAG_REQ_ACK_ON_PROCESSED TI_SCI_MSG_FLAG(1)
|
||||
#define TI_SCI_FLAG_RESP_GENERIC_NACK 0x0
|
||||
#define TI_SCI_FLAG_RESP_GENERIC_ACK TI_SCI_MSG_FLAG(1)
|
||||
|
||||
/* Device-state request: software state values and header flag options */
|
||||
|
||||
#define MSG_DEVICE_SW_STATE_AUTO_OFF 0
|
||||
#define MSG_DEVICE_SW_STATE_RETENTION 1
|
||||
#define MSG_DEVICE_SW_STATE_ON 2
|
||||
|
||||
#define MSG_FLAG_DEVICE_WAKE_ENABLED TI_SCI_MSG_FLAG(8)
|
||||
#define MSG_FLAG_DEVICE_RESET_ISO TI_SCI_MSG_FLAG(9)
|
||||
#define MSG_FLAG_DEVICE_EXCLUSIVE TI_SCI_MSG_FLAG(10)
|
||||
|
||||
/* Device-state response: hardware state values */
|
||||
|
||||
#define MSG_DEVICE_HW_STATE_OFF 0
|
||||
#define MSG_DEVICE_HW_STATE_ON 1
|
||||
#define MSG_DEVICE_HW_STATE_TRANS 2
|
||||
|
||||
/* Clock-state request: software state values and header flag options */
|
||||
|
||||
#define MSG_CLOCK_SW_STATE_UNREQ 0
|
||||
#define MSG_CLOCK_SW_STATE_AUTO 1
|
||||
#define MSG_CLOCK_SW_STATE_REQ 2
|
||||
|
||||
#define MSG_FLAG_CLOCK_ALLOW_SSC TI_SCI_MSG_FLAG(8)
|
||||
#define MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE TI_SCI_MSG_FLAG(9)
|
||||
#define MSG_FLAG_CLOCK_INPUT_TERM TI_SCI_MSG_FLAG(10)
|
||||
|
||||
/* When a clk_id does not fit in the 8-bit clk_id field, it is set to 255 and
|
||||
* the real id is carried in the 32-bit clk_id_32 field.
|
||||
*/
|
||||
|
||||
#define TI_SCI_CLOCK_ID_INDIRECT 255
|
||||
|
||||
/* Resource-management IRQ request: valid_params bit flags */
|
||||
|
||||
#define MSG_FLAG_DST_ID_VALID TI_SCI_MSG_FLAG(0)
|
||||
#define MSG_FLAG_DST_HOST_IRQ_VALID TI_SCI_MSG_FLAG(1)
|
||||
#define MSG_FLAG_IA_ID_VALID TI_SCI_MSG_FLAG(2)
|
||||
#define MSG_FLAG_VINT_VALID TI_SCI_MSG_FLAG(3)
|
||||
#define MSG_FLAG_GLB_EVNT_VALID TI_SCI_MSG_FLAG(4)
|
||||
#define MSG_FLAG_VINT_STS_BIT_VALID TI_SCI_MSG_FLAG(5)
|
||||
#define MSG_FLAG_SHOST_VALID TI_SCI_MSG_FLAG(31)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Common message header (prefixes every request and response) */
|
||||
|
||||
begin_packed_struct struct ti_sci_msg_hdr
|
||||
{
|
||||
uint16_t type;
|
||||
uint8_t host;
|
||||
uint8_t seq;
|
||||
uint32_t flags;
|
||||
} end_packed_struct;
|
||||
|
||||
/* TI_SCI_MSG_VERSION */
|
||||
|
||||
begin_packed_struct struct ti_sci_msg_resp_version
|
||||
{
|
||||
struct ti_sci_msg_hdr hdr;
|
||||
char firmware_description[32];
|
||||
uint16_t firmware_revision;
|
||||
uint8_t abi_major;
|
||||
uint8_t abi_minor;
|
||||
} end_packed_struct;
|
||||
|
||||
/* TI_SCI_MSG_SET_DEVICE_STATE / GET_DEVICE_STATE */
|
||||
|
||||
begin_packed_struct struct ti_sci_msg_req_set_device_state
|
||||
{
|
||||
struct ti_sci_msg_hdr hdr;
|
||||
uint32_t id;
|
||||
uint32_t reserved;
|
||||
uint8_t state;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct ti_sci_msg_req_get_device_state
|
||||
{
|
||||
struct ti_sci_msg_hdr hdr;
|
||||
uint32_t id;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct ti_sci_msg_resp_get_device_state
|
||||
{
|
||||
struct ti_sci_msg_hdr hdr;
|
||||
uint32_t context_loss_count;
|
||||
uint32_t resets;
|
||||
uint8_t programmed_state;
|
||||
uint8_t current_state;
|
||||
} end_packed_struct;
|
||||
|
||||
/* TI_SCI_MSG_SET_DEVICE_RESETS */
|
||||
|
||||
begin_packed_struct struct ti_sci_msg_req_set_device_resets
|
||||
{
|
||||
struct ti_sci_msg_hdr hdr;
|
||||
uint32_t id;
|
||||
uint32_t resets;
|
||||
} end_packed_struct;
|
||||
|
||||
/* TI_SCI_MSG_SET_CLOCK_STATE */
|
||||
|
||||
begin_packed_struct struct ti_sci_msg_req_set_clock_state
|
||||
{
|
||||
struct ti_sci_msg_hdr hdr;
|
||||
uint32_t dev_id;
|
||||
uint8_t clk_id;
|
||||
uint8_t request_state;
|
||||
uint32_t clk_id_32;
|
||||
} end_packed_struct;
|
||||
|
||||
/* TI_SCI_MSG_SET_CLOCK_FREQ */
|
||||
|
||||
begin_packed_struct struct ti_sci_msg_req_set_clock_freq
|
||||
{
|
||||
struct ti_sci_msg_hdr hdr;
|
||||
uint32_t dev_id;
|
||||
uint64_t min_freq_hz;
|
||||
uint64_t target_freq_hz;
|
||||
uint64_t max_freq_hz;
|
||||
uint8_t clk_id;
|
||||
uint32_t clk_id_32;
|
||||
} end_packed_struct;
|
||||
|
||||
/* TI_SCI_MSG_GET_CLOCK_FREQ */
|
||||
|
||||
begin_packed_struct struct ti_sci_msg_req_get_clock_freq
|
||||
{
|
||||
struct ti_sci_msg_hdr hdr;
|
||||
uint32_t dev_id;
|
||||
uint8_t clk_id;
|
||||
uint32_t clk_id_32;
|
||||
} end_packed_struct;
|
||||
|
||||
begin_packed_struct struct ti_sci_msg_resp_get_clock_freq
|
||||
{
|
||||
struct ti_sci_msg_hdr hdr;
|
||||
uint64_t freq_hz;
|
||||
} end_packed_struct;
|
||||
|
||||
/* TI_SCI_MSG_RM_IRQ_SET / RM_IRQ_RELEASE */
|
||||
|
||||
begin_packed_struct struct ti_sci_msg_req_manage_irq
|
||||
{
|
||||
struct ti_sci_msg_hdr hdr;
|
||||
uint32_t valid_params;
|
||||
uint16_t src_id;
|
||||
uint16_t src_index;
|
||||
uint16_t dst_id;
|
||||
uint16_t dst_host_irq;
|
||||
uint16_t ia_id;
|
||||
uint16_t vint;
|
||||
uint16_t global_event;
|
||||
uint8_t vint_status_bit;
|
||||
uint8_t secondary_host;
|
||||
} end_packed_struct;
|
||||
|
||||
#endif /* __ARCH_ARM64_SRC_AM62X_HARDWARE_AM62X_TISCI_PROTO_H */
|
||||
69
boards/arm64/am62x/beagleplay/configs/i2c/defconfig
Normal file
69
boards/arm64/am62x/beagleplay/configs/i2c/defconfig
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#
|
||||
# This file is autogenerated: PLEASE DO NOT EDIT IT.
|
||||
#
|
||||
# You can use "make menuconfig" to make any modifications to the installed .config file.
|
||||
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
|
||||
# modifications.
|
||||
#
|
||||
CONFIG_16550_ADDRWIDTH=0
|
||||
CONFIG_16550_POLLING=y
|
||||
CONFIG_16550_SET_MCR_OUT2=y
|
||||
CONFIG_16550_SUPRESS_INITIAL_CONFIG=y
|
||||
CONFIG_16550_UART0=y
|
||||
CONFIG_16550_UART0_BASE=0x02800000
|
||||
CONFIG_16550_UART0_CLOCK=48000000
|
||||
CONFIG_16550_UART0_IRQ=210
|
||||
CONFIG_16550_UART0_RX_TRIGGER=0
|
||||
CONFIG_16550_UART0_SERIAL_CONSOLE=y
|
||||
CONFIG_16550_UART=y
|
||||
CONFIG_AM62X_GPIO=y
|
||||
CONFIG_AM62X_I2C0=y
|
||||
CONFIG_AM62X_I2C1=y
|
||||
CONFIG_AM62X_TISCI=y
|
||||
CONFIG_ARCH="arm64"
|
||||
CONFIG_ARCH_ARM64=y
|
||||
CONFIG_ARCH_BOARD="beagleplay"
|
||||
CONFIG_ARCH_BOARD_BEAGLEPLAY=y
|
||||
CONFIG_ARCH_CHIP="am62x"
|
||||
CONFIG_ARCH_CHIP_AM62X=y
|
||||
CONFIG_ARCH_EARLY_PRINT=y
|
||||
CONFIG_ARCH_INTERRUPTSTACK=4096
|
||||
CONFIG_ARCH_IRQPRIO=y
|
||||
CONFIG_BOARD_LOOPSPERMSEC=100000
|
||||
CONFIG_BUILTIN=y
|
||||
CONFIG_DEBUG_ASSERTIONS=y
|
||||
CONFIG_DEBUG_FEATURES=y
|
||||
CONFIG_DEBUG_FULLOPT=y
|
||||
CONFIG_DEBUG_SCHED=y
|
||||
CONFIG_DEBUG_SCHED_ERROR=y
|
||||
CONFIG_DEBUG_SCHED_WARN=y
|
||||
CONFIG_DEBUG_SYMBOLS=y
|
||||
CONFIG_DEFAULT_TASK_STACKSIZE=8192
|
||||
CONFIG_FS_PROCFS=y
|
||||
CONFIG_HAVE_CXX=y
|
||||
CONFIG_HAVE_CXXINITIALIZE=y
|
||||
CONFIG_I2C=y
|
||||
CONFIG_IDLETHREAD_STACKSIZE=8192
|
||||
CONFIG_INIT_ENTRYPOINT="nsh_main"
|
||||
CONFIG_INTELHEX_BINARY=y
|
||||
CONFIG_NSH_BUILTIN_APPS=y
|
||||
CONFIG_NSH_FILEIOSIZE=512
|
||||
CONFIG_NSH_READLINE=y
|
||||
CONFIG_PREALLOC_TIMERS=4
|
||||
CONFIG_PTHREAD_STACK_MIN=8192
|
||||
CONFIG_RAMLOG=y
|
||||
CONFIG_RAM_SIZE=536870912
|
||||
CONFIG_RAM_START=0x80000000
|
||||
CONFIG_RAW_BINARY=y
|
||||
CONFIG_READLINE_CMD_HISTORY=y
|
||||
CONFIG_RR_INTERVAL=200
|
||||
CONFIG_SCHED_HPWORK=y
|
||||
CONFIG_SCHED_HPWORKPRIORITY=192
|
||||
CONFIG_SCHED_WAITPID=y
|
||||
CONFIG_SERIAL_UART_ARCH_MMIO=y
|
||||
CONFIG_SPINLOCK=y
|
||||
CONFIG_STACK_COLORATION=y
|
||||
CONFIG_SYMTAB_ORDEREDBYNAME=y
|
||||
CONFIG_SYSTEM_I2CTOOL=y
|
||||
CONFIG_SYSTEM_NSH=y
|
||||
CONFIG_USEC_PER_TICK=1000
|
||||
|
|
@ -16,6 +16,8 @@ CONFIG_16550_UART0_IRQ=210
|
|||
CONFIG_16550_UART0_RX_TRIGGER=0
|
||||
CONFIG_16550_UART0_SERIAL_CONSOLE=y
|
||||
CONFIG_16550_UART=y
|
||||
CONFIG_AM62X_GPIO=y
|
||||
CONFIG_AM62X_TISCI=y
|
||||
CONFIG_ARCH="arm64"
|
||||
CONFIG_ARCH_ARM64=y
|
||||
CONFIG_ARCH_BOARD="beagleplay"
|
||||
|
|
|
|||
|
|
@ -3,6 +3,21 @@
|
|||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* BeaglePlay (AM6254) — 2 GB LPDDR4 at 0x8000_0000.
|
||||
* NuttX load address = 0x8200_0000 to avoid the DDR region reserved by
|
||||
* the BeagleBoard.org U-Boot environment.
|
||||
|
|
|
|||
|
|
@ -3,6 +3,21 @@
|
|||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* BeaglePlay (AM6254) linker script.
|
||||
* Load address 0x8200_0000 avoids U-Boot reserved region at DDR base.
|
||||
* Identical in structure to the PocketBeagle 2 script; kept separate so
|
||||
|
|
|
|||
|
|
@ -25,16 +25,52 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
|
||||
#include "am62x_gpio.h"
|
||||
#include "am62x_i2c.h"
|
||||
#include "am62x_tisci.h"
|
||||
#include "beagleplay.h"
|
||||
|
||||
#ifdef CONFIG_FS_PROCFS
|
||||
# include <nuttx/fs/fs.h>
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_I2C_DRIVER) && \
|
||||
(defined(CONFIG_AM62X_I2C0) || defined(CONFIG_AM62X_I2C1))
|
||||
static int am62x_i2cdev_register(int bus)
|
||||
{
|
||||
struct i2c_master_s *i2c;
|
||||
int ret;
|
||||
|
||||
i2c = am62x_i2cbus_initialize(bus);
|
||||
if (i2c == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to initialize I2C%d\n", bus);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = i2c_register(i2c, bus);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to register /dev/i2c%d: %d\n",
|
||||
bus, ret);
|
||||
am62x_i2cbus_uninitialize(i2c);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
@ -44,13 +80,7 @@
|
|||
*
|
||||
* Description:
|
||||
* Bring up board features after the scheduler and device drivers are
|
||||
* initialised. This is the right place to:
|
||||
* - Mount pseudo file systems (procfs, etc.)
|
||||
* - Register I2C / SPI bus instances
|
||||
* - Attach sensor drivers
|
||||
*
|
||||
* Phase 1 only mounts procfs — additional drivers will be added as the
|
||||
* port matures.
|
||||
* initialised.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure. Non-fatal errors
|
||||
|
|
@ -63,8 +93,6 @@ int beagleplay_bringup(void)
|
|||
int ret = OK;
|
||||
|
||||
#ifdef CONFIG_FS_PROCFS
|
||||
/* Mount the process filesystem at /proc */
|
||||
|
||||
ret = nx_mount(NULL, "/proc", "procfs", 0, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
|
|
@ -73,5 +101,41 @@ int beagleplay_bringup(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AM62X_TISCI
|
||||
/* Bring up the TISCI link first: peripheral power, clocks, resets, and
|
||||
* interrupt routing are requested from the DM/TIFS firmware through it.
|
||||
*/
|
||||
|
||||
ret = am62x_tisci_initialize();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to initialize TISCI: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AM62X_GPIO
|
||||
ret = am62x_gpio_initialize();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to initialize GPIO: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_I2C_DRIVER) && defined(CONFIG_AM62X_I2C0)
|
||||
ret = am62x_i2cdev_register(0);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to bring up I2C0: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_I2C_DRIVER) && defined(CONFIG_AM62X_I2C1)
|
||||
ret = am62x_i2cdev_register(1);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to bring up I2C1: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
71
boards/arm64/am62x/pocketbeagle2/configs/i2c/defconfig
Normal file
71
boards/arm64/am62x/pocketbeagle2/configs/i2c/defconfig
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
#
|
||||
# This file is autogenerated: PLEASE DO NOT EDIT IT.
|
||||
#
|
||||
# You can use "make menuconfig" to make any modifications to the installed .config file.
|
||||
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
|
||||
# modifications.
|
||||
#
|
||||
CONFIG_16550_ADDRWIDTH=0
|
||||
CONFIG_16550_POLLING=y
|
||||
CONFIG_16550_REGWIDTH=32
|
||||
CONFIG_16550_SET_MCR_OUT2=y
|
||||
CONFIG_16550_SUPRESS_INITIAL_CONFIG=y
|
||||
CONFIG_16550_UART0=y
|
||||
CONFIG_16550_UART0_BASE=0x02860000
|
||||
CONFIG_16550_UART0_CLOCK=48000000
|
||||
CONFIG_16550_UART0_IRQ=216
|
||||
CONFIG_16550_UART0_RX_TRIGGER=0
|
||||
CONFIG_16550_UART0_SERIAL_CONSOLE=y
|
||||
CONFIG_16550_UART=y
|
||||
CONFIG_AM62X_GPIO=y
|
||||
CONFIG_AM62X_I2C0=y
|
||||
CONFIG_AM62X_I2C2=y
|
||||
CONFIG_AM62X_TISCI=y
|
||||
CONFIG_ARCH="arm64"
|
||||
CONFIG_ARCH_ARM64=y
|
||||
CONFIG_ARCH_BOARD="pocketbeagle2"
|
||||
CONFIG_ARCH_BOARD_POCKETBEAGLE2=y
|
||||
CONFIG_ARCH_CHIP="am62x"
|
||||
CONFIG_ARCH_CHIP_AM62X=y
|
||||
CONFIG_ARCH_EARLY_PRINT=y
|
||||
CONFIG_ARCH_INTERRUPTSTACK=4096
|
||||
CONFIG_ARCH_IRQPRIO=y
|
||||
CONFIG_BOARD_LOOPSPERMSEC=100000
|
||||
CONFIG_BUILTIN=y
|
||||
CONFIG_DEBUG_ASSERTIONS=y
|
||||
CONFIG_DEBUG_FEATURES=y
|
||||
CONFIG_DEBUG_FULLOPT=y
|
||||
CONFIG_DEBUG_SCHED=y
|
||||
CONFIG_DEBUG_SCHED_ERROR=y
|
||||
CONFIG_DEBUG_SCHED_WARN=y
|
||||
CONFIG_DEBUG_SYMBOLS=y
|
||||
CONFIG_DEFAULT_TASK_STACKSIZE=8192
|
||||
CONFIG_FS_PROCFS=y
|
||||
CONFIG_HAVE_CXX=y
|
||||
CONFIG_HAVE_CXXINITIALIZE=y
|
||||
CONFIG_I2C=y
|
||||
CONFIG_IDLETHREAD_STACKSIZE=8192
|
||||
CONFIG_INIT_ENTRYPOINT="nsh_main"
|
||||
CONFIG_INTELHEX_BINARY=y
|
||||
CONFIG_NSH_BUILTIN_APPS=y
|
||||
CONFIG_NSH_FILEIOSIZE=512
|
||||
CONFIG_NSH_READLINE=y
|
||||
CONFIG_PREALLOC_TIMERS=4
|
||||
CONFIG_PTHREAD_STACK_MIN=8192
|
||||
CONFIG_RAMLOG=y
|
||||
CONFIG_RAM_SIZE=536870912
|
||||
CONFIG_RAM_START=0x80000000
|
||||
CONFIG_RAM_VSTART=0x80000000
|
||||
CONFIG_RAW_BINARY=y
|
||||
CONFIG_READLINE_CMD_HISTORY=y
|
||||
CONFIG_RR_INTERVAL=200
|
||||
CONFIG_SCHED_HPWORK=y
|
||||
CONFIG_SCHED_HPWORKPRIORITY=192
|
||||
CONFIG_SCHED_WAITPID=y
|
||||
CONFIG_SERIAL_UART_ARCH_MMIO=y
|
||||
CONFIG_SPINLOCK=y
|
||||
CONFIG_STACK_COLORATION=y
|
||||
CONFIG_SYMTAB_ORDEREDBYNAME=y
|
||||
CONFIG_SYSTEM_I2CTOOL=y
|
||||
CONFIG_SYSTEM_NSH=y
|
||||
CONFIG_USEC_PER_TICK=1000
|
||||
|
|
@ -17,6 +17,8 @@ CONFIG_16550_UART0_IRQ=216
|
|||
CONFIG_16550_UART0_RX_TRIGGER=0
|
||||
CONFIG_16550_UART0_SERIAL_CONSOLE=y
|
||||
CONFIG_16550_UART=y
|
||||
CONFIG_AM62X_GPIO=y
|
||||
CONFIG_AM62X_TISCI=y
|
||||
CONFIG_ARCH="arm64"
|
||||
CONFIG_ARCH_ARM64=y
|
||||
CONFIG_ARCH_BOARD="pocketbeagle2"
|
||||
|
|
|
|||
|
|
@ -52,24 +52,25 @@
|
|||
|
||||
/* LED definitions *********************************************************
|
||||
*
|
||||
* PocketBeagle 2 user LEDs are connected to GPIO pins on the AM6254.
|
||||
* The exact GPIO numbers will be finalised when the GPIO driver is added;
|
||||
* these defines are placeholders so board code can compile now.
|
||||
*
|
||||
* LED index Colour Net name
|
||||
* 0 USR0 Green
|
||||
* 1 USR1 Yellow/Amber
|
||||
* 2 USR2 Red
|
||||
* The PocketBeagle 2 user LEDs are on main GPIO0 lines 3-6.
|
||||
*/
|
||||
|
||||
#define BOARD_LED_USR0 0
|
||||
#define BOARD_LED_USR1 1
|
||||
#define BOARD_LED_USR2 2
|
||||
#define BOARD_NLEDS 3
|
||||
#define BOARD_LED_USR3 3
|
||||
#define BOARD_NLEDS 4
|
||||
|
||||
#define BOARD_LED_USR0_BIT (1 << BOARD_LED_USR0)
|
||||
#define BOARD_LED_USR1_BIT (1 << BOARD_LED_USR1)
|
||||
#define BOARD_LED_USR2_BIT (1 << BOARD_LED_USR2)
|
||||
#define BOARD_LED_USR3_BIT (1 << BOARD_LED_USR3)
|
||||
|
||||
/* GPIO test devices ********************************************************/
|
||||
|
||||
#define BOARD_NGPIOOUT 4
|
||||
#define BOARD_NGPIOIN 0
|
||||
#define BOARD_NGPIOINT 0
|
||||
|
||||
/* LED encoded OS states (used when CONFIG_ARCH_LEDS is set) ***************
|
||||
*
|
||||
|
|
|
|||
|
|
@ -26,4 +26,8 @@ if(CONFIG_ARCH_LEDS)
|
|||
list(APPEND SRCS pocketbeagle2_autoleds.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_DEV_GPIO)
|
||||
list(APPEND SRCS pocketbeagle2_gpio.c)
|
||||
endif()
|
||||
|
||||
target_sources(board PRIVATE ${SRCS})
|
||||
|
|
|
|||
|
|
@ -32,4 +32,8 @@ ifeq ($(CONFIG_ARCH_LEDS),y)
|
|||
CSRCS += pocketbeagle2_autoleds.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DEV_GPIO),y)
|
||||
CSRCS += pocketbeagle2_gpio.c
|
||||
endif
|
||||
|
||||
include $(TOPDIR)/boards/Board.mk
|
||||
|
|
|
|||
|
|
@ -71,6 +71,18 @@ int pocketbeagle2_bringup(void);
|
|||
void pocketbeagle2_led_initialize(void);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: pocketbeagle2_gpio_initialize
|
||||
*
|
||||
* Description:
|
||||
* Register board GPIO test devices under /dev/gpioN.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF)
|
||||
int pocketbeagle2_gpio_initialize(void);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,17 +25,95 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <syslog.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/i2c/i2c_master.h>
|
||||
|
||||
#include "am62x_gpio.h"
|
||||
#include "am62x_i2c.h"
|
||||
#include "am62x_tisci.h"
|
||||
#include "pocketbeagle2.h"
|
||||
|
||||
#ifdef CONFIG_FS_PROCFS
|
||||
# include <nuttx/fs/fs.h>
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_I2C_DRIVER) && \
|
||||
(defined(CONFIG_AM62X_I2C0) || defined(CONFIG_AM62X_I2C2))
|
||||
static int am62x_i2cdev_register(int bus)
|
||||
{
|
||||
struct i2c_master_s *i2c;
|
||||
int ret;
|
||||
|
||||
i2c = am62x_i2cbus_initialize(bus);
|
||||
if (i2c == NULL)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to initialize I2C%d\n", bus);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = i2c_register(i2c, bus);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to register /dev/i2c%d: %d\n",
|
||||
bus, ret);
|
||||
am62x_i2cbus_uninitialize(i2c);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_AM62X_I2C0) || defined(CONFIG_AM62X_I2C2)
|
||||
static int pocketbeagle2_i2c_pinmux(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_AM62X_I2C0
|
||||
uint32_t i2c0_cfg = AM62X_PADCFG_RXACTIVE | AM62X_PADCFG_PULL_UP |
|
||||
AM62X_PADCFG_MUXMODE(0);
|
||||
|
||||
ret = am62x_pinmux_configure(0x01e0, i2c0_cfg); /* I2C0_SCL */
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = am62x_pinmux_configure(0x01e4, i2c0_cfg); /* I2C0_SDA */
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AM62X_I2C2
|
||||
uint32_t i2c2_cfg = AM62X_PADCFG_RXACTIVE | AM62X_PADCFG_PULL_UP |
|
||||
AM62X_PADCFG_MUXMODE(1);
|
||||
|
||||
ret = am62x_pinmux_configure(0x00b0, i2c2_cfg); /* P1.28 I2C2_SCL */
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = am62x_pinmux_configure(0x00b4, i2c2_cfg); /* P1.26 I2C2_SDA */
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
|
@ -45,13 +123,7 @@
|
|||
*
|
||||
* Description:
|
||||
* Bring up board features after the scheduler and device drivers are
|
||||
* initialised. This is the right place to:
|
||||
* - Mount pseudo file systems (procfs, etc.)
|
||||
* - Register I2C / SPI bus instances
|
||||
* - Attach sensor drivers
|
||||
*
|
||||
* Phase 1 only mounts procfs — additional drivers will be added as the
|
||||
* port matures.
|
||||
* initialised.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) on success; a negated errno on failure. Non-fatal errors
|
||||
|
|
@ -64,8 +136,6 @@ int pocketbeagle2_bringup(void)
|
|||
int ret = OK;
|
||||
|
||||
#ifdef CONFIG_FS_PROCFS
|
||||
/* Mount the process filesystem at /proc */
|
||||
|
||||
ret = nx_mount(NULL, "/proc", "procfs", 0, NULL);
|
||||
if (ret < 0)
|
||||
{
|
||||
|
|
@ -74,13 +144,57 @@ int pocketbeagle2_bringup(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* TODO Phase 2:
|
||||
* I2C bus registration (am62x I2C0/I2C1)
|
||||
* SPI bus registration (am62x SPI0)
|
||||
* MMC/SD registration (am62x MMCSD0 / MMCSD1)
|
||||
* GPIO driver registration
|
||||
* USB device/host registration
|
||||
#ifdef CONFIG_AM62X_TISCI
|
||||
/* Bring up the TISCI link first: peripheral power, clocks, resets, and
|
||||
* interrupt routing are requested from the DM/TIFS firmware through it.
|
||||
*/
|
||||
|
||||
ret = am62x_tisci_initialize();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to initialize TISCI: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AM62X_GPIO
|
||||
ret = am62x_gpio_initialize();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to initialize GPIO: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF)
|
||||
ret = pocketbeagle2_gpio_initialize();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to register GPIO devices: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_AM62X_I2C0) || defined(CONFIG_AM62X_I2C2)
|
||||
ret = pocketbeagle2_i2c_pinmux();
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to configure I2C pinmux: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_I2C_DRIVER) && defined(CONFIG_AM62X_I2C0)
|
||||
ret = am62x_i2cdev_register(0);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to bring up I2C0: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_I2C_DRIVER) && defined(CONFIG_AM62X_I2C2)
|
||||
ret = am62x_i2cdev_register(2);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "ERROR: Failed to bring up I2C2: %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
165
boards/arm64/am62x/pocketbeagle2/src/pocketbeagle2_gpio.c
Normal file
165
boards/arm64/am62x/pocketbeagle2/src/pocketbeagle2_gpio.c
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
/****************************************************************************
|
||||
* boards/arm64/am62x/pocketbeagle2/src/pocketbeagle2_gpio.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/ioexpander/gpio.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "am62x_gpio.h"
|
||||
#include "pocketbeagle2.h"
|
||||
|
||||
#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF)
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define PB2_GPIO_OUT_FLAGS (AM62X_GPIO_OUTPUT | AM62X_GPIO_PULL_NONE)
|
||||
#define PB2_LED_PADCFG (AM62X_PADCFG_PULL_DISABLE | \
|
||||
AM62X_PADCFG_MUXMODE(7))
|
||||
#define PB2_PADCFG_GPIO0_3 0x000c
|
||||
#define PB2_PADCFG_GPIO0_4 0x0010
|
||||
#define PB2_PADCFG_GPIO0_5 0x0014
|
||||
#define PB2_PADCFG_GPIO0_6 0x0018
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct pocketbeagle2_gpio_dev_s
|
||||
{
|
||||
struct gpio_dev_s gpio;
|
||||
uint8_t id;
|
||||
};
|
||||
|
||||
struct pocketbeagle2_gpio_pin_s
|
||||
{
|
||||
gpio_pinset_t pinset;
|
||||
uintptr_t padcfg;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static int gpout_read(struct gpio_dev_s *dev, bool *value);
|
||||
static int gpout_write(struct gpio_dev_s *dev, bool value);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct gpio_operations_s gpout_ops =
|
||||
{
|
||||
.go_read = gpout_read,
|
||||
.go_write = gpout_write,
|
||||
.go_attach = NULL,
|
||||
.go_enable = NULL,
|
||||
};
|
||||
|
||||
static const struct pocketbeagle2_gpio_pin_s g_gpiooutputs[BOARD_NGPIOOUT] =
|
||||
{
|
||||
{ AM62X_GPIO_PIN(0, 3) | PB2_GPIO_OUT_FLAGS, PB2_PADCFG_GPIO0_3 },
|
||||
{ AM62X_GPIO_PIN(0, 4) | PB2_GPIO_OUT_FLAGS, PB2_PADCFG_GPIO0_4 },
|
||||
{ AM62X_GPIO_PIN(0, 5) | PB2_GPIO_OUT_FLAGS, PB2_PADCFG_GPIO0_5 },
|
||||
{ AM62X_GPIO_PIN(0, 6) | PB2_GPIO_OUT_FLAGS, PB2_PADCFG_GPIO0_6 },
|
||||
};
|
||||
|
||||
static struct pocketbeagle2_gpio_dev_s g_gpout[BOARD_NGPIOOUT];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int gpout_read(struct gpio_dev_s *dev, bool *value)
|
||||
{
|
||||
struct pocketbeagle2_gpio_dev_s *pb2gpio =
|
||||
(struct pocketbeagle2_gpio_dev_s *)dev;
|
||||
|
||||
DEBUGASSERT(pb2gpio != NULL);
|
||||
DEBUGASSERT(value != NULL);
|
||||
DEBUGASSERT(pb2gpio->id < BOARD_NGPIOOUT);
|
||||
|
||||
*value = am62x_gpiooutread(g_gpiooutputs[pb2gpio->id].pinset);
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int gpout_write(struct gpio_dev_s *dev, bool value)
|
||||
{
|
||||
struct pocketbeagle2_gpio_dev_s *pb2gpio =
|
||||
(struct pocketbeagle2_gpio_dev_s *)dev;
|
||||
|
||||
DEBUGASSERT(pb2gpio != NULL);
|
||||
DEBUGASSERT(pb2gpio->id < BOARD_NGPIOOUT);
|
||||
|
||||
am62x_gpiowrite(g_gpiooutputs[pb2gpio->id].pinset, value);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int pocketbeagle2_gpio_initialize(void)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < BOARD_NGPIOOUT; i++)
|
||||
{
|
||||
ret = am62x_pinmux_configure(g_gpiooutputs[i].padcfg, PB2_LED_PADCFG);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = am62x_configgpio(g_gpiooutputs[i].pinset);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
g_gpout[i].gpio.gp_pintype = GPIO_OUTPUT_PIN;
|
||||
g_gpout[i].gpio.gp_ops = &gpout_ops;
|
||||
g_gpout[i].id = i;
|
||||
|
||||
ret = gpio_pin_register(&g_gpout[i].gpio,
|
||||
AM62X_GPIO_LINE(g_gpiooutputs[i].pinset));
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
#endif /* defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF) */
|
||||
Loading…
Add table
Add a link
Reference in a new issue