diff --git a/Documentation/introduction/supported_platforms.rst b/Documentation/introduction/supported_platforms.rst index 5f3e5f7b870..a634a80d01a 100644 --- a/Documentation/introduction/supported_platforms.rst +++ b/Documentation/introduction/supported_platforms.rst @@ -102,6 +102,7 @@ MCU. Follow the links for the details: - Allwinner - :ref:`introduction/detailed_support:Allwinner A10` (Cortex-A8) + - :ref:`introduction/detailed_support:Allwinner A64` (Cortex-A53) - Broadcom diff --git a/Documentation/platforms/arm/a64/boards/pinephone/index.rst b/Documentation/platforms/arm/a64/boards/pinephone/index.rst index fc3f3435cb7..78f052c3f49 100644 --- a/Documentation/platforms/arm/a64/boards/pinephone/index.rst +++ b/Documentation/platforms/arm/a64/boards/pinephone/index.rst @@ -113,6 +113,19 @@ To see the available commands in NuttShell: $ help +LEDs +==== + +The supported PinePhone LEDs are: + +===== ========= === +Index LED PIO +===== ========= === +LED1 Green LED PD18 +LED2 Red LED PD19 +LED3 Blue LED PD20 +===== ========= === + Configurations ============== @@ -132,5 +145,6 @@ NuttX for PinePhone supports these peripherals: =========== ======= ===== Peripheral Support NOTES =========== ======= ===== +PIO Yes UART Yes Only UART0 is supported =========== ======= ===== diff --git a/arch/arm64/src/a64/Make.defs b/arch/arm64/src/a64/Make.defs index 92a1daaaaa1..a82916b8e16 100644 --- a/arch/arm64/src/a64/Make.defs +++ b/arch/arm64/src/a64/Make.defs @@ -21,6 +21,6 @@ include common/Make.defs # Allwinner A64 specific C source files -CHIP_CSRCS = a64_boot.c a64_serial.c +CHIP_CSRCS = a64_boot.c a64_pio.c a64_serial.c CHIP_ASRCS = a64_lowputc.S diff --git a/arch/arm64/src/a64/a64_pio.c b/arch/arm64/src/a64/a64_pio.c new file mode 100644 index 00000000000..2630891d493 --- /dev/null +++ b/arch/arm64/src/a64/a64_pio.c @@ -0,0 +1,329 @@ +/**************************************************************************** + * arch/arm64/src/a64/a64_pio.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "arm64_internal.h" +#include "chip.h" +#include "a64_pio.h" +#include "hardware/a64_pio.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: a64_pio_pin + * + * Description: + * Return the Port Number for the bit-encoded description of the pin. + * + * Input Parameters: + * cfgset - Bit-encoded description of a pin + * + * Returned Value: + * Port Number (PIO_REG_PORTB to PIO_REG_PORTL) + * + ****************************************************************************/ + +static inline int a64_pio_port(pio_pinset_t cfgset) +{ + int port = (cfgset & PIO_PORT_MASK) >> PIO_PORT_SHIFT; + + DEBUGASSERT(port >= PIO_REG_PORTB && port <= PIO_REG_PORTL); + return port; +} + +/**************************************************************************** + * Name: a64_pio_pin + * + * Description: + * Return the Pin Number for the bit-encoded description of the pin. + * + * Input Parameters: + * cfgset - Bit-encoded description of a pin + * + * Returned Value: + * Pin Number (0 to 24) + * + ****************************************************************************/ + +static inline int a64_pio_pin(pio_pinset_t cfgset) +{ + int pin = (cfgset & PIO_PIN_MASK) >> PIO_PIN_SHIFT; + + DEBUGASSERT(pin >= 0 && pin <= 24); + return pin; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: a64_pio_config + * + * Description: + * Configure a PIO pin based on bit-encoded description of the pin. + * + * Input Parameters: + * cfgset - Bit-encoded description of a pin + * + * Returned Value: + * Zero (OK) on success; a negated errno value is returned on any failure. + * + ****************************************************************************/ + +int a64_pio_config(pio_pinset_t cfgset) +{ + unsigned int port = a64_pio_port(cfgset); + unsigned int pin = a64_pio_pin(cfgset); + unsigned int shift; + unsigned int value; + uintptr_t cfgaddr; + uintptr_t puaddr; + uintptr_t drvaddr; + uintptr_t intaddr; + uintptr_t dataddr; + uint32_t regval; + irqstate_t flags; + + /* Disable interrupts to prohibit re-entrance. */ + + flags = enter_critical_section(); + + /* Set the peripheral ID (0=input, 1=output) and interrupt mode */ + + switch (pin >> 3) + { + case 0: /* PIO 0-7 */ + cfgaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_CFG0 : + A64_PIO_CFG0(port); + intaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_INT_CFG0 : + A64_PIO_INT_CFG0; + break; + + case 1: /* PIO 8-15 */ + cfgaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_CFG1 : + A64_PIO_CFG1(port); + intaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_INT_CFG1 : + A64_PIO_INT_CFG1; + break; + + case 2: /* PIO 16-23 */ + cfgaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_CFG2 : + A64_PIO_CFG2(port); + intaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_INT_CFG2 : + A64_PIO_INT_CFG2; + break; + + case 3: /* PIO 24-31 */ + cfgaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_CFG3 : + A64_PIO_CFG3(port); + intaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_INT_CFG3 : + A64_PIO_INT_CFG3; + break; + + default: + leave_critical_section(flags); + return -EINVAL; + } + + value = (cfgset & PIO_MODE_MASK) >> PIO_MODE_SHIFT; + shift = (pin & 7) << 2; + + regval = getreg32(cfgaddr); + regval &= ~(7 << shift); + regval |= (value << shift); + putreg32(regval, cfgaddr); + + /* Do not modify the INT MASK unless this pin is configured + * as an external PIO interrupt. + */ + + if ((cfgset & PIO_EINT_MASK) == PIO_EINT) + { + value = (cfgset & PIO_INT_MASK) >> PIO_INT_SHIFT; + + regval = getreg32(intaddr); + regval &= ~(7 << shift); + regval |= (value << shift); + putreg32(regval, intaddr); + } + + /* Set the pull-up/down and drive strength */ + + switch (pin >> 4) + { + case 0: /* PIO 0-15 */ + puaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_PUL0 : + A64_PIO_PUL0(port); + drvaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_DRV0 : + A64_PIO_DRV0(port); + break; + + case 1: /* PIO 16-31 */ + puaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_PUL1 : + A64_PIO_PUL1(port); + drvaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_DRV1 : + A64_PIO_DRV1(port); + break; + + default: + leave_critical_section(flags); + return -EINVAL; + } + + value = (cfgset & PIO_PULL_MASK) >> PIO_PULL_SHIFT; + shift = (pin & 15) << 1; + + regval = getreg32(puaddr); + regval &= ~(3 << shift); + regval |= (value << shift); + putreg32(regval, puaddr); + + value = (cfgset & PIO_DRIVE_MASK) >> PIO_DRIVE_SHIFT; + + regval = getreg32(drvaddr); + regval &= ~(3 << shift); + regval |= (value << shift); + putreg32(regval, drvaddr); + + /* Set the output value (will have no effect on inputs) */ + + dataddr = (port == PIO_REG_PORTL) ? + A64_RPIO_DAT : + A64_PIO_DAT(port); + regval = getreg32(dataddr); + + if ((cfgset & PIO_OUTPUT_SET) != 0) + { + regval |= PIO_DAT(pin); + } + else + { + regval &= ~PIO_DAT(pin); + } + + putreg32(regval, dataddr); + + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: a64_piowrite + * + * Description: + * Write one or zero to the selected PIO pin. + * + * Input Parameters: + * pinset - PIO pin + * + * Returned Value: + * None + * + ****************************************************************************/ + +void a64_pio_write(pio_pinset_t pinset, bool value) +{ + unsigned int port = a64_pio_port(pinset); + unsigned int pin = a64_pio_pin(pinset); + irqstate_t flags; + uintptr_t regaddr; + uint32_t regval; + + /* Disable interrupts to prohibit re-entrance. */ + + flags = enter_critical_section(); + + /* Set the output value (will have no effect on inputs */ + + regaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_DAT : + A64_PIO_DAT(port); + regval = getreg32(regaddr); + + if (value) + { + regval |= PIO_DAT(pin); + } + else + { + regval &= ~PIO_DAT(pin); + } + + putreg32(regval, regaddr); + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: a64_pio_read + * + * Description: + * Read one or zero from the selected PIO pin + * + * Input Parameters: + * pinset - PIO pin + * + * Returned Value: + * Input value of PIO pin + * + ****************************************************************************/ + +bool a64_pio_read(pio_pinset_t pinset) +{ + unsigned int port = a64_pio_port(pinset); + unsigned int pin = a64_pio_pin(pinset); + uintptr_t regaddr; + uint32_t regval; + + /* Get the input value */ + + regaddr = (port == PIO_REG_PORTL) ? + A64_RPIO_DAT : + A64_PIO_DAT(port); + regval = getreg32(regaddr); + return ((regval & PIO_DAT(pin)) != 0); +} diff --git a/arch/arm64/src/a64/a64_pio.h b/arch/arm64/src/a64/a64_pio.h new file mode 100644 index 00000000000..1a4ff7f1cd2 --- /dev/null +++ b/arch/arm64/src/a64/a64_pio.h @@ -0,0 +1,287 @@ +/**************************************************************************** + * arch/arm64/src/a64/a64_pio.h + * + * 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_A64_A64_PIO_H +#define __ARCH_ARM64_SRC_A64_A64_PIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include "hardware/a64_pio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Bit-encoded input to a64_pio_config() ************************************/ + +/* 32-bit Encoding: + * + * 3322 2222 2222 1111 1111 11 + * 1098 7654 3210 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- ---- ---- ---- + * .... .... MMMM PPDD IIIV ...P PPPB BBBB + */ + +/* Input/Output mode: + * + * 3322 2222 2222 1111 1111 11 + * 1098 7654 3210 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- ---- ---- ---- + * .... .... MMMX .... .... .... .... .... + */ + +#define PIO_MODE_SHIFT (21) /* Bits 21-23: PIO mode */ +#define PIO_MODE_MASK (7 << PIO_MODE_SHIFT) +#define PIO_PERIPH0 (PIO_REG_CFG_INPUT << PIO_MODE_SHIFT) +#define PIO_PERIPH1 (PIO_REG_CFG_OUTPUT << PIO_MODE_SHIFT) +#define PIO_PERIPH2 (2 << PIO_MODE_SHIFT) +#define PIO_PERIPH3 (3 << PIO_MODE_SHIFT) +#define PIO_PERIPH4 (4 << PIO_MODE_SHIFT) +#define PIO_PERIPH5 (5 << PIO_MODE_SHIFT) +#define PIO_PERIPH6 (6 << PIO_MODE_SHIFT) +#define PIO_PERIPH7 (7 << PIO_MODE_SHIFT) + +#define PIO_INPUT PIO_PERIPH0 /* Input */ +#define PIO_OUTPUT PIO_PERIPH1 /* Output */ +#define PIO_PWM PIO_PERIPH2 /* PWM for PL10 */ + +/* Bit 20 also specifies an external interrupt which must go with ID=6 */ + +#define PIO_EINT_BIT (1 << 20) /* Bit 20: External PIO interrupt */ +#define PIO_EINT_SHIFT (20) /* Bits 20-23: Extended PIO mode */ +#define PIO_EINT_MASK (15 << PIO_EINT_SHIFT) +#define PIO_EINT (PIO_EINT_BIT | PIO_PERIPH6) + +/* These bits set the pull-up/down configuration of the pin: + * + * 3322 2222 2222 1111 1111 11 + * 1098 7654 3210 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- ---- ---- ---- + * .... .... .... PP.. .... .... .... .... + */ + +#define PIO_PULL_SHIFT (18) /* Bits 18-19: PIO configuration bits */ +#define PIO_PULL_MASK (3 << PIO_PULL_SHIFT) +#define PIO_PULL_NONE (PIO_REG_PULL_NONE << PIO_PULL_SHIFT) +#define PIO_PULL_PULLUP (PIO_REG_PULL_UP << PIO_PULL_SHIFT) +#define PIO_PULL_PULLDOWN (PIO_REG_PULL_DOWN << PIO_PULL_SHIFT) + +/* Drive (outputs only): + * + * 3322 2222 2222 1111 1111 11 + * 1098 7654 3210 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- ---- ---- ---- + * .... .... .... ..DD .... .... .... .... + */ + +#define PIO_DRIVE_SHIFT (16) /* Bits 16-17: Drive strength */ +#define PIO_DRIVE_MASK (3 << PIO_DRIVE_SHIFT) +#define PIO_DRIVE_NONE (0 << PIO_DRIVE_SHIFT) +#define PIO_DRIVE_LOW (PIO_REG_DRV_LEVEL0 << PIO_DRIVE_SHIFT) +#define PIO_DRIVE_MEDLOW (PIO_REG_DRV_LEVEL1 << PIO_DRIVE_SHIFT) +#define PIO_DRIVE_MEDHIGH (PIO_REG_DRV_LEVEL2 << PIO_DRIVE_SHIFT) +#define PIO_DRIVE_HIGH (PIO_REG_DRV_LEVEL3 << PIO_DRIVE_SHIFT) + +/* Interrupt modes (inputs only): + * + * 3322 2222 2222 1111 1111 11 + * 1098 7654 3210 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- ---- ---- ---- + * .... .... ... .... III. .... .... .... + */ + +#define PIO_INT_SHIFT (13) /* Bits 13-15: PIO interrupt bits */ +#define PIO_INT_MASK (7 << PIO_INT_SHIFT) +#define PIO_INT_NONE (0 << PIO_INT_SHIFT) +#define PIO_INT_RISING (PIO_REG_INT_POSEDGE << PIO_INT_SHIFT) +#define PIO_INT_FALLING (PIO_REG_INT_NEGEDGE << PIO_INT_SHIFT) +#define PIO_INT_HIGHLEVEL (PIO_REG_INT_HILEVEL << PIO_INT_SHIFT) +#define PIO_INT_LOWLEVEL (PIO_REG_INT_LOWLEVEL << PIO_INT_SHIFT) +#define PIO_INT_BOTHEDGES (PIO_REG_INT_BOTHEDGES << PIO_INT_SHIFT) + +/* If the pin is an PIO output, then this identifies the initial + * output value: + * + * 3322 2222 2222 1111 1111 11 + * 1098 7654 3210 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- ---- ---- ---- + * .... .... .... .... ...V .... .... .... + * V + */ + +#define PIO_OUTPUT_SET (1 << 12) /* Bit 12: Initial value of output */ +#define PIO_OUTPUT_CLEAR (0) + +/* This identifies the PIO port: + * + * 3322 2222 2222 1111 1111 11 + * 1098 7654 3210 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- ---- ---- ---- + * .... .... .... .... .... ...P PPP. .... + * PPPP + */ + +#define PIO_PORT_SHIFT (5) /* Bit 5-8: Port number */ +#define PIO_PORT_MASK (15 << PIO_PORT_SHIFT) +#define PIO_PORT_PIOB (PIO_REG_PORTB << PIO_PORT_SHIFT) +#define PIO_PORT_PIOC (PIO_REG_PORTC << PIO_PORT_SHIFT) +#define PIO_PORT_PIOD (PIO_REG_PORTD << PIO_PORT_SHIFT) +#define PIO_PORT_PIOE (PIO_REG_PORTE << PIO_PORT_SHIFT) +#define PIO_PORT_PIOF (PIO_REG_PORTF << PIO_PORT_SHIFT) +#define PIO_PORT_PIOG (PIO_REG_PORTG << PIO_PORT_SHIFT) +#define PIO_PORT_PIOH (PIO_REG_PORTH << PIO_PORT_SHIFT) +#define PIO_PORT_PIOL (PIO_REG_PORTL << PIO_PORT_SHIFT) + +/* This identifies the bit in the port: + * + * 3322 2222 2222 1111 1111 11 + * 1098 7654 3210 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- ---- ---- ---- + * .... .... .... .... .... .... ...B BBBB + */ + +#define PIO_PIN_SHIFT (0) /* Bits 0-4: PIO number: 0-31 */ +#define PIO_PIN_MASK (31 << PIO_PIN_SHIFT) +#define PIO_PIN0 (0 << PIO_PIN_SHIFT) +#define PIO_PIN1 (1 << PIO_PIN_SHIFT) +#define PIO_PIN2 (2 << PIO_PIN_SHIFT) +#define PIO_PIN3 (3 << PIO_PIN_SHIFT) +#define PIO_PIN4 (4 << PIO_PIN_SHIFT) +#define PIO_PIN5 (5 << PIO_PIN_SHIFT) +#define PIO_PIN6 (6 << PIO_PIN_SHIFT) +#define PIO_PIN7 (7 << PIO_PIN_SHIFT) +#define PIO_PIN8 (8 << PIO_PIN_SHIFT) +#define PIO_PIN9 (9 << PIO_PIN_SHIFT) +#define PIO_PIN10 (10 << PIO_PIN_SHIFT) +#define PIO_PIN11 (11 << PIO_PIN_SHIFT) +#define PIO_PIN12 (12 << PIO_PIN_SHIFT) +#define PIO_PIN13 (13 << PIO_PIN_SHIFT) +#define PIO_PIN14 (14 << PIO_PIN_SHIFT) +#define PIO_PIN15 (15 << PIO_PIN_SHIFT) +#define PIO_PIN16 (16 << PIO_PIN_SHIFT) +#define PIO_PIN17 (17 << PIO_PIN_SHIFT) +#define PIO_PIN18 (18 << PIO_PIN_SHIFT) +#define PIO_PIN19 (19 << PIO_PIN_SHIFT) +#define PIO_PIN20 (20 << PIO_PIN_SHIFT) +#define PIO_PIN21 (21 << PIO_PIN_SHIFT) +#define PIO_PIN22 (22 << PIO_PIN_SHIFT) +#define PIO_PIN23 (23 << PIO_PIN_SHIFT) +#define PIO_PIN24 (24 << PIO_PIN_SHIFT) +#define PIO_PIN25 (25 << PIO_PIN_SHIFT) +#define PIO_PIN26 (26 << PIO_PIN_SHIFT) +#define PIO_PIN27 (27 << PIO_PIN_SHIFT) +#define PIO_PIN28 (28 << PIO_PIN_SHIFT) +#define PIO_PIN29 (29 << PIO_PIN_SHIFT) +#define PIO_PIN30 (30 << PIO_PIN_SHIFT) +#define PIO_PIN31 (31 << PIO_PIN_SHIFT) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Must be big enough to hold the 32-bit encoding */ + +typedef uint32_t pio_pinset_t; + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: a64_pio_config + * + * Description: + * Configure a PIO pin based on bit-encoded description of the pin. + * + * Input Parameters: + * cfgset - Bit-encoded description of a pin + * + * Returned Value: + * Zero (OK) on success; a negated errno value is returned on any failure. + * + ****************************************************************************/ + +int a64_pio_config(pio_pinset_t cfgset); + +/**************************************************************************** + * Name: a64_piowrite + * + * Description: + * Write one or zero to the selected PIO pin. + * + * Input Parameters: + * pinset - PIO pin + * + * Returned Value: + * None + * + ****************************************************************************/ + +void a64_pio_write(pio_pinset_t pinset, bool value); + +/**************************************************************************** + * Name: a64_pio_read + * + * Description: + * Read one or zero from the selected PIO pin + * + * Input Parameters: + * pinset - PIO pin + * + * Returned Value: + * Input value of PIO pin + * + ****************************************************************************/ + +bool a64_pio_read(pio_pinset_t pinset); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM64_SRC_A64_A64_PIO_H */ diff --git a/arch/arm64/src/a64/hardware/a64_memorymap.h b/arch/arm64/src/a64/hardware/a64_memorymap.h new file mode 100644 index 00000000000..72d012935af --- /dev/null +++ b/arch/arm64/src/a64/hardware/a64_memorymap.h @@ -0,0 +1,51 @@ +/**************************************************************************** + * arch/arm64/src/a64/hardware/a64_memorymap.h + * + * 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_A64_HARDWARE_A64_MEMORYMAP_H +#define __ARCH_ARM64_SRC_A64_HARDWARE_A64_MEMORYMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Peripheral Base Addresses */ + +#define A64_PIO_ADDR 0x01c20800 /* PIO 0x01c2:0800-0x01c2:0bff 1K */ +#define A64_RPIO_ADDR 0x01f02c00 /* R_PIO 0x01f0:2c00-0x01f0:2fff 1K */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +#endif /* __ARCH_ARM64_SRC_A64_HARDWARE_A64_MEMORYMAP_H */ diff --git a/arch/arm64/src/a64/hardware/a64_pio.h b/arch/arm64/src/a64/hardware/a64_pio.h new file mode 100644 index 00000000000..21260129328 --- /dev/null +++ b/arch/arm64/src/a64/hardware/a64_pio.h @@ -0,0 +1,210 @@ +/**************************************************************************** + * arch/arm64/src/a64/hardware/a64_pio.h + * + * 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_A64_HARDWARE_A64_PIO_H +#define __ARCH_ARM64_SRC_A64_HARDWARE_A64_PIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/a64_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define PIO_REG_PORTB 1 +#define PIO_REG_PORTC 2 +#define PIO_REG_PORTD 3 +#define PIO_REG_PORTE 4 +#define PIO_REG_PORTF 5 +#define PIO_REG_PORTG 6 +#define PIO_REG_PORTH 7 +#define PIO_REG_PORTL 8 + +#define PIO_REG_CFG_INPUT 0 +#define PIO_REG_CFG_OUTPUT 1 + +#define PIO_REG_DRV_LEVEL0 0 +#define PIO_REG_DRV_LEVEL1 1 +#define PIO_REG_DRV_LEVEL2 2 +#define PIO_REG_DRV_LEVEL3 3 + +#define PIO_REG_PULL_NONE 0 +#define PIO_REG_PULL_UP 1 +#define PIO_REG_PULL_DOWN 2 + +#define PIO_REG_INT_POSEDGE 0 +#define PIO_REG_INT_NEGEDGE 1 +#define PIO_REG_INT_HILEVEL 2 +#define PIO_REG_INT_LOWLEVEL 3 +#define PIO_REG_INT_BOTHEDGES 4 + +/* Register Offsets *********************************************************/ + +#define A64_PIO_CFG0_OFFSET(n) (0x0000 + (n)*0x24) /* Port Configure Register 0, n=0-7 */ +#define A64_PIO_CFG1_OFFSET(n) (0x0004 + (n)*0x24) /* Port Configure Register 1, n=0-7 */ +#define A64_PIO_CFG2_OFFSET(n) (0x0008 + (n)*0x24) /* Port Configure Register 2, n=0-7 */ +#define A64_PIO_CFG3_OFFSET(n) (0x000c + (n)*0x24) /* Port Configure Register 3, n=0-7 */ +#define A64_PIO_DAT_OFFSET(n) (0x0010 + (n)*0x24) /* Port Data Register, n=0-7 */ +#define A64_PIO_DRV0_OFFSET(n) (0x0014 + (n)*0x24) /* Port Multi-Driving Register 0, n=0-7 */ +#define A64_PIO_DRV1_OFFSET(n) (0x0018 + (n)*0x24) /* Port Multi-Driving Register 1, n=0-7 */ +#define A64_PIO_PUL0_OFFSET(n) (0x001c + (n)*0x24) /* Port Pull Register 0, n=0-7 */ +#define A64_PIO_PUL1_OFFSET(n) (0x0020 + (n)*0x24) /* Port Pull Register 1, n=0-7 */ +#define A64_PIO_INT_CFG0_OFFSET 0x0200 /* PIO Interrupt Configure Register 0 */ +#define A64_PIO_INT_CFG1_OFFSET 0x0204 /* PIO Interrupt Configure Register 1 */ +#define A64_PIO_INT_CFG2_OFFSET 0x0208 /* PIO Interrupt Configure Register 2 */ +#define A64_PIO_INT_CFG3_OFFSET 0x020c /* PIO Interrupt Configure Register 3 */ +#define A64_PIO_INT_CTL_OFFSET 0x0210 /* PIO Interrupt Control Register */ +#define A64_PIO_INT_STA_OFFSET 0x0214 /* PIO Interrupt Status Register */ +#define A64_PIO_INT_DEB_OFFSET 0x0218 /* PIO Interrupt Debounce Register */ + +/* Register Addresses *******************************************************/ + +#define A64_PIO_CFG0(n) (A64_PIO_ADDR+A64_PIO_CFG0_OFFSET(n)) +#define A64_PIO_CFG1(n) (A64_PIO_ADDR+A64_PIO_CFG1_OFFSET(n)) +#define A64_PIO_CFG2(n) (A64_PIO_ADDR+A64_PIO_CFG2_OFFSET(n)) +#define A64_PIO_CFG3(n) (A64_PIO_ADDR+A64_PIO_CFG3_OFFSET(n)) +#define A64_PIO_DAT(n) (A64_PIO_ADDR+A64_PIO_DAT_OFFSET(n)) +#define A64_PIO_DRV0(n) (A64_PIO_ADDR+A64_PIO_DRV0_OFFSET(n)) +#define A64_PIO_DRV1(n) (A64_PIO_ADDR+A64_PIO_DRV1_OFFSET(n)) +#define A64_PIO_PUL0(n) (A64_PIO_ADDR+A64_PIO_PUL0_OFFSET(n)) +#define A64_PIO_PUL1(n) (A64_PIO_ADDR+A64_PIO_PUL1_OFFSET(n)) +#define A64_PIO_INT_CFG0 (A64_PIO_ADDR+A64_PIO_INT_CFG0_OFFSET) +#define A64_PIO_INT_CFG1 (A64_PIO_ADDR+A64_PIO_INT_CFG1_OFFSET) +#define A64_PIO_INT_CFG2 (A64_PIO_ADDR+A64_PIO_INT_CFG2_OFFSET) +#define A64_PIO_INT_CFG3 (A64_PIO_ADDR+A64_PIO_INT_CFG3_OFFSET) +#define A64_PIO_INT_CTL (A64_PIO_ADDR+A64_PIO_INT_CTL_OFFSET) +#define A64_PIO_INT_STA (A64_PIO_ADDR+A64_PIO_INT_STA_OFFSET) +#define A64_PIO_INT_DEB (A64_PIO_ADDR+A64_PIO_INT_DEB_OFFSET) + +#define A64_RPIO_CFG0 (A64_RPIO_ADDR+A64_PIO_CFG0_OFFSET(0)) +#define A64_RPIO_CFG1 (A64_RPIO_ADDR+A64_PIO_CFG1_OFFSET(0)) +#define A64_RPIO_CFG2 (A64_RPIO_ADDR+A64_PIO_CFG2_OFFSET(0)) +#define A64_RPIO_CFG3 (A64_RPIO_ADDR+A64_PIO_CFG3_OFFSET(0)) +#define A64_RPIO_DAT (A64_RPIO_ADDR+A64_PIO_DAT_OFFSET(0)) +#define A64_RPIO_DRV0 (A64_RPIO_ADDR+A64_PIO_DRV0_OFFSET(0)) +#define A64_RPIO_DRV1 (A64_RPIO_ADDR+A64_PIO_DRV1_OFFSET(0)) +#define A64_RPIO_PUL0 (A64_RPIO_ADDR+A64_PIO_PUL0_OFFSET(0)) +#define A64_RPIO_PUL1 (A64_RPIO_ADDR+A64_PIO_PUL1_OFFSET(0)) +#define A64_RPIO_INT_CFG0 (A64_RPIO_ADDR+A64_PIO_INT_CFG0_OFFSET) +#define A64_RPIO_INT_CFG1 (A64_RPIO_ADDR+A64_PIO_INT_CFG1_OFFSET) +#define A64_RPIO_INT_CFG2 (A64_RPIO_ADDR+A64_PIO_INT_CFG2_OFFSET) +#define A64_RPIO_INT_CFG3 (A64_RPIO_ADDR+A64_PIO_INT_CFG3_OFFSET) +#define A64_RPIO_INT_CTL (A64_RPIO_ADDR+A64_PIO_INT_CTL_OFFSET) +#define A64_RPIO_INT_STA (A64_RPIO_ADDR+A64_PIO_INT_STA_OFFSET) +#define A64_RPIO_INT_DEB (A64_RPIO_ADDR+A64_PIO_INT_DEB_OFFSET) + +/* Register Bit Field Definitions *******************************************/ + +/* Port Configure Register 0, n=0-7 */ + +#define PIO_CFG0_SHIFT(n) ((n) << 2) +#define PIO_CFG0_MASK(n)) (7 << PIO_CFG0_SHIFT(n)) +#define PIO_CFG0(m,v) ((uint32_t)(v) << PIO_CFG0_SHIFT(n)) + +/* Port Configure Register 1, n=8-15 */ + +#define PIO_CFG1_SHIFT(n) (((n) - 8) << 2) +#define PIO_CFG1_MASK(n)) (7 << PIO_CFG1_SHIFT(n)) +#define PIO_CFG1(m,v) ((uint32_t)(v) << PIO_CFG1_SHIFT(n)) + +/* Port Configure Register 2, n=16-23 */ + +#define PIO_CFG2_SHIFT(n) (((n) - 16) << 2) +#define PIO_CFG2_MASK(n)) (7 << PIO_CFG2_SHIFT(n)) +#define PIO_CFG2(m,v) ((uint32_t)(v) << PIO_CFG2_SHIFT(n)) + +/* Port Configure Register 3, n=24-31 */ + +#define PIO_CFG3_SHIFT(n) (((n) - 24) << 2) +#define PIO_CFG3_MASK(n)) (7 << PIO_CFG3_SHIFT(n)) +#define PIO_CFG3(m,v) ((uint32_t)(v) << PIO_CFG3_SHIFT(n)) + +/* Port n Data Register, n=0-31 */ + +#define PIO_DAT(n) (1 << (n)) /* PA data, n=0-31 */ + +/* Port n Multi-Driving Register 0, n=1-7 */ + +#define PIO_DRV0_SHIFT(n) ((n) << 1) /* PA DRV0, n=0-15 */ +#define PIO_DRV0_MASK(n) (3 << PIO_DRV0_SHIFT(n)) +#define PIO_DRV0(n,v) ((uint32_t)(v) << PIO_DRV0_SHIFT(n)) + +/* Port n Multi-Driving Register 1, n=1-7 */ + +#define PIO_DRV1_SHIFT(n) (((n) - 16) << 1) /* PA DRV1, n=16-31 */ +#define PIO_DRV1_MASK(n) (3 << PIO_DRV1_SHIFT(n)) +#define PIO_DRV1(n,v) ((uint32_t)(v) << PIO_DRV1_SHIFT(n)) + +/* Port n Pull Register 0, n=1-7 */ + +#define PIO_PUL0_SHIFT(n) ((n) << 1) /* PA PUL0, n=0-15 */ +#define PIO_PUL0_MASK(n) (3 << PIO_PUL0_SHIFT(n)) +#define PIO_PUL0(n,v) ((uint32_t)(v) << PIO_PUL0_SHIFT(n)) + +/* Port n Pull Register 1, n=1-7 */ + +#define PIO_PUL1_SHIFT(n) (((n) - 16) << 1) /* PA PUL1, n=16-31 */ +#define PIO_PUL1_MASK(n) (3 << PIO_PUL1_SHIFT(n)) +#define PIO_PUL1(n,v) ((uint32_t)(v) << PIO_PUL1_SHIFT(n)) + +/* PIO Interrupt Configure Register 0 */ + +#define PIO_INT_CFG0_SHIFT(n) ((n) << 2) +#define PIO_INT_CFG0_MASK(n)) (15 << PIO_INT_CFG0_SHIFT(n)) +#define PIO_INT_CFG0(m,v) ((uint32_t)(v) << PIO_INT_CFG0_SHIFT(n)) + +/* PIO Interrupt Configure Register 1 */ + +#define PIO_INT_CFG1_SHIFT(n) (((n) - 8) << 2) +#define PIO_INT_CFG1_MASK(n)) (15 << PIO_INT_CFG1_SHIFT(n)) +#define PIO_INT_CFG1(m,v) ((uint32_t)(v) << PIO_INT_CFG1_SHIFT(n)) + +/* PIO Interrupt Configure Register 2 */ + +#define PIO_INT_CFG2_SHIFT(n) (((n) - 16) << 2) +#define PIO_INT_CFG2_MASK(n)) (15 << PIO_INT_CFG2_SHIFT(n)) +#define PIO_INT_CFG2(m,v) ((uint32_t)(v) << PIO_INT_CFG2_SHIFT(n)) + +/* PIO Interrupt Configure Register 3 */ + +#define PIO_INT_CFG3_SHIFT(n) (((n) - 24) << 2) +#define PIO_INT_CFG3_MASK(n)) (15 << PIO_INT_CFG3_SHIFT(n)) +#define PIO_INT_CFG3(m,v) ((uint32_t)(v) << PIO_INT_CFG3_SHIFT(n)) + +/* PIO Interrupt Control Register */ + +#define PIO_INT_CTL(n) (1 << (n)) + +/* PIO Interrupt Status Register */ + +#define PIO_INT_STA(n) (1 << (n)) + +/* PIO Interrupt Debounce Register */ + +#define PIO_INT_DEB_CLKSEL (1 << 0) /* Bit 0: PIO Interrupt Clock Select */ +#define PIO_INT_DEB_CLKPRESC_SHIFT (4) /* Bit 4-6: Debounce Clock Pre-scale */ +#define PIO_INT_DEB_CLKPRESC_MASK (7 << PIO_INT_DEB_CLKPRESC_SHIFT) +#define PIO_INT_DEB_CLKPRESC(n) ((uint32_t)(n) << PIO_INT_DEB_CLKPRESC_SHIFT) + +#endif /* __ARCH_ARM64_SRC_A64_HARDWARE_A64_PIO_H */ diff --git a/boards/Kconfig b/boards/Kconfig index b3accc91e85..b4207505fcc 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -1763,6 +1763,7 @@ config ARCH_BOARD_QEMU_ARMV8A config ARCH_BOARD_PINEPHONE bool "PINE64 PinePhone" depends on ARCH_CHIP_A64 + select ARCH_HAVE_LEDS select ARCH_HAVE_IRQBUTTONS ---help--- This options selects support for NuttX on PINE64 PinePhone based diff --git a/boards/arm64/a64/pinephone/configs/nsh/defconfig b/boards/arm64/a64/pinephone/configs/nsh/defconfig index 14d5c206e45..dded83c2098 100644 --- a/boards/arm64/a64/pinephone/configs/nsh/defconfig +++ b/boards/arm64/a64/pinephone/configs/nsh/defconfig @@ -28,6 +28,7 @@ CONFIG_DEBUG_WARN=y CONFIG_DEFAULT_TASK_STACKSIZE=8192 CONFIG_DEV_ZERO=y CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_LEDS=y CONFIG_EXPERIMENTAL=y CONFIG_FS_PROCFS=y CONFIG_FS_ROMFS=y @@ -62,3 +63,5 @@ CONFIG_TESTING_GETPRIME=y CONFIG_TESTING_OSTEST=y CONFIG_UART1_SERIAL_CONSOLE=y CONFIG_USEC_PER_TICK=1000 +CONFIG_USERLED=y +CONFIG_USERLED_LOWER=y diff --git a/boards/arm64/a64/pinephone/include/board.h b/boards/arm64/a64/pinephone/include/board.h new file mode 100644 index 00000000000..7716e44d1bb --- /dev/null +++ b/boards/arm64/a64/pinephone/include/board.h @@ -0,0 +1,71 @@ +/**************************************************************************** + * boards/arm64/a64/pinephone/include/board.h + * + * 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 __BOARDS_ARM64_A64_PINEPHONE_INCLUDE_BOARD_H +#define __BOARDS_ARM64_A64_PINEPHONE_INCLUDE_BOARD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* LED definitions **********************************************************/ + +/* LED index values for use with board_userled() */ + +typedef enum +{ + BOARD_LED1 = 0, /* Green LED */ + BOARD_LED2 = 1, /* Red LED */ + BOARD_LED3 = 2, /* Blue LED */ + BOARD_LEDS /* Number of LEDs */ +} led_typedef_enum; + +/* LED bits for use with board_userled_all() */ + +#define BOARD_LED1_BIT (1 << BOARD_LED1) +#define BOARD_LED2_BIT (1 << BOARD_LED2) +#define BOARD_LED3_BIT (1 << BOARD_LED3) + +/* If CONFIG_ARCH_LEDS is defined, the usage by the board port is defined in + * include/board.h and src/pinephone_autoleds.c. The LEDs are used to encode + * OS-related events as follows: + * + * SYMBOL Meaning LED state + * LED1 LED2 LED3 + * ---------------------- -------------------------- ------ ------ --- + */ + +#define LED_STARTED 0 /* NuttX has been started OFF OFF OFF */ +#define LED_HEAPALLOCATE 1 /* Heap has been allocated ON OFF OFF */ +#define LED_IRQSENABLED 2 /* Interrupts enabled OFF ON OFF */ +#define LED_STACKCREATED 3 /* Idle stack created OFF OFF ON */ +#define LED_INIRQ 4 /* In an interrupt ON ON OFF */ +#define LED_SIGNAL 5 /* In a signal handler ON OFF ON */ +#define LED_ASSERTION 6 /* An assertion failed OFF ON ON */ +#define LED_PANIC 7 /* The system has crashed FLASH ON ON */ +#define LED_IDLE 8 /* MCU is is sleep mode OFF FLASH OFF */ + +#endif /* __BOARDS_ARM64_A64_PINEPHONE_INCLUDE_BOARD_H */ diff --git a/boards/arm64/a64/pinephone/src/Makefile b/boards/arm64/a64/pinephone/src/Makefile index 7a06b9d61a5..fc32f89bffd 100644 --- a/boards/arm64/a64/pinephone/src/Makefile +++ b/boards/arm64/a64/pinephone/src/Makefile @@ -26,4 +26,12 @@ ifeq ($(CONFIG_BOARDCTL),y) CSRCS += pinephone_appinit.c endif +ifeq ($(CONFIG_ARCH_LEDS),y) +CSRCS += pinephone_autoleds.c +endif + +ifeq ($(CONFIG_USERLED),y) +CSRCS += pinephone_userleds.c +endif + include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm64/a64/pinephone/src/pinephone.h b/boards/arm64/a64/pinephone/src/pinephone.h index 5169eec217e..6c7625cbe86 100644 --- a/boards/arm64/a64/pinephone/src/pinephone.h +++ b/boards/arm64/a64/pinephone/src/pinephone.h @@ -27,6 +27,33 @@ #include #include +#include "a64_pio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* LEDs *********************************************************************/ + +/* Green LED on PD18 */ + +#define LED1 (PIO_OUTPUT | PIO_PULL_NONE | \ + PIO_DRIVE_MEDLOW | PIO_INT_NONE | \ + PIO_OUTPUT_SET | PIO_PORT_PIOD | PIO_PIN18) + +/* Red LED on PD19 */ + +#define LED2 (PIO_OUTPUT | PIO_PULL_NONE | \ + PIO_DRIVE_MEDLOW | PIO_INT_NONE | \ + PIO_OUTPUT_SET | PIO_PORT_PIOD | PIO_PIN19) + +/* Blue LED on PD20 */ + +#define LED3 (PIO_OUTPUT | PIO_PULL_NONE | \ + PIO_DRIVE_MEDLOW | PIO_INT_NONE | \ + PIO_OUTPUT_SET | PIO_PORT_PIOD | PIO_PIN20) #ifndef __ASSEMBLY__ @@ -46,5 +73,17 @@ int pinephone_bringup(void); #endif +/**************************************************************************** + * Name: pinephone_led_initialize + * + * Description: + * Configure LEDs. LEDs are left in the OFF state. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_LEDS +void pinephone_led_initialize(void); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __BOARDS_ARM64_A64_PINEPHONE_SRC_PINEPHONE_H */ diff --git a/boards/arm64/a64/pinephone/src/pinephone_autoleds.c b/boards/arm64/a64/pinephone/src/pinephone_autoleds.c new file mode 100644 index 00000000000..1bce21a6002 --- /dev/null +++ b/boards/arm64/a64/pinephone/src/pinephone_autoleds.c @@ -0,0 +1,257 @@ +/**************************************************************************** + * boards/arm64/a64/pinephone/src/pinephone_autoleds.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "chip.h" +#include "arm64_internal.h" +#include "pinephone.h" + +#ifdef CONFIG_ARCH_LEDS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0])) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* LED index */ + +static const uint32_t g_led_map[BOARD_LEDS] = +{ + LED1, + LED2, + LED3 +}; + +static bool g_initialized; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Turn on selected led */ + +static void pinephone_led_on(led_typedef_enum led_num) +{ + a64_pio_write(g_led_map[led_num], true); +} + +/* Turn off selected led */ + +static void pinephone_led_off(led_typedef_enum led_num) +{ + a64_pio_write(g_led_map[led_num], false); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_autoled_initialize + * + * Description: + * This function is called very early in initialization to perform board- + * specific initialization of LED-related resources. This includes such + * things as, for example, configure GPIO pins to drive the LEDs and also + * putting the LEDs in their correct initial state. + * + * NOTE: In most architectures, board_autoled_initialize() is called from + * board-specific initialization logic. But there are a few architectures + * where this initialization function is still called from common chip + * architecture logic. This interface is not, however, a common board + * interface in any event and, hence, the usage of the name + * board_autoled_initialize is deprecated. + * + * WARNING: This interface name will eventually be removed; do not use it + * in new board ports. New implementations should use the naming + * conventions for "Microprocessor-Specific Interfaces" or the "Board- + * Specific Interfaces" as described above. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_autoled_initialize(void) +{ + int i; + int ret; + + /* Configure the LED GPIO for output. */ + + for (i = 0; i < ARRAYSIZE(g_led_map); i++) + { + ret = a64_pio_config(g_led_map[i]); + DEBUGASSERT(ret == OK); + } +} + +/**************************************************************************** + * Name: board_autoled_on + * + * Description: + * Set the LED configuration into the ON condition for the state provided + * by the led parameter. This may be one of: + * + * LED_STARTED NuttX has been started + * LED_HEAPALLOCATE Heap has been allocated + * LED_IRQSENABLED Interrupts enabled + * LED_STACKCREATED Idle stack created + * LED_INIRQ In an interrupt + * LED_SIGNAL In a signal handler + * LED_ASSERTION An assertion failed + * LED_PANIC The system has crashed + * LED_IDLE MCU is in sleep mode + * + * Where these values are defined in a board-specific way in the standard + * board.h header file exported by every architecture. + * + * Input Parameters: + * led - Identifies the LED state to put in the ON state (which may or may + * not equate to turning an LED on) + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_autoled_on(int led) +{ + switch (led) + { + case LED_HEAPALLOCATE: + pinephone_led_on(BOARD_LED1); + break; + + case LED_IRQSENABLED: + pinephone_led_on(BOARD_LED2); + break; + + case LED_STACKCREATED: + pinephone_led_on(BOARD_LED3); + g_initialized = true; + break; + + case LED_INIRQ: + pinephone_led_on(BOARD_LED1); + pinephone_led_on(BOARD_LED2); + break; + + case LED_SIGNAL: + pinephone_led_on(BOARD_LED1); + pinephone_led_on(BOARD_LED3); + break; + + case LED_ASSERTION: + pinephone_led_on(BOARD_LED2); + pinephone_led_on(BOARD_LED3); + break; + + case LED_PANIC: + pinephone_led_on(BOARD_LED1); + break; + + case LED_IDLE: + pinephone_led_on(BOARD_LED2); + break; + + default: + break; + } +} + +/**************************************************************************** + * Name: board_autoled_off + * + * Description: + * Set the LED configuration into the OFF condition for the state provided + * by the led parameter. This may be one of: + * + * LED_INIRQ Leaving an interrupt + * LED_SIGNAL Leaving a signal handler + * LED_ASSERTION Recovering from an assertion failure + * LED_PANIC The system has crashed (blinking). + * LED_IDLE MCU is not in sleep mode + * + * Where these values are defined in a board-specific way in the standard + * board.h header file exported by every architecture. + * + * Input Parameters: + * led - Identifies the LED state to put in the OFF state (which may or may + * not equate to turning an LED off) + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_autoled_off(int led) +{ + switch (led) + { + case LED_SIGNAL: + pinephone_led_off(BOARD_LED1); + pinephone_led_off(BOARD_LED3); + break; + + case LED_INIRQ: + pinephone_led_off(BOARD_LED1); + pinephone_led_off(BOARD_LED2); + break; + + case LED_ASSERTION: + pinephone_led_off(BOARD_LED2); + pinephone_led_off(BOARD_LED3); + break; + + case LED_PANIC: + pinephone_led_off(BOARD_LED1); + break; + + case LED_IDLE: + pinephone_led_off(BOARD_LED2); + break; + + default: + break; + } +} + +#endif /* CONFIG_ARCH_LEDS */ diff --git a/boards/arm64/a64/pinephone/src/pinephone_boardinit.c b/boards/arm64/a64/pinephone/src/pinephone_boardinit.c index 31945f12cd0..2b3c20a8278 100644 --- a/boards/arm64/a64/pinephone/src/pinephone_boardinit.c +++ b/boards/arm64/a64/pinephone/src/pinephone_boardinit.c @@ -79,6 +79,7 @@ void a64_board_initialize(void) #ifdef CONFIG_ARCH_LEDS /* Configure on-board LEDs if LED support has been selected. */ + board_autoled_initialize(); #endif } diff --git a/boards/arm64/a64/pinephone/src/pinephone_bringup.c b/boards/arm64/a64/pinephone/src/pinephone_bringup.c index fb79b626ad8..1b9f2e125a8 100644 --- a/boards/arm64/a64/pinephone/src/pinephone_bringup.c +++ b/boards/arm64/a64/pinephone/src/pinephone_bringup.c @@ -25,7 +25,15 @@ #include #include #include -#include + +#ifdef CONFIG_FS_PROCFS +# include +#endif + +#ifdef CONFIG_USERLED +# include +#endif + #include "pinephone.h" /**************************************************************************** @@ -44,6 +52,16 @@ int pinephone_bringup(void) { int ret; +#ifdef CONFIG_USERLED + /* Register the LED driver */ + + ret = userled_lower_initialize("/dev/userleds"); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: userled_lower_initialize() failed: %d\n", ret); + } +#endif + #ifdef CONFIG_FS_PROCFS /* Mount the procfs file system */ diff --git a/boards/arm64/a64/pinephone/src/pinephone_userleds.c b/boards/arm64/a64/pinephone/src/pinephone_userleds.c new file mode 100644 index 00000000000..87fdd1dc9e5 --- /dev/null +++ b/boards/arm64/a64/pinephone/src/pinephone_userleds.c @@ -0,0 +1,191 @@ +/**************************************************************************** + * boards/arm64/a64/pinephone/src/pinephone_userleds.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "chip.h" +#include "arm64_internal.h" +#include "pinephone.h" + +#ifdef CONFIG_USERLED + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0])) + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* LED index */ + +static const uint32_t g_led_map[BOARD_LEDS] = +{ + LED1, + LED2, + LED3 +}; + +static const uint32_t g_led_setmap[BOARD_LEDS] = +{ + BOARD_LED1_BIT, + BOARD_LED2_BIT, + BOARD_LED3_BIT +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_userled_initialize + * + * Description: + * This function may called from application-specific logic during its + * to perform board-specific initialization of LED resources. This + * includes such things as, for example, configure GPIO pins to drive the + * LEDs and also putting the LEDs in their correct initial state. + * + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then this interfaces may be + * available to control the LEDs directly from user board logic or + * indirectly user applications (via the common LED character driver). + * + * Most boards have only a few LEDs and in those cases all LEDs may be + * used by the NuttX LED logic exclusively and may not be available for + * use by user logic if CONFIG_ARCH_LEDS=y. + * + * NOTE: The LED number is returned. + * + * Input Parameters: + * None + * + * Returned Value: + * Number of LEDs on board + * + ****************************************************************************/ + +uint32_t board_userled_initialize(void) +{ + int i; + int ret; + + /* Configure the LED GPIO for output. */ + + for (i = 0; i < ARRAYSIZE(g_led_map); i++) + { + ret = a64_pio_config(g_led_map[i]); + DEBUGASSERT(ret == OK); + } + + return BOARD_LEDS; +} + +/**************************************************************************** + * Name: board_userled + * + * Description: + * This interface may be used by application specific logic to set the + * state of a single LED. Definitions for the led identification are + * provided in the board-specific board.h header file that may be included + * like: + * + * #included + * + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then this interfaces may be + * available to control the LEDs directly from user board logic or + * indirectly user applications (via the common LED character driver). + * + * Most boards have only a few LEDs and in those cases all LEDs may be + * used by the NuttX LED logic exclusively and may not be available for + * use by user logic if CONFIG_ARCH_LEDS=y. + * + * Input Parameters: + * led - LED number + * ledon - True if LED should be turned on; False to turn off + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_userled(int led, bool ledon) +{ + if ((unsigned)led < ARRAYSIZE(g_led_map)) + { + a64_pio_write(g_led_map[led], ledon); + } +} + +/**************************************************************************** + * Name: board_userled_all + * + * Description: + * This interface may be used by application specific logic to set the + * state of all board LED. Definitions for the led set member + * identification is provided in the board-specific board.h header file + * that may be includedlike: + * + * #included + * + * If CONFIG_ARCH_LEDS is defined, then NuttX will control the on-board + * LEDs. If CONFIG_ARCH_LEDS is not defined, then this interfaces may be + * available to control the LEDs directly from user board logic or + * indirectly user applications (via the common LED character driver). + * + * Most boards have only a few LEDs and in those cases all LEDs may be + * used by the NuttX LED logic exclusively and may not be available for + * use by user logic if CONFIG_ARCH_LEDS=y. + * + * Input Parameters: + * ledset - Bitset of LEDs to be turned on and off + * + * Returned Value: + * None + * + ****************************************************************************/ + +void board_userled_all(uint32_t ledset) +{ + int i; + + /* Configure LED1-3 GPIOs for output */ + + for (i = 0; i < ARRAYSIZE(g_led_map); i++) + { + a64_pio_write(g_led_map[i], (ledset & g_led_setmap[i]) != 0); + } +} + +#endif /* CONFIG_USERLED */