summaryrefslogtreecommitdiffstats
path: root/bsps/shared/dev
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/shared/dev')
-rw-r--r--bsps/shared/dev/btimer/btimer-cpucounter.c27
-rw-r--r--bsps/shared/dev/clock/arm-generic-timer.c46
-rw-r--r--bsps/shared/dev/clock/bcm2835-system-timer.c94
-rw-r--r--bsps/shared/dev/clock/clockimpl.h102
-rw-r--r--bsps/shared/dev/clock/xil-ttc.c214
-rw-r--r--bsps/shared/dev/cpucounter/cpucounterfrequency.c27
-rw-r--r--bsps/shared/dev/cpucounter/cpucounterread.c27
-rw-r--r--bsps/shared/dev/display/disp_fonts.h27
-rw-r--r--bsps/shared/dev/display/disp_hcms29xx.c27
-rw-r--r--bsps/shared/dev/display/font_hcms29xx.c27
-rw-r--r--bsps/shared/dev/display/font_hcms29xx.h27
-rw-r--r--bsps/shared/dev/dma/fsl-edma.c4
-rw-r--r--bsps/shared/dev/getentropy/getentropy-cpucounter.c27
-rw-r--r--bsps/shared/dev/i2c/cadence-i2c.c3
-rw-r--r--bsps/shared/dev/i2c/i2c-sc620.c27
-rw-r--r--bsps/shared/dev/i2c/spi-flash-m25p40.c27
-rw-r--r--bsps/shared/dev/i2c/spi-fram-fm25l256.c27
-rw-r--r--bsps/shared/dev/i2c/spi-memdrv.c27
-rw-r--r--bsps/shared/dev/i2c/spi-sd-card.c27
-rw-r--r--bsps/shared/dev/ide/ata_util.c2
-rw-r--r--bsps/shared/dev/irq/arm-gicv2-get-attributes.c7
-rw-r--r--bsps/shared/dev/irq/arm-gicv2-zynqmp.c6
-rw-r--r--bsps/shared/dev/irq/arm-gicv2.c67
-rw-r--r--bsps/shared/dev/irq/arm-gicv3.c35
-rw-r--r--bsps/shared/dev/nand/VERSION24
-rw-r--r--bsps/shared/dev/nand/xnandpsu.c3027
-rw-r--r--bsps/shared/dev/nand/xnandpsu_bbm.c1001
-rw-r--r--bsps/shared/dev/nand/xnandpsu_onfi.c91
-rw-r--r--bsps/shared/dev/rtc/icm7170.c25
-rw-r--r--bsps/shared/dev/rtc/icm7170_reg.c25
-rw-r--r--bsps/shared/dev/rtc/icm7170_reg2.c25
-rw-r--r--bsps/shared/dev/rtc/icm7170_reg4.c25
-rw-r--r--bsps/shared/dev/rtc/icm7170_reg8.c25
-rw-r--r--bsps/shared/dev/rtc/m48t08.c25
-rw-r--r--bsps/shared/dev/rtc/m48t08_reg.c25
-rw-r--r--bsps/shared/dev/rtc/m48t08_reg2.c25
-rw-r--r--bsps/shared/dev/rtc/m48t08_reg4.c25
-rw-r--r--bsps/shared/dev/rtc/m48t08_reg8.c25
-rw-r--r--bsps/shared/dev/rtc/mc146818a.c25
-rw-r--r--bsps/shared/dev/rtc/mc146818a_ioreg.c25
-rw-r--r--bsps/shared/dev/rtc/mcp7940m.c361
-rw-r--r--bsps/shared/dev/rtc/rtcprobe.c25
-rw-r--r--bsps/shared/dev/serial/arm-pl011.c27
-rw-r--r--bsps/shared/dev/serial/console-output-char.c27
-rw-r--r--bsps/shared/dev/serial/console-polled.c27
-rw-r--r--bsps/shared/dev/serial/console-termios-init.c27
-rw-r--r--bsps/shared/dev/serial/console-termios.c27
-rw-r--r--bsps/shared/dev/serial/getserialmouseps2.c27
-rw-r--r--bsps/shared/dev/serial/legacy-console-control.c25
-rw-r--r--bsps/shared/dev/serial/legacy-console-select.c25
-rw-r--r--bsps/shared/dev/serial/legacy-console.c31
-rw-r--r--bsps/shared/dev/serial/legacy-console.h25
-rw-r--r--bsps/shared/dev/serial/mc68681.c25
-rw-r--r--bsps/shared/dev/serial/mc68681_p.h25
-rw-r--r--bsps/shared/dev/serial/mc68681_reg.c25
-rw-r--r--bsps/shared/dev/serial/mc68681_reg2.c25
-rw-r--r--bsps/shared/dev/serial/mc68681_reg4.c25
-rw-r--r--bsps/shared/dev/serial/mc68681_reg8.c25
-rw-r--r--bsps/shared/dev/serial/printk-dummy.c25
-rw-r--r--bsps/shared/dev/serial/uart-output-char.c27
-rw-r--r--bsps/shared/dev/serial/z85c30_reg.c25
-rw-r--r--bsps/shared/dev/serial/zynq-uart-kernel-io.c88
-rw-r--r--bsps/shared/dev/serial/zynq-uart-polled.c43
-rw-r--r--bsps/shared/dev/serial/zynq-uart.c21
-rw-r--r--bsps/shared/dev/spi/VERSION29
-rw-r--r--bsps/shared/dev/spi/xqspipsu-flash-helper.c2341
-rw-r--r--bsps/shared/dev/spi/xqspipsu.c1086
-rw-r--r--bsps/shared/dev/spi/xqspipsu_control.c282
-rw-r--r--bsps/shared/dev/spi/xqspipsu_hw.c768
-rw-r--r--bsps/shared/dev/spi/xqspipsu_options.c532
70 files changed, 11185 insertions, 260 deletions
diff --git a/bsps/shared/dev/btimer/btimer-cpucounter.c b/bsps/shared/dev/btimer/btimer-cpucounter.c
index 1663cba9ef..8757cb844b 100644
--- a/bsps/shared/dev/btimer/btimer-cpucounter.c
+++ b/bsps/shared/dev/btimer/btimer-cpucounter.c
@@ -1,9 +1,28 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
- * Copyright (c) 2017 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2017 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems/btimer.h>
diff --git a/bsps/shared/dev/clock/arm-generic-timer.c b/bsps/shared/dev/clock/arm-generic-timer.c
index 11df5cef25..ba159f6833 100644
--- a/bsps/shared/dev/clock/arm-generic-timer.c
+++ b/bsps/shared/dev/clock/arm-generic-timer.c
@@ -1,9 +1,28 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
- * Copyright (c) 2017 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2017 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <bsp.h>
@@ -35,15 +54,12 @@ typedef struct {
static arm_gt_clock_context arm_gt_clock_instance;
-/* This is defined in dev/clock/clockimpl.h */
-void Clock_isr(rtems_irq_hdl_param arg);
-
-static void arm_gt_clock_at_tick(void)
+static void arm_gt_clock_at_tick(arm_gt_clock_context *ctx)
{
uint64_t cval;
uint32_t interval;
- interval = arm_gt_clock_instance.interval;
+ interval = ctx->interval;
cval = arm_gt_clock_get_compare_value();
cval += interval;
arm_gt_clock_set_compare_value(cval);
@@ -52,7 +68,7 @@ static void arm_gt_clock_at_tick(void)
#endif /* ARM_GENERIC_TIMER_UNMASK_AT_TICK */
}
-static void arm_gt_clock_handler_install(void)
+static void arm_gt_clock_handler_install(rtems_interrupt_handler handler)
{
rtems_status_code sc;
@@ -60,8 +76,8 @@ static void arm_gt_clock_handler_install(void)
arm_gt_clock_instance.irq,
"Clock",
RTEMS_INTERRUPT_UNIQUE,
- (rtems_interrupt_handler) Clock_isr,
- NULL
+ handler,
+ &arm_gt_clock_instance
);
if (sc != RTEMS_SUCCESSFUL) {
bsp_fatal(BSP_ARM_FATAL_GENERIC_TIMER_CLOCK_IRQ_INSTALL);
@@ -166,14 +182,14 @@ RTEMS_SYSINIT_ITEM(
RTEMS_SYSINIT_ORDER_FIRST
);
-#define Clock_driver_support_at_tick() \
- arm_gt_clock_at_tick()
+#define Clock_driver_support_at_tick(arg) \
+ arm_gt_clock_at_tick(arg)
#define Clock_driver_support_initialize_hardware() \
arm_gt_clock_initialize()
#define Clock_driver_support_install_isr(isr) \
- arm_gt_clock_handler_install()
+ arm_gt_clock_handler_install(isr)
/* Include shared source clock driver code */
#include "../../shared/dev/clock/clockimpl.h"
diff --git a/bsps/shared/dev/clock/bcm2835-system-timer.c b/bsps/shared/dev/clock/bcm2835-system-timer.c
new file mode 100644
index 0000000000..bb8490d03a
--- /dev/null
+++ b/bsps/shared/dev/clock/bcm2835-system-timer.c
@@ -0,0 +1,94 @@
+/**
+ * @file
+ *
+ * @ingroup RTEMSDriverClockImpl
+ *
+ * @brief This source file contains the implementation of the BCM2835 Clock
+ * Driver.
+ */
+
+/*
+ * Copyright (c) 2013 Alan Cudmore
+ * Copyright (c) 2016 Pavel Pisa
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ *
+ * http://www.rtems.org/license/LICENSE
+ *
+*/
+
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/irq-generic.h>
+#include <bsp/raspberrypi.h>
+#include <rtems/timecounter.h>
+
+static struct timecounter raspberrypi_tc;
+
+static uint32_t raspberrypi_clock_get_timecount(struct timecounter *tc)
+{
+ return BCM2835_REG(BCM2835_GPU_TIMER_CLO);
+}
+
+static void raspberrypi_clock_at_tick(void)
+{
+ uint32_t act_val;
+ uint32_t next_cmp = BCM2835_REG(BCM2835_GPU_TIMER_C3);
+ next_cmp += rtems_configuration_get_microseconds_per_tick();
+ BCM2835_REG(BCM2835_GPU_TIMER_C3) = next_cmp;
+ act_val = BCM2835_REG(BCM2835_GPU_TIMER_CLO);
+
+ /*
+ * Clear interrupt only if there is time left to the next tick.
+ * If time of the next tick has already passed then interrupt
+ * request stays active and fires immediately after current tick
+ * processing is finished.
+ */
+ if ((int32_t)(next_cmp - act_val) > 0)
+ BCM2835_REG(BCM2835_GPU_TIMER_CS) = BCM2835_GPU_TIMER_CS_M3;
+}
+
+static void raspberrypi_clock_handler_install_isr(
+ rtems_interrupt_handler clock_isr
+)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+ sc = rtems_interrupt_handler_install(
+ BCM2835_IRQ_ID_GPU_TIMER_M3,
+ "Clock",
+ RTEMS_INTERRUPT_UNIQUE,
+ clock_isr,
+ NULL
+ );
+ if ( sc != RTEMS_SUCCESSFUL ) {
+ rtems_fatal_error_occurred(0xdeadbeef);
+ }
+}
+
+static void raspberrypi_clock_initialize_hardware(void)
+{
+ uint32_t next_cmp = BCM2835_REG(BCM2835_GPU_TIMER_CLO);
+ next_cmp += rtems_configuration_get_microseconds_per_tick();
+ BCM2835_REG(BCM2835_GPU_TIMER_C3) = next_cmp;
+ BCM2835_REG(BCM2835_GPU_TIMER_CS) = BCM2835_GPU_TIMER_CS_M3;
+
+ raspberrypi_tc.tc_get_timecount = raspberrypi_clock_get_timecount;
+ raspberrypi_tc.tc_counter_mask = 0xffffffff;
+ raspberrypi_tc.tc_frequency = 1000000; /* 1 MHz */
+ raspberrypi_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ rtems_timecounter_install(&raspberrypi_tc);
+}
+
+#define Clock_driver_support_at_tick(arg) raspberrypi_clock_at_tick()
+
+#define Clock_driver_support_initialize_hardware() raspberrypi_clock_initialize_hardware()
+
+#define Clock_driver_support_install_isr(clock_isr) \
+ raspberrypi_clock_handler_install_isr(clock_isr)
+
+#define CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR 1
+
+#include "../../../shared/dev/clock/clockimpl.h"
diff --git a/bsps/shared/dev/clock/clockimpl.h b/bsps/shared/dev/clock/clockimpl.h
index dad71307f4..b27f7c15bc 100644
--- a/bsps/shared/dev/clock/clockimpl.h
+++ b/bsps/shared/dev/clock/clockimpl.h
@@ -1,18 +1,40 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
*
- * @ingroup bsp_clock
+ * @ingroup RTEMSDriverClockImpl
+ *
+ * @brief This header file contains the shared Clock Driver implementation.
*
- * @brief Clock Tick Device Driver Shell
+ * This header file shall only be included by a particular Clock Driver
+ * implementation source file.
*/
/*
* COPYRIGHT (c) 1989-2014.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
@@ -20,27 +42,35 @@
#include <bsp.h>
#include <rtems/clockdrv.h>
#include <rtems/score/percpu.h>
+#include <rtems/score/processormaskimpl.h>
#include <rtems/score/smpimpl.h>
#include <rtems/score/timecounter.h>
#include <rtems/score/thread.h>
#include <rtems/score/watchdogimpl.h>
-#ifdef Clock_driver_nanoseconds_since_last_tick
-#error "Update driver to use the timecounter instead of nanoseconds extension"
-#endif
-
/**
- * @defgroup bsp_clock Clock Support
- *
- * @ingroup RTEMSBSPsShared
+ * @defgroup RTEMSDriverClockImpl Clock Driver Implementation
*
- * @brief Clock support
+ * @ingroup RTEMSDriverClock
*
+ * @brief This group contains the Clock Driver implementation.
*/
+
+#ifdef Clock_driver_nanoseconds_since_last_tick
+#error "Update driver to use the timecounter instead of nanoseconds extension"
+#endif
+
#if CLOCK_DRIVER_USE_FAST_IDLE && CLOCK_DRIVER_ISRS_PER_TICK
#error "Fast Idle PLUS n ISRs per tick is not supported"
#endif
+#if defined(BSP_FEATURE_IRQ_EXTENSION) || \
+ (CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
+typedef void * Clock_isr_argument;
+#else
+typedef rtems_vector_number Clock_isr_argument;
+#endif
+
/**
* @brief Do nothing by default.
*/
@@ -59,7 +89,7 @@
* @brief Do nothing by default.
*/
#ifndef Clock_driver_support_at_tick
- #define Clock_driver_support_at_tick()
+ #define Clock_driver_support_at_tick( arg ) do { (void) arg; } while (0)
#endif
/**
@@ -74,8 +104,9 @@
* instead of the default.
*/
#ifndef Clock_driver_timecounter_tick
-static void Clock_driver_timecounter_tick( void )
+static void Clock_driver_timecounter_tick( Clock_isr_argument arg )
{
+ (void) arg;
#if defined(CLOCK_DRIVER_USE_DUMMY_TIMECOUNTER)
rtems_clock_tick();
#elif defined(RTEMS_SMP) && defined(CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR)
@@ -117,25 +148,31 @@ volatile uint32_t Clock_driver_ticks;
#error "Clock_driver_support_shutdown_hardware() is no longer supported"
#endif
+#if CLOCK_DRIVER_USE_FAST_IDLE
+static bool _Clock_Has_watchdogs(const Per_CPU_Control *cpu)
+{
+ size_t i;
+
+ for (i = 0; i < RTEMS_ARRAY_SIZE(cpu->Watchdog.Header); ++i) {
+ if (_Watchdog_Header_first(&cpu->Watchdog.Header[i]) != NULL) {
+ return true;
+ }
+ }
+
+ return false;
+}
+#endif
+
/**
* @brief Clock_isr
*
* This is the clock tick interrupt handler.
*
- * @param vector Vector number.
+ * @param arg is the clock interrupt handler argument.
*/
-#if defined(BSP_FEATURE_IRQ_EXTENSION) || \
- (CPU_SIMPLE_VECTORED_INTERRUPTS != TRUE)
-void Clock_isr(void *arg);
-void Clock_isr(void *arg)
+void Clock_isr( Clock_isr_argument arg );
+void Clock_isr( Clock_isr_argument arg )
{
-#else
-rtems_isr Clock_isr(rtems_vector_number vector);
-rtems_isr Clock_isr(
- rtems_vector_number vector
-)
-{
-#endif
/*
* Accurate count of ISRs
*/
@@ -143,7 +180,7 @@ rtems_isr Clock_isr(
#if CLOCK_DRIVER_USE_FAST_IDLE
{
- Clock_driver_timecounter_tick();
+ Clock_driver_timecounter_tick( arg );
if (_SMP_Get_processor_maximum() == 1) {
struct timecounter *tc;
@@ -160,6 +197,7 @@ rtems_isr Clock_isr(
cpu_self->thread_dispatch_disable_level == cpu_self->isr_nest_level
&& cpu_self->heir == cpu_self->executing
&& cpu_self->executing->is_idle
+ && _Clock_Has_watchdogs(cpu_self)
) {
ISR_lock_Context lock_context;
@@ -172,7 +210,7 @@ rtems_isr Clock_isr(
}
}
- Clock_driver_support_at_tick();
+ Clock_driver_support_at_tick( arg );
}
#else
/*
@@ -180,14 +218,14 @@ rtems_isr Clock_isr(
*
* The counter/timer may or may not be set to automatically reload.
*/
- Clock_driver_support_at_tick();
+ Clock_driver_support_at_tick( arg );
#if CLOCK_DRIVER_ISRS_PER_TICK
/*
* The driver is multiple ISRs per clock tick.
*/
if ( !Clock_driver_isrs ) {
- Clock_driver_timecounter_tick();
+ Clock_driver_timecounter_tick( arg );
Clock_driver_isrs = CLOCK_DRIVER_ISRS_PER_TICK_VALUE;
}
@@ -196,7 +234,7 @@ rtems_isr Clock_isr(
/*
* The driver is one ISR per clock tick.
*/
- Clock_driver_timecounter_tick();
+ Clock_driver_timecounter_tick( arg );
#endif
#endif
}
diff --git a/bsps/shared/dev/clock/xil-ttc.c b/bsps/shared/dev/clock/xil-ttc.c
new file mode 100644
index 0000000000..624845d71c
--- /dev/null
+++ b/bsps/shared/dev/clock/xil-ttc.c
@@ -0,0 +1,214 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSDriverClockXilTTC
+ *
+ * @brief This source file contains a Clock Driver implementation using the
+ * Xilinx Triple Timer Counter (TTC).
+ */
+
+/*
+ * Copyright (C) 2024 embedded brains GmbH & Co. KG
+ * Copyright (C) 2023 Reflex Aerospace GmbH
+ *
+ * Written by Philip Kirkpatrick <p.kirkpatrick@reflexaerospace.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <bsp/fatal.h>
+#include <dev/clock/xttcps_hw.h>
+#include <rtems/sysinit.h>
+#include <rtems/timecounter.h>
+
+#if XTTCPS_COUNT_VALUE_MASK != UINT32_MAX
+#error "unexpected XTTCPS_COUNT_VALUE_MASK value"
+#endif
+
+/**
+ * @defgroup RTEMSDriverClockXilTTC \
+ * Xilinx Triple Timer Counter (TTC) Clock Driver
+ *
+ * @ingroup RTEMSDriverClockImpl
+ *
+ * @brief This group contains the Xilinx Triple Timer Counter (TTC) Clock
+ * Driver implementation.
+ *
+ * @{
+ */
+
+uint32_t _CPU_Counter_frequency( void )
+{
+ return XIL_CLOCK_TTC_REFERENCE_CLOCK;
+}
+
+CPU_Counter_ticks _CPU_Counter_read(void)
+{
+ return XTtcPs_ReadReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_COUNT_VALUE_OFFSET);
+}
+
+static void xil_ttc_initialize(void)
+{
+ /* Do not use a prescaler to get a high resolution time source */
+ XTtcPs_WriteReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_CLK_CNTRL_OFFSET, 0);
+
+ /* Disable interupts */
+ XTtcPs_WriteReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_IER_OFFSET, 0);
+
+ /*
+ * Enable the timer, do not enable waveform output, increment up, use
+ * overflow mode, enable match mode.
+ */
+ XTtcPs_WriteReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_CNT_CNTRL_OFFSET,
+ XTTCPS_CNT_CNTRL_EN_WAVE_MASK | XTTCPS_CNT_CNTRL_MATCH_MASK);
+}
+
+RTEMS_SYSINIT_ITEM(
+ xil_ttc_initialize,
+ RTEMS_SYSINIT_CPU_COUNTER,
+ RTEMS_SYSINIT_ORDER_MIDDLE
+);
+
+typedef struct {
+ struct timecounter base;
+ uint32_t irq_match_interval;
+} xil_ttc_timecounter;
+
+static xil_ttc_timecounter xil_ttc_clock_instance;
+
+static uint32_t xil_ttc_get_timecount(struct timecounter *tc)
+{
+ (void) tc;
+ return XTtcPs_ReadReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_COUNT_VALUE_OFFSET);
+}
+
+static void xil_ttc_clock_driver_support_initialize_hardware(void)
+{
+ xil_ttc_timecounter *tc;
+ uint64_t frequency;
+ uint32_t irq_match_interval;
+ uint32_t count;
+
+ tc = &xil_ttc_clock_instance;
+ frequency = XIL_CLOCK_TTC_REFERENCE_CLOCK;
+ irq_match_interval = (uint32_t)
+ ((frequency * rtems_configuration_get_microseconds_per_tick()) / 1000000);
+
+ /* Setup match register to generate clock interrupts */
+ count = XTtcPs_ReadReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_COUNT_VALUE_OFFSET);
+ XTtcPs_WriteReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_MATCH_0_OFFSET,
+ count + irq_match_interval);
+
+ /* Clear interupts (clear on read) */
+ (void) XTtcPs_ReadReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_ISR_OFFSET);
+
+ /* Enable interupt for match register */
+ XTtcPs_WriteReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_IER_OFFSET,
+ XTTCPS_IXR_MATCH_0_MASK);
+
+ /* Install timecounter */
+ tc->irq_match_interval = irq_match_interval;
+ tc->base.tc_counter_mask = UINT32_MAX;
+ tc->base.tc_frequency = XIL_CLOCK_TTC_REFERENCE_CLOCK;
+ tc->base.tc_get_timecount = xil_ttc_get_timecount;
+ tc->base.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
+ rtems_timecounter_install(&tc->base);
+}
+
+static void xil_ttc_clock_driver_support_at_tick(xil_ttc_timecounter *tc)
+{
+ uint32_t irq_match_interval;
+ uint32_t count;
+ uint32_t match;
+
+ irq_match_interval = tc->irq_match_interval;
+
+ /* Update match register */
+ match = XTtcPs_ReadReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_MATCH_0_OFFSET);
+ match += irq_match_interval;
+ XTtcPs_WriteReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_MATCH_0_OFFSET, match);
+
+ /* Clear interupts (clear on read) */
+ (void) XTtcPs_ReadReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_ISR_OFFSET);
+
+ /* Check that the new match value is in the future */
+ count = XTtcPs_ReadReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_COUNT_VALUE_OFFSET);
+
+ while (RTEMS_PREDICT_FALSE(match - count > irq_match_interval)) {
+ /*
+ * Tick misses may happen if interrupts are disabled for an extremly long
+ * period or while debugging.
+ */
+ rtems_timecounter_tick();
+
+ /* Update match register */
+ match += irq_match_interval;
+ XTtcPs_WriteReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_MATCH_0_OFFSET, match);
+
+ /* Clear interupts (clear on read) */
+ (void) XTtcPs_ReadReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_ISR_OFFSET);
+
+ /* Maybe the new match value is now in the future */
+ count = XTtcPs_ReadReg(XIL_CLOCK_TTC_BASE_ADDR, XTTCPS_COUNT_VALUE_OFFSET);
+ }
+}
+
+static rtems_interrupt_entry xil_ttc_interrupt_entry;
+
+static void xil_ttc_clock_driver_support_install_isr(
+ rtems_interrupt_handler handler
+)
+{
+ rtems_status_code sc;
+
+ rtems_interrupt_entry_initialize(
+ &xil_ttc_interrupt_entry,
+ handler,
+ &xil_ttc_clock_instance,
+ "Clock"
+ );
+ sc = rtems_interrupt_entry_install(
+ XIL_CLOCK_TTC_IRQ,
+ RTEMS_INTERRUPT_UNIQUE,
+ &xil_ttc_interrupt_entry
+ );
+ if ( sc != RTEMS_SUCCESSFUL ) {
+ bsp_fatal(XIL_FATAL_TTC_IRQ_INSTALL);
+ }
+}
+
+#define Clock_driver_support_at_tick(arg) \
+ xil_ttc_clock_driver_support_at_tick(arg)
+
+#define Clock_driver_support_initialize_hardware \
+ xil_ttc_clock_driver_support_initialize_hardware
+
+#define Clock_driver_support_install_isr(isr) \
+ xil_ttc_clock_driver_support_install_isr(isr)
+
+/** @} */
+
+#include "../../../shared/dev/clock/clockimpl.h"
diff --git a/bsps/shared/dev/cpucounter/cpucounterfrequency.c b/bsps/shared/dev/cpucounter/cpucounterfrequency.c
index d5249e3134..96a4078889 100644
--- a/bsps/shared/dev/cpucounter/cpucounterfrequency.c
+++ b/bsps/shared/dev/cpucounter/cpucounterfrequency.c
@@ -1,9 +1,28 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
- * Copyright (c) 2018 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2018 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems/score/cpu.h>
diff --git a/bsps/shared/dev/cpucounter/cpucounterread.c b/bsps/shared/dev/cpucounter/cpucounterread.c
index fd540efafc..f4e6e77fc1 100644
--- a/bsps/shared/dev/cpucounter/cpucounterread.c
+++ b/bsps/shared/dev/cpucounter/cpucounterread.c
@@ -1,9 +1,28 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
- * Copyright (c) 2014 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2014 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems/score/cpu.h>
diff --git a/bsps/shared/dev/display/disp_fonts.h b/bsps/shared/dev/display/disp_fonts.h
index 49caf05906..e6023721ee 100644
--- a/bsps/shared/dev/display/disp_fonts.h
+++ b/bsps/shared/dev/display/disp_fonts.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* Display driver for HCMS29xx.
*
@@ -5,11 +7,28 @@
*/
/*
- * Copyright (c) 2008 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2008 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DISP_FONTS_H
diff --git a/bsps/shared/dev/display/disp_hcms29xx.c b/bsps/shared/dev/display/disp_hcms29xx.c
index 6990f042db..4e221a1a94 100644
--- a/bsps/shared/dev/display/disp_hcms29xx.c
+++ b/bsps/shared/dev/display/disp_hcms29xx.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* Display driver for HCMS29xx.
*
@@ -6,11 +8,28 @@
*/
/*
- * Copyright (c) 2008 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2008 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
diff --git a/bsps/shared/dev/display/font_hcms29xx.c b/bsps/shared/dev/display/font_hcms29xx.c
index 8e8d25f7b6..43596923a8 100644
--- a/bsps/shared/dev/display/font_hcms29xx.c
+++ b/bsps/shared/dev/display/font_hcms29xx.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* Display driver for HCMS29xx.
*
@@ -5,11 +7,28 @@
*/
/*
- * Copyright (c) 2008 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2008 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <stddef.h>
diff --git a/bsps/shared/dev/display/font_hcms29xx.h b/bsps/shared/dev/display/font_hcms29xx.h
index 93feec9f94..d390b9c90b 100644
--- a/bsps/shared/dev/display/font_hcms29xx.h
+++ b/bsps/shared/dev/display/font_hcms29xx.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* Display driver for HCMS29xx.
*
@@ -5,11 +7,28 @@
*/
/*
- * Copyright (c) 2008 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2008 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FONT_HCMS29XX_H
diff --git a/bsps/shared/dev/dma/fsl-edma.c b/bsps/shared/dev/dma/fsl-edma.c
index b3e1bb2fc5..c8b812c1a5 100644
--- a/bsps/shared/dev/dma/fsl-edma.c
+++ b/bsps/shared/dev/dma/fsl-edma.c
@@ -7,7 +7,7 @@
*/
/*
- * Copyright (C) 2008-2020 embedded brains GmbH (http://www.embedded-brains.de)
+ * Copyright (C) 2008, 2020 embedded brains GmbH & Co. KG
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -40,7 +40,7 @@
#include <bsp/fatal.h>
#include <bsp/irq.h>
#ifdef LIBBSP_ARM_IMXRT_BSP_H
-#include <MIMXRT1052.h>
+#include <fsl_device_registers.h>
#endif
#define EDMA_CHANNELS_PER_GROUP 32U
diff --git a/bsps/shared/dev/getentropy/getentropy-cpucounter.c b/bsps/shared/dev/getentropy/getentropy-cpucounter.c
index f822587a14..44a2573f50 100644
--- a/bsps/shared/dev/getentropy/getentropy-cpucounter.c
+++ b/bsps/shared/dev/getentropy/getentropy-cpucounter.c
@@ -1,9 +1,28 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
- * Copyright (c) 2017 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2017 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
/*
diff --git a/bsps/shared/dev/i2c/cadence-i2c.c b/bsps/shared/dev/i2c/cadence-i2c.c
index 91774fb926..67dec0da46 100644
--- a/bsps/shared/dev/i2c/cadence-i2c.c
+++ b/bsps/shared/dev/i2c/cadence-i2c.c
@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (C) 2014 embedded brains GmbH
+ * Copyright (C) 2014 embedded brains GmbH & Co. KG
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,7 +28,6 @@
#include <dev/i2c/cadence-i2c.h>
#include <dev/i2c/cadence-i2c-regs.h>
-#include <rtems/irq-extension.h>
#include <rtems/score/assert.h>
#include <dev/i2c/i2c.h>
diff --git a/bsps/shared/dev/i2c/i2c-sc620.c b/bsps/shared/dev/i2c/i2c-sc620.c
index af0763fd97..ed360086d8 100644
--- a/bsps/shared/dev/i2c/i2c-sc620.c
+++ b/bsps/shared/dev/i2c/i2c-sc620.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
*
@@ -5,11 +7,28 @@
*/
/*
- * Copyright (c) 2013 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2013 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <libchip/i2c-sc620.h>
diff --git a/bsps/shared/dev/i2c/spi-flash-m25p40.c b/bsps/shared/dev/i2c/spi-flash-m25p40.c
index 60c29c3011..9f6189cd3c 100644
--- a/bsps/shared/dev/i2c/spi-flash-m25p40.c
+++ b/bsps/shared/dev/i2c/spi-flash-m25p40.c
@@ -1,13 +1,32 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* SPI driver for M25P40 like spi flash device.
*/
/*
- * Copyright (c) 2007 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2007 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems.h>
diff --git a/bsps/shared/dev/i2c/spi-fram-fm25l256.c b/bsps/shared/dev/i2c/spi-fram-fm25l256.c
index 509b4686ca..e1ff15e5b3 100644
--- a/bsps/shared/dev/i2c/spi-fram-fm25l256.c
+++ b/bsps/shared/dev/i2c/spi-fram-fm25l256.c
@@ -1,13 +1,32 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* SPI driver for FM25L256 like spi fram device.
*/
/*
- * Copyright (c) 2008 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2008 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems.h>
diff --git a/bsps/shared/dev/i2c/spi-memdrv.c b/bsps/shared/dev/i2c/spi-memdrv.c
index 7656966362..d890b9e41a 100644
--- a/bsps/shared/dev/i2c/spi-memdrv.c
+++ b/bsps/shared/dev/i2c/spi-memdrv.c
@@ -1,13 +1,32 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* SPI driver for spi memory devices.
*/
/*
- * Copyright (c) 2008 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2008 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
/*
diff --git a/bsps/shared/dev/i2c/spi-sd-card.c b/bsps/shared/dev/i2c/spi-sd-card.c
index 1d91ef5cb7..36a2721bb9 100644
--- a/bsps/shared/dev/i2c/spi-sd-card.c
+++ b/bsps/shared/dev/i2c/spi-sd-card.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
*
@@ -5,11 +7,28 @@
*/
/*
- * Copyright (c) 2008, 2018 embedded brains GmbH
+ * Copyright (C) 2008, 2018 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
diff --git a/bsps/shared/dev/ide/ata_util.c b/bsps/shared/dev/ide/ata_util.c
index 68e0f0bbe5..5fd286cdc5 100644
--- a/bsps/shared/dev/ide/ata_util.c
+++ b/bsps/shared/dev/ide/ata_util.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 embedded brains GmbH.
+ * Copyright (c) 2010 embedded brains GmbH & Co. KG
*
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
* Authors: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
diff --git a/bsps/shared/dev/irq/arm-gicv2-get-attributes.c b/bsps/shared/dev/irq/arm-gicv2-get-attributes.c
index 8a1351bbe5..613174bb3a 100644
--- a/bsps/shared/dev/irq/arm-gicv2-get-attributes.c
+++ b/bsps/shared/dev/irq/arm-gicv2-get-attributes.c
@@ -3,13 +3,14 @@
/**
* @file
*
- * @ingroup RTEMSBSPsShared
+ * @ingroup DevIRQGIC
*
- * @brief This source file contains the interrupt get attribute implementation.
+ * @brief This source file contains the implementation of
+ * bsp_interrupt_get_attributes() for the GICv2.
*/
/*
- * Copyright (c) 2013, 2021 embedded brains GmbH. All rights reserved.
+ * Copyright (C) 2013, 2021 embedded brains GmbH & Co. KG
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
diff --git a/bsps/shared/dev/irq/arm-gicv2-zynqmp.c b/bsps/shared/dev/irq/arm-gicv2-zynqmp.c
index ee4479155a..bb9bfafb48 100644
--- a/bsps/shared/dev/irq/arm-gicv2-zynqmp.c
+++ b/bsps/shared/dev/irq/arm-gicv2-zynqmp.c
@@ -3,9 +3,11 @@
/**
* @file
*
- * @ingroup RTEMSBSPsShared
+ * @ingroup DevIRQGIC
*
- * @brief This source file contains the interrupt get attribute implementation.
+ * @brief This source file contains the implementation of
+ * bsp_interrupt_get_attributes() for the GICv2 of Xilinx Zynq UltraScale+
+ * MPSoC and RFSoC devices.
*/
/*
diff --git a/bsps/shared/dev/irq/arm-gicv2.c b/bsps/shared/dev/irq/arm-gicv2.c
index 49aa6c2455..263278148b 100644
--- a/bsps/shared/dev/irq/arm-gicv2.c
+++ b/bsps/shared/dev/irq/arm-gicv2.c
@@ -1,17 +1,53 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup DevIRQGIC
+ *
+ * @brief This source file contains the implementation of the generic GICv2
+ * support.
+ */
+
/*
- * Copyright (c) 2013, 2021 embedded brains GmbH. All rights reserved.
+ * Copyright (C) 2013, 2021 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <dev/irq/arm-gic.h>
#include <dev/irq/arm-gic-arch.h>
-#include <bsp/irq.h>
#include <bsp/irq-generic.h>
#include <bsp/start.h>
+#include <rtems/score/processormaskimpl.h>
+
+/*
+ * The GIC architecture reserves interrupt ID numbers 1020 to 1023 for special
+ * purposes.
+ */
+#if BSP_INTERRUPT_VECTOR_COUNT >= 1020
+#error "BSP_INTERRUPT_VECTOR_COUNT is too large"
+#endif
#define GIC_CPUIF ((volatile gic_cpuif *) BSP_ARM_GIC_CPUIF_BASE)
@@ -47,12 +83,19 @@
void bsp_interrupt_dispatch(void)
{
volatile gic_cpuif *cpuif = GIC_CPUIF;
- uint32_t icciar = cpuif->icciar;
- rtems_vector_number vector = GIC_CPUIF_ICCIAR_ACKINTID_GET(icciar);
- rtems_vector_number spurious = 1023;
- if (vector != spurious) {
- arm_interrupt_handler_dispatch(vector);
+ while (true) {
+ uint32_t icciar = cpuif->icciar;
+ rtems_vector_number vector = GIC_CPUIF_ICCIAR_ACKINTID_GET(icciar);
+ uint32_t status;
+
+ if (!bsp_interrupt_is_valid_vector(vector)) {
+ break;
+ }
+
+ status = arm_interrupt_enable_interrupts();
+ bsp_interrupt_handler_dispatch_unchecked(vector);
+ arm_interrupt_restore_interrupts(status);
cpuif->icceoir = icciar;
}
@@ -301,6 +344,7 @@ rtems_status_code arm_gic_irq_get_group(
return sc;
}
+#ifdef RTEMS_SMP
rtems_status_code bsp_interrupt_set_affinity(
rtems_vector_number vector,
const Processor_mask *affinity
@@ -360,6 +404,7 @@ rtems_status_code bsp_interrupt_get_affinity(
_Processor_mask_From_uint32_t(affinity, targets, 0);
return RTEMS_SUCCESSFUL;
}
+#endif
void arm_gic_trigger_sgi(rtems_vector_number vector, uint32_t targets)
{
@@ -373,9 +418,11 @@ void arm_gic_trigger_sgi(rtems_vector_number vector, uint32_t targets)
| GIC_DIST_ICDSGIR_SGIINTID(vector);
}
+#ifdef RTEMS_SMP
uint32_t arm_gic_irq_processor_count(void)
{
volatile gic_dist *dist = ARM_GIC_DIST;
return GIC_DIST_ICDICTR_CPU_NUMBER_GET(dist->icdictr) + 1;
}
+#endif
diff --git a/bsps/shared/dev/irq/arm-gicv3.c b/bsps/shared/dev/irq/arm-gicv3.c
index 4772ff5db4..958b1061bd 100644
--- a/bsps/shared/dev/irq/arm-gicv3.c
+++ b/bsps/shared/dev/irq/arm-gicv3.c
@@ -1,6 +1,15 @@
-/*
- * SPDX-License-Identifier: BSD-2-Clause
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup DevIRQGIC
*
+ * @brief This source file contains the implementation of the generic GICv3
+ * support.
+ */
+
+/*
* Copyright (C) 2019 On-Line Applications Research Corporation (OAR)
*
* Redistribution and use in source and binary forms, with or without
@@ -27,18 +36,24 @@
#include <dev/irq/arm-gicv3.h>
-#include <bsp/irq.h>
#include <bsp/irq-generic.h>
#include <bsp/start.h>
+#include <rtems/score/processormaskimpl.h>
void bsp_interrupt_dispatch(void)
{
- uint32_t icciar = READ_SR(ICC_IAR1);
- rtems_vector_number vector = GIC_CPUIF_ICCIAR_ACKINTID_GET(icciar);
- rtems_vector_number spurious = 1023;
+ while (true) {
+ uint32_t icciar = READ_SR(ICC_IAR1);
+ rtems_vector_number vector = GIC_CPUIF_ICCIAR_ACKINTID_GET(icciar);
+ uint32_t status;
- if (vector != spurious) {
- arm_interrupt_handler_dispatch(vector);
+ if (!bsp_interrupt_is_valid_vector(vector)) {
+ break;
+ }
+
+ status = arm_interrupt_enable_interrupts();
+ bsp_interrupt_handler_dispatch_unchecked(vector);
+ arm_interrupt_restore_interrupts(status);
WRITE_SR(ICC_EOIR1, icciar);
}
@@ -242,6 +257,7 @@ rtems_status_code arm_gic_irq_get_priority(
return sc;
}
+#ifdef RTEMS_SMP
rtems_status_code bsp_interrupt_set_affinity(
rtems_vector_number vector,
const Processor_mask *affinity
@@ -274,12 +290,14 @@ rtems_status_code bsp_interrupt_get_affinity(
_Processor_mask_From_uint32_t(affinity, targets, 0);
return RTEMS_SUCCESSFUL;
}
+#endif
void arm_gic_trigger_sgi(rtems_vector_number vector, uint32_t targets)
{
gicv3_trigger_sgi(vector, targets);
}
+#ifdef RTEMS_SMP
uint32_t arm_gic_irq_processor_count(void)
{
volatile gic_dist *dist = ARM_GIC_DIST;
@@ -306,3 +324,4 @@ uint32_t arm_gic_irq_processor_count(void)
return cpu_count;
}
+#endif
diff --git a/bsps/shared/dev/nand/VERSION b/bsps/shared/dev/nand/VERSION
new file mode 100644
index 0000000000..5e4eb00fe9
--- /dev/null
+++ b/bsps/shared/dev/nand/VERSION
@@ -0,0 +1,24 @@
+The information in this file describes the source of files in
+bsps/shared/dev/nand/ and bsps/include/dev/nand/.
+
+Import from:
+
+https://github.com/Xilinx/embeddedsw.git
+
+commit 5330a64c8efd14f0eef09befdbb8d3d738c33ec2
+Refs: <xilinx_v2022.2>
+Author: Nicole Baze <nicole.baze@xilinx.com>
+AuthorDate: Mon Oct 3 13:27:19 2022 -0700
+Commit: Siva Addepalli <sivaprasad.addepalli@xilinx.com>
+CommitDate: Fri Oct 7 10:26:16 2022 +0530
+
+ xilpm: versal: server: Fix bug in AIE2 zeroization
+
+ There is a bug in AIE2 zeriozation function when polling for memory
+ zeroization complete. Currently the entire memory register is being
+ checked against zero but instead we need to check the bits specific
+ to the memory tiles. This patch updates the zeroization check by
+ adding a mask so that only the desired bits are checked for zero.
+
+ Signed-off-by: Nicole Baze <nicole.baze@xilinx.com>
+ Acked-by: Jesus De Haro <jesus.de-haro@xilinx.com>
diff --git a/bsps/shared/dev/nand/xnandpsu.c b/bsps/shared/dev/nand/xnandpsu.c
new file mode 100644
index 0000000000..79025f3c04
--- /dev/null
+++ b/bsps/shared/dev/nand/xnandpsu.c
@@ -0,0 +1,3027 @@
+/******************************************************************************
+* Copyright (C) 2015 - 2022 Xilinx, Inc. All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+*
+* @file xnandpsu.c
+* @addtogroup Overview
+* @{
+*
+* This file contains the implementation of the interface functions for
+* XNandPsu driver. Refer to the header file xnandpsu.h for more detailed
+* information.
+*
+* This module supports for NAND flash memory devices that conform to the
+* "Open NAND Flash Interface" (ONFI) 3.0 Specification. This modules
+* implements basic flash operations like read, write and erase.
+*
+* @note Driver has been renamed to nandpsu after change in
+* naming convention.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ---- ---------- -----------------------------------------------
+* 1.0 nm 05/06/2014 First release
+* 2.0 sb 01/12/2015 Removed Null checks for Buffer passed
+* as parameter to Read API's
+* - XNandPsu_Read()
+* - XNandPsu_ReadPage
+* Modified
+* - XNandPsu_SetFeature()
+* - XNandPsu_GetFeature()
+* and made them public.
+* Removed Failure Return for BCF Error check in
+* XNandPsu_ReadPage() and added BCH_Error counter
+* in the instance pointer structure.
+* Added XNandPsu_Prepare_Cmd API
+* Replaced
+* - XNandPsu_IntrStsEnable
+* - XNandPsu_IntrStsClear
+* - XNandPsu_IntrClear
+* - XNandPsu_SetProgramReg
+* with XNandPsu_WriteReg call
+* Modified xnandpsu.c file API's with above changes.
+* Corrected the program command for Set Feature API.
+* Modified
+* - XNandPsu_OnfiReadStatus
+* - XNandPsu_GetFeature
+* - XNandPsu_SetFeature
+* to add support for DDR mode.
+* Changed Convention for SLC/MLC
+* SLC --> HAMMING
+* MLC --> BCH
+* SlcMlc --> IsBCH
+* Removed extra DMA mode initialization from
+* the XNandPsu_CfgInitialize API.
+* Modified
+* - XNandPsu_SetEccAddrSize
+* ECC address now is calculated based upon the
+* size of spare area
+* Modified Block Erase API, removed clearing of
+* packet register before erase.
+* Clearing Data Interface Register before
+* XNandPsu_OnfiReset call.
+* Modified XNandPsu_ChangeTimingMode API supporting
+* SDR and NVDDR interface for timing modes 0 to 5.
+* Modified Bbt Signature and Version Offset value for
+* Oob and No-Oob region.
+* 1.0 kpc 17/6/2015 Added timer based timeout intsead of sw counter.
+* 1.1 mi 09/16/16 Removed compilation warnings with extra compiler flags.
+* 1.1 nsk 11/07/16 Change memcpy to Xil_MemCpy to handle word aligned
+* data access.
+* 1.2 nsk 01/19/17 Fix for the failure of reading nand first redundant
+* parameter page. CR#966603
+* 1.3 nsk 08/14/17 Added CCI support
+* 1.4 nsk 04/10/18 Added ICCARM compiler support. CR#997552.
+* 1.5 mus 11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
+* 1.5 mus 11/05/18 Updated XNandPsu_ChangeClockFreq to fix compilation
+* warnings.
+* 1.6 sd 06/02/20 Added Clock support
+* 1.6 sd 20/03/20 Added compilation flag
+* 1.8 sg 03/18/21 Added validation check for parameter page.
+* 1.9 akm 07/15/21 Initialize NandInstPtr with Data Interface & Timing mode info.
+* 1.10 akm 10/20/21 Fix gcc warnings.
+* 1.10 akm 12/21/21 Validate input parameters before use.
+* 1.10 akm 01/05/22 Remove assert checks form static and internal APIs.
+* 1.11 akm 03/31/22 Fix unused parameter warning.
+* 1.11 akm 03/31/22 Fix misleading-indentation warning.
+*
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+#include "xnandpsu.h"
+#include "xnandpsu_bbm.h"
+#include "sleep.h"
+#include "xil_mem.h"
+/************************** Constant Definitions *****************************/
+
+static const XNandPsu_EccMatrix EccMatrix[] = {
+ /* 512 byte page */
+ {XNANDPSU_PAGE_SIZE_512, 9U, 1U, XNANDPSU_HAMMING, 0x20DU, 0x3U},
+ {XNANDPSU_PAGE_SIZE_512, 9U, 4U, XNANDPSU_BCH, 0x209U, 0x7U},
+ {XNANDPSU_PAGE_SIZE_512, 9U, 8U, XNANDPSU_BCH, 0x203U, 0xDU},
+ /* 2K byte page */
+ {XNANDPSU_PAGE_SIZE_2K, 9U, 1U, XNANDPSU_HAMMING, 0x834U, 0xCU},
+ {XNANDPSU_PAGE_SIZE_2K, 9U, 4U, XNANDPSU_BCH, 0x826U, 0x1AU},
+ {XNANDPSU_PAGE_SIZE_2K, 9U, 8U, XNANDPSU_BCH, 0x80cU, 0x34U},
+ {XNANDPSU_PAGE_SIZE_2K, 9U, 12U, XNANDPSU_BCH, 0x822U, 0x4EU},
+ {XNANDPSU_PAGE_SIZE_2K, 10U, 24U, XNANDPSU_BCH, 0x81cU, 0x54U},
+ /* 4K byte page */
+ {XNANDPSU_PAGE_SIZE_4K, 9U, 1U, XNANDPSU_HAMMING, 0x1068U, 0x18U},
+ {XNANDPSU_PAGE_SIZE_4K, 9U, 4U, XNANDPSU_BCH, 0x104cU, 0x34U},
+ {XNANDPSU_PAGE_SIZE_4K, 9U, 8U, XNANDPSU_BCH, 0x1018U, 0x68U},
+ {XNANDPSU_PAGE_SIZE_4K, 9U, 12U, XNANDPSU_BCH, 0x1044U, 0x9CU},
+ {XNANDPSU_PAGE_SIZE_4K, 10U, 24U, XNANDPSU_BCH, 0x1038U, 0xA8U},
+ /* 8K byte page */
+ {XNANDPSU_PAGE_SIZE_8K, 9U, 1U, XNANDPSU_HAMMING, 0x20d0U, 0x30U},
+ {XNANDPSU_PAGE_SIZE_8K, 9U, 4U, XNANDPSU_BCH, 0x2098U, 0x68U},
+ {XNANDPSU_PAGE_SIZE_8K, 9U, 8U, XNANDPSU_BCH, 0x2030U, 0xD0U},
+ {XNANDPSU_PAGE_SIZE_8K, 9U, 12U, XNANDPSU_BCH, 0x2088U, 0x138U},
+ {XNANDPSU_PAGE_SIZE_8K, 10U, 24U, XNANDPSU_BCH, 0x2070U, 0x150U},
+ /* 16K byte page */
+ {XNANDPSU_PAGE_SIZE_16K, 9U, 1U, XNANDPSU_HAMMING, 0x4460U, 0x60U},
+ {XNANDPSU_PAGE_SIZE_16K, 9U, 4U, XNANDPSU_BCH, 0x43f0U, 0xD0U},
+ {XNANDPSU_PAGE_SIZE_16K, 9U, 8U, XNANDPSU_BCH, 0x4320U, 0x1A0U},
+ {XNANDPSU_PAGE_SIZE_16K, 9U, 12U, XNANDPSU_BCH, 0x4250U, 0x270U},
+ {XNANDPSU_PAGE_SIZE_16K, 10U, 24U, XNANDPSU_BCH, 0x4220U, 0x2A0U}
+};
+
+/**************************** Type Definitions *******************************/
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+static s32 XNandPsu_FlashInit(XNandPsu *InstancePtr);
+
+static s32 XNandPsu_InitGeometry(XNandPsu *InstancePtr, OnfiParamPage *Param);
+
+static void XNandPsu_InitFeatures(XNandPsu *InstancePtr, OnfiParamPage *Param);
+
+static void XNandPsu_InitDataInterface(XNandPsu *InstancePtr, OnfiParamPage *Param);
+
+static void XNandPsu_InitTimingMode(XNandPsu *InstancePtr, OnfiParamPage *Param);
+
+static s32 XNandPsu_PollRegTimeout(XNandPsu *InstancePtr, u32 RegOffset,
+ u32 Mask, u32 Timeout);
+
+static void XNandPsu_SetPktSzCnt(XNandPsu *InstancePtr, u32 PktSize,
+ u32 PktCount);
+
+static void XNandPsu_SetPageColAddr(XNandPsu *InstancePtr, u32 Page, u16 Col);
+
+static void XNandPsu_SetPageSize(XNandPsu *InstancePtr);
+
+static void XNandPsu_SelectChip(XNandPsu *InstancePtr, u32 Target);
+
+static s32 XNandPsu_OnfiReset(XNandPsu *InstancePtr, u32 Target);
+
+static s32 XNandPsu_OnfiReadStatus(XNandPsu *InstancePtr, u32 Target,
+ u16 *OnfiStatus);
+
+static s32 XNandPsu_OnfiReadId(XNandPsu *InstancePtr, u32 Target, u8 IdAddr,
+ u32 IdLen, u8 *Buf);
+
+static s32 XNandPsu_OnfiReadParamPage(XNandPsu *InstancePtr, u32 Target,
+ u8 *Buf);
+
+static s32 XNandPsu_ProgramPage(XNandPsu *InstancePtr, u32 Target, u32 Page,
+ u32 Col, u8 *Buf);
+
+static s32 XNandPsu_ReadPage(XNandPsu *InstancePtr, u32 Target, u32 Page,
+ u32 Col, u8 *Buf);
+
+static s32 XNandPsu_CheckOnDie(XNandPsu *InstancePtr);
+
+static void XNandPsu_SetEccAddrSize(XNandPsu *InstancePtr);
+
+static s32 XNandPsu_ChangeReadColumn(XNandPsu *InstancePtr, u32 Target,
+ u32 Col, u32 PktSize, u32 PktCount,
+ u8 *Buf);
+
+static s32 XNandPsu_ChangeWriteColumn(XNandPsu *InstancePtr, u32 Target,
+ u32 Col, u32 PktSize, u32 PktCount,
+ u8 *Buf);
+
+static s32 XNandPsu_InitExtEcc(XNandPsu *InstancePtr, OnfiExtPrmPage *ExtPrm);
+
+static s32 XNandPsu_Data_ReadWrite(XNandPsu *InstancePtr, u8* Buf, u32 PktCount,
+ u32 PktSize, u32 Operation, u8 DmaMode);
+
+static s32 XNandPsu_WaitFor_Transfer_Complete(XNandPsu *InstancePtr);
+
+static s32 XNandPsu_Device_Ready(XNandPsu *InstancePtr, u32 Target);
+
+static void XNandPsu_Fifo_Read(XNandPsu *InstancePtr, u8* Buf, u32 Size);
+
+static void XNandPsu_Fifo_Write(XNandPsu *InstancePtr, u8* Buf, u32 Size);
+
+static void XNandPsu_Update_DmaAddr(XNandPsu *InstancePtr, u8* Buf);
+/*****************************************************************************/
+/**
+*
+* This function initializes a specific XNandPsu instance. This function must
+* be called prior to using the NAND flash device to read or write any data.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param ConfigPtr points to XNandPsu device configuration structure.
+* @param EffectiveAddr is the base address of NAND flash controller.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if fail.
+*
+* @note The user needs to first call the XNandPsu_LookupConfig() API
+* which returns the Configuration structure pointer which is
+* passed as a parameter to the XNandPsu_CfgInitialize() API.
+*
+******************************************************************************/
+s32 XNandPsu_CfgInitialize(XNandPsu *InstancePtr, XNandPsu_Config *ConfigPtr,
+ u32 EffectiveAddr)
+{
+ /* Assert the input arguments. */
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(ConfigPtr != NULL);
+
+ s32 Status = XST_FAILURE;
+
+ /* Initialize InstancePtr Config structure */
+ InstancePtr->Config.DeviceId = ConfigPtr->DeviceId;
+ InstancePtr->Config.BaseAddress = EffectiveAddr;
+ InstancePtr->Config.IsCacheCoherent = ConfigPtr->IsCacheCoherent;
+#if defined (XCLOCKING)
+ InstancePtr->Config.RefClk = ConfigPtr->RefClk;
+#endif
+ /* Operate in Polling Mode */
+ InstancePtr->Mode = XNANDPSU_POLLING;
+ /* Enable MDMA mode by default */
+ InstancePtr->DmaMode = XNANDPSU_MDMA;
+ InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
+
+#ifdef __rtems__
+ /* Set page cache to unavailable */
+ InstancePtr->PartialDataPageIndex = XNANDPSU_PAGE_CACHE_UNAVAILABLE;
+#endif
+
+ /* Initialize the NAND flash targets */
+ Status = XNandPsu_FlashInit(InstancePtr);
+ if (Status != XST_SUCCESS) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Flash init failed\r\n",__func__);
+#endif
+ goto Out;
+ }
+ /* Set ECC mode */
+ if (InstancePtr->Features.EzNand != 0U) {
+ InstancePtr->EccMode = XNANDPSU_EZNAND;
+ } else if (InstancePtr->Features.OnDie != 0U) {
+ InstancePtr->EccMode = XNANDPSU_ONDIE;
+ } else {
+ InstancePtr->EccMode = XNANDPSU_HWECC;
+ }
+
+ /* Initialize Ecc Error flip counters */
+ InstancePtr->Ecc_Stat_PerPage_flips = 0U;
+ InstancePtr->Ecc_Stats_total_flips = 0U;
+
+ /*
+ * Scan for the bad block table(bbt) stored in the flash & load it in
+ * memory(RAM). If bbt is not found, create bbt by scanning factory
+ * marked bad blocks and store it in last good blocks of flash.
+ */
+ XNandPsu_InitBbtDesc(InstancePtr);
+ Status = XNandPsu_ScanBbt(InstancePtr);
+ if (Status != XST_SUCCESS) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: BBT scan failed\r\n",__func__);
+#endif
+ goto Out;
+ }
+
+#ifdef __rtems__
+ /* Set page cache to none */
+ InstancePtr->PartialDataPageIndex = XNANDPSU_PAGE_CACHE_NONE;
+#endif
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function initializes the NAND flash and gets the geometry information.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_FlashInit(XNandPsu *InstancePtr)
+{
+ u32 Target;
+ u8 Id[ONFI_SIG_LEN] = {0U};
+ OnfiParamPage Param[ONFI_MND_PRM_PGS] = {0U};
+ s32 Status = XST_FAILURE;
+ u32 Index;
+ u32 Crc;
+ u32 PrmPgOff;
+ u32 PrmPgLen;
+#ifdef __ICCARM__
+#pragma pack(push, 1)
+ OnfiExtPrmPage ExtParam = {0U};
+#pragma pack(pop)
+#else
+ OnfiExtPrmPage ExtParam __attribute__ ((aligned(64))) = {0U};
+#endif
+
+ /* Clear Data Interface Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_DATA_INTF_OFFSET, 0U);
+
+ /* Clear DMA Buffer Boundary Register */
+ XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XNANDPSU_DMA_BUF_BND_OFFSET, 0U);
+
+ for (Target = 0U; Target < XNANDPSU_MAX_TARGETS; Target++) {
+ /* Reset the Target */
+ Status = XNandPsu_OnfiReset(InstancePtr, Target);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ /* Read ONFI ID */
+ Status = XNandPsu_OnfiReadId(InstancePtr, Target,
+ ONFI_READ_ID_ADDR,
+ ONFI_SIG_LEN,
+ (u8 *)&Id[0]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+
+ if (!IS_ONFI(Id)) {
+ if (Target == 0U) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: ONFI ID doesn't match\r\n",
+ __func__);
+#endif
+ Status = XST_FAILURE;
+ goto Out;
+ }
+ }
+
+ /* Read Parameter Page */
+ Status = XNandPsu_OnfiReadParamPage(InstancePtr,
+ Target, (u8 *)&Param[0]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ for(Index = 0U; Index < ONFI_MND_PRM_PGS; Index++){
+ /* Check CRC */
+ Crc = XNandPsu_OnfiParamPageCrc((u8*)&Param[Index], 0U,
+ ONFI_CRC_LEN);
+ if (Crc != Param[Index].Crc) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: ONFI parameter page (%d) crc check failed\r\n",
+ __func__, Index);
+#endif
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (Index >= ONFI_MND_PRM_PGS) {
+ Status = XST_FAILURE;
+ goto Out;
+ }
+ /* Fill Geometry for the first target */
+ if (Target == 0U) {
+ Status = XNandPsu_InitGeometry(InstancePtr, &Param[Index]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ XNandPsu_InitDataInterface(InstancePtr, &Param[Index]);
+ XNandPsu_InitTimingMode(InstancePtr, &Param[Index]);
+ XNandPsu_InitFeatures(InstancePtr, &Param[Index]);
+ if ((!InstancePtr->Features.EzNand) != 0U) {
+ Status =XNandPsu_CheckOnDie(InstancePtr);
+ if (Status != XST_SUCCESS) {
+ InstancePtr->Features.OnDie = 0U;
+ }
+ }
+ if ((InstancePtr->Geometry.NumBitsECC == 0xFFU) &&
+ (InstancePtr->Features.ExtPrmPage != 0U)) {
+ /* ONFI 3.1 section 5.7.1.6 & 5.7.1.7 */
+ PrmPgLen = (u32)Param[Index].ExtParamPageLen * 16U;
+ PrmPgOff = (u32)((u32)Param[Index].NumOfParamPages *
+ ONFI_PRM_PG_LEN) + (Index * (u32)PrmPgLen);
+
+ Status = XNandPsu_ChangeReadColumn(
+ InstancePtr, Target,
+ PrmPgOff, PrmPgLen, 1U,
+ (u8 *)(void *)&ExtParam);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ /* Check CRC */
+ Crc = XNandPsu_OnfiParamPageCrc(
+ (u8 *)&ExtParam,
+ 2U, PrmPgLen);
+ if (Crc != ExtParam.Crc) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: ONFI extended parameter page (%d) crc check failed\r\n",
+ __func__, Index);
+#endif
+ Status = XST_FAILURE;
+ goto Out;
+ }
+ /* Initialize Extended ECC info */
+ Status = XNandPsu_InitExtEcc(
+ InstancePtr,
+ &ExtParam);
+ if (Status != XST_SUCCESS) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Init extended ecc failed\r\n",__func__);
+#endif
+ goto Out;
+ }
+ }
+ /* Configure ECC settings */
+ XNandPsu_SetEccAddrSize(InstancePtr);
+ }
+ InstancePtr->Geometry.NumTargets++;
+ }
+ /* Calculate total number of blocks and total size of flash */
+ InstancePtr->Geometry.NumPages = InstancePtr->Geometry.NumTargets *
+ InstancePtr->Geometry.NumTargetPages;
+ InstancePtr->Geometry.NumBlocks = InstancePtr->Geometry.NumTargets *
+ InstancePtr->Geometry.NumTargetBlocks;
+ InstancePtr->Geometry.DeviceSize =
+ (u64)InstancePtr->Geometry.NumTargets *
+ InstancePtr->Geometry.TargetSize;
+
+ Status = XST_SUCCESS;
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function initializes the geometry information from ONFI parameter page.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Param is pointer to the ONFI parameter page.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_InitGeometry(XNandPsu *InstancePtr, OnfiParamPage *Param)
+{
+ s32 Status = XST_FAILURE;
+
+ if (Param->BytesPerPage > XNANDPSU_MAX_PAGE_SIZE) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Invalid Bytes Per Page %d\r\n",
+ __func__, Param->BytesPerPage);
+#endif
+ goto Out;
+ }
+ InstancePtr->Geometry.BytesPerPage = Param->BytesPerPage;
+
+
+ if (Param->SpareBytesPerPage > XNANDPSU_MAX_SPARE_SIZE) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Invalid Spare Bytes Per Page %d\r\n",
+ __func__, Param->SpareBytesPerPage);
+#endif
+ goto Out;
+ }
+ InstancePtr->Geometry.SpareBytesPerPage = Param->SpareBytesPerPage;
+
+ if (Param->PagesPerBlock > XNANDPSU_MAX_PAGES_PER_BLOCK) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Invalid Page Count Per Block %d\r\n",
+ __func__, Param->PagesPerBlock);
+#endif
+ goto Out;
+ }
+ InstancePtr->Geometry.PagesPerBlock = Param->PagesPerBlock;
+
+
+ if (Param->BlocksPerLun > XNANDPSU_MAX_BLOCKS) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Invalid block count per LUN %d\r\n",
+ __func__, Param->BlocksPerLun);
+#endif
+ goto Out;
+ }
+ InstancePtr->Geometry.BlocksPerLun = Param->BlocksPerLun;
+
+ if (Param->NumLuns > XNANDPSU_MAX_LUNS) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Invalid LUN count %d\r\n",
+ __func__, Param->NumLuns);
+#endif
+ goto Out;
+ }
+ InstancePtr->Geometry.NumLuns = Param->NumLuns;
+
+ InstancePtr->Geometry.RowAddrCycles = Param->AddrCycles & 0xFU;
+ InstancePtr->Geometry.ColAddrCycles = (Param->AddrCycles >> 4U) & 0xFU;
+ InstancePtr->Geometry.NumBitsPerCell = Param->BitsPerCell;
+ InstancePtr->Geometry.NumBitsECC = Param->EccBits;
+ InstancePtr->Geometry.BlockSize = (Param->PagesPerBlock *
+ Param->BytesPerPage);
+ InstancePtr->Geometry.NumTargetBlocks = (Param->BlocksPerLun *
+ (u32)Param->NumLuns);
+ InstancePtr->Geometry.NumTargetPages = (Param->BlocksPerLun *
+ (u32)Param->NumLuns *
+ Param->PagesPerBlock);
+ InstancePtr->Geometry.TargetSize = ((u64)Param->BlocksPerLun *
+ (u64)Param->NumLuns *
+ (u64)Param->PagesPerBlock *
+ (u64)Param->BytesPerPage);
+ InstancePtr->Geometry.EccCodeWordSize = 9U; /* 2 power of 9 = 512 */
+ if (InstancePtr->Geometry.NumTargetBlocks > XNANDPSU_MAX_BLOCKS)
+ xil_printf("!!! Device contains more blocks than the max defined blocks in driver\r\n");
+
+#ifdef XNANDPSU_DEBUG
+ xil_printf("Manufacturer: %s\r\n", Param->DeviceManufacturer);
+ xil_printf("Device Model: %s\r\n", Param->DeviceModel);
+ xil_printf("Jedec ID: 0x%x\r\n", Param->JedecManufacturerId);
+ xil_printf("Bytes Per Page: 0x%x\r\n", Param->BytesPerPage);
+ xil_printf("Spare Bytes Per Page: 0x%x\r\n", Param->SpareBytesPerPage);
+ xil_printf("Pages Per Block: 0x%x\r\n", Param->PagesPerBlock);
+ xil_printf("Blocks Per LUN: 0x%x\r\n", Param->BlocksPerLun);
+ xil_printf("Number of LUNs: 0x%x\r\n", Param->NumLuns);
+ xil_printf("Number of bits per cell: 0x%x\r\n", Param->BitsPerCell);
+ xil_printf("Number of ECC bits: 0x%x\r\n", Param->EccBits);
+ xil_printf("Block Size: 0x%x\r\n", InstancePtr->Geometry.BlockSize);
+
+ xil_printf("Number of Target Blocks: 0x%x\r\n",
+ InstancePtr->Geometry.NumTargetBlocks);
+ xil_printf("Number of Target Pages: 0x%x\r\n",
+ InstancePtr->Geometry.NumTargetPages);
+
+#endif
+ Status = XST_SUCCESS;
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function initializes the feature list from ONFI parameter page.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Param is pointer to ONFI parameter page buffer.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static void XNandPsu_InitFeatures(XNandPsu *InstancePtr, OnfiParamPage *Param)
+{
+ InstancePtr->Features.NvDdr = ((Param->Features & (1U << 5)) != 0U) ?
+ 1U : 0U;
+ InstancePtr->Features.EzNand = ((Param->Features & (1U << 9)) != 0U) ?
+ 1U : 0U;
+ InstancePtr->Features.ExtPrmPage = ((Param->Features & (1U << 7)) != 0U) ?
+ 1U : 0U;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function initializes the Data Interface from ONFI parameter page.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Param is pointer to ONFI parameter page buffer.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static void XNandPsu_InitDataInterface(XNandPsu *InstancePtr, OnfiParamPage *Param)
+{
+ if (Param->NVDDRTimingMode)
+ InstancePtr->DataInterface = XNANDPSU_NVDDR;
+ else if (Param->SDRTimingMode)
+ InstancePtr->DataInterface = XNANDPSU_SDR;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function initializes the Timing mode from ONFI parameter page.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Param is pointer to ONFI parameter page buffer.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static void XNandPsu_InitTimingMode(XNandPsu *InstancePtr, OnfiParamPage *Param)
+{
+ s8 Mode;
+ u8 TimingMode = (u8)(Param->SDRTimingMode);
+
+ if (InstancePtr->DataInterface == XNANDPSU_NVDDR)
+ TimingMode = Param->NVDDRTimingMode;
+
+ for(Mode = XNANDPSU_MAX_TIMING_MODE; Mode >= 0; Mode--) {
+ if (TimingMode & (0x01 << Mode)) {
+ InstancePtr->TimingMode = Mode;
+ break;
+ } else {
+ continue;
+ }
+ }
+}
+
+/*****************************************************************************/
+/**
+*
+* This function checks if the flash supports on-die ECC.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Param is pointer to ONFI parameter page.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_CheckOnDie(XNandPsu *InstancePtr)
+{
+ s32 Status = XST_FAILURE;
+ u8 JedecId[2] = {0U};
+ u8 EccSetFeature[4] = {0x08U, 0x00U, 0x00U, 0x00U};
+ u8 EccGetFeature[4] ={0U};
+
+ /*
+ * Check if this flash supports On-Die ECC.
+ * For more information, refer to Micron TN2945.
+ * Micron Flash: MT29F1G08ABADA, MT29F1G08ABBDA
+ * MT29F1G16ABBDA,
+ * MT29F2G08ABBEA, MT29F2G16ABBEA,
+ * MT29F2G08ABAEA, MT29F2G16ABAEA,
+ * MT29F4G08ABBDA, MT29F4G16ABBDA,
+ * MT29F4G08ABADA, MT29F4G16ABADA,
+ * MT29F8G08ADBDA, MT29F8G16ADBDA,
+ * MT29F8G08ADADA, MT29F8G16ADADA
+ */
+
+ /* Read JEDEC ID */
+ Status = XNandPsu_OnfiReadId(InstancePtr, 0U, 0x00U, 2U, &JedecId[0]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+
+ if ((JedecId[0] == 0x2CU) &&
+ /* 1 Gb flash devices */
+ ((JedecId[1] == 0xF1U) ||
+ (JedecId[1] == 0xA1U) ||
+ (JedecId[1] == 0xB1U) ||
+ /* 2 Gb flash devices */
+ (JedecId[1] == 0xAAU) ||
+ (JedecId[1] == 0xBAU) ||
+ (JedecId[1] == 0xDAU) ||
+ (JedecId[1] == 0xCAU) ||
+ /* 4 Gb flash devices */
+ (JedecId[1] == 0xACU) ||
+ (JedecId[1] == 0xBCU) ||
+ (JedecId[1] == 0xDCU) ||
+ (JedecId[1] == 0xCCU) ||
+ /* 8 Gb flash devices */
+ (JedecId[1] == 0xA3U) ||
+ (JedecId[1] == 0xB3U) ||
+ (JedecId[1] == 0xD3U) ||
+ (JedecId[1] == 0xC3U))) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Ondie flash detected, jedec id 0x%x 0x%x\r\n",
+ __func__, JedecId[0], JedecId[1]);
+#endif
+ /* On-Die Set Feature */
+ Status = XNandPsu_SetFeature(InstancePtr, 0U, 0x90U,
+ &EccSetFeature[0]);
+ if (Status != XST_SUCCESS) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Ondie set_feature failed\r\n",
+ __func__);
+#endif
+ goto Out;
+ }
+ /* Check to see if ECC feature is set */
+ Status = XNandPsu_GetFeature(InstancePtr, 0U, 0x90U,
+ &EccGetFeature[0]);
+ if (Status != XST_SUCCESS) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Ondie get_feature failed\r\n",
+ __func__);
+#endif
+ goto Out;
+ }
+ if ((EccGetFeature[0] & 0x08U) != 0U) {
+ InstancePtr->Features.OnDie = 1U;
+ Status = XST_SUCCESS;
+ }
+ } else {
+ /* On-Die flash not found */
+ Status = XST_FAILURE;
+ }
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function enables DMA mode of controller operation.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+void XNandPsu_EnableDmaMode(XNandPsu *InstancePtr)
+{
+ /* Assert the input arguments. */
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ InstancePtr->DmaMode = XNANDPSU_MDMA;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function disables DMA mode of driver/controller operation.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+void XNandPsu_DisableDmaMode(XNandPsu *InstancePtr)
+{
+ /* Assert the input arguments. */
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ InstancePtr->DmaMode = XNANDPSU_PIO;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function enables ECC mode of driver/controller operation.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+void XNandPsu_EnableEccMode(XNandPsu *InstancePtr)
+{
+ /* Assert the input arguments. */
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ InstancePtr->EccMode = XNANDPSU_HWECC;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function disables ECC mode of driver/controller operation.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+void XNandPsu_DisableEccMode(XNandPsu *InstancePtr)
+{
+ /* Assert the input arguments. */
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ InstancePtr->EccMode = XNANDPSU_NONE;
+}
+
+#ifdef __rtems__
+#include <rtems/rtems/clock.h>
+static void udelay( void )
+{
+ uint64_t time = rtems_clock_get_uptime_nanoseconds() + 1000;
+ while (1) {
+ uint64_t newtime = rtems_clock_get_uptime_nanoseconds();
+ if (newtime > time) {
+ break;
+ }
+ }
+}
+#define usleep(x) udelay()
+#endif
+
+/*****************************************************************************/
+/**
+*
+* This function polls for a register bit set status till the timeout.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param RegOffset is the offset of register.
+* @param Mask is the bitmask.
+* @param Timeout is the timeout value.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_PollRegTimeout(XNandPsu *InstancePtr, u32 RegOffset,
+ u32 Mask, u32 Timeout)
+{
+ s32 Status = XST_FAILURE;
+ volatile u32 RegVal;
+ u32 TimeoutVar = Timeout;
+
+ while (TimeoutVar > 0U) {
+ RegVal = XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ RegOffset) & Mask;
+ if (RegVal != 0U) {
+ break;
+ }
+ TimeoutVar--;
+ usleep(1);
+ }
+
+ if (TimeoutVar <= 0U) {
+ Status = XST_FAILURE;
+ } else {
+ Status = XST_SUCCESS;
+ }
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sets packet size and packet count values in packet register.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param PktSize is the packet size.
+* @param PktCount is the packet count.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static void XNandPsu_SetPktSzCnt(XNandPsu *InstancePtr, u32 PktSize,
+ u32 PktCount)
+{
+ /* Update Packet Register with pkt size and count */
+ XNandPsu_ReadModifyWrite(InstancePtr, XNANDPSU_PKT_OFFSET,
+ ((u32)XNANDPSU_PKT_PKT_SIZE_MASK |
+ (u32)XNANDPSU_PKT_PKT_CNT_MASK),
+ ((PktSize & XNANDPSU_PKT_PKT_SIZE_MASK) |
+ ((PktCount << XNANDPSU_PKT_PKT_CNT_SHIFT) &
+ XNANDPSU_PKT_PKT_CNT_MASK)));
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sets Page and Column values in the Memory address registers.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Page is the page value.
+* @param Col is the column value.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static void XNandPsu_SetPageColAddr(XNandPsu *InstancePtr, u32 Page, u16 Col)
+{
+ /* Program Memory Address Register 1 */
+ XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XNANDPSU_MEM_ADDR1_OFFSET,
+ (((u32)Col & XNANDPSU_MEM_ADDR1_COL_ADDR_MASK) |
+ ((Page << (u32)XNANDPSU_MEM_ADDR1_PG_ADDR_SHIFT) &
+ XNANDPSU_MEM_ADDR1_PG_ADDR_MASK)));
+ /* Program Memory Address Register 2 */
+ XNandPsu_ReadModifyWrite(InstancePtr, XNANDPSU_MEM_ADDR2_OFFSET,
+ XNANDPSU_MEM_ADDR2_MEM_ADDR_MASK,
+ ((Page >> XNANDPSU_MEM_ADDR1_PG_ADDR_SHIFT) &
+ XNANDPSU_MEM_ADDR2_MEM_ADDR_MASK));
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sets the size of page in Command Register.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static void XNandPsu_SetPageSize(XNandPsu *InstancePtr)
+{
+ u32 PageSizeMask = 0;
+ u32 PageSize = InstancePtr->Geometry.BytesPerPage;
+
+ /* Calculate page size mask */
+ switch(PageSize) {
+ case XNANDPSU_PAGE_SIZE_512:
+ PageSizeMask = (0U << XNANDPSU_CMD_PG_SIZE_SHIFT);
+ break;
+ case XNANDPSU_PAGE_SIZE_2K:
+ PageSizeMask = (1U << XNANDPSU_CMD_PG_SIZE_SHIFT);
+ break;
+ case XNANDPSU_PAGE_SIZE_4K:
+ PageSizeMask = (2U << XNANDPSU_CMD_PG_SIZE_SHIFT);
+ break;
+ case XNANDPSU_PAGE_SIZE_8K:
+ PageSizeMask = (3U << XNANDPSU_CMD_PG_SIZE_SHIFT);
+ break;
+ case XNANDPSU_PAGE_SIZE_16K:
+ PageSizeMask = (4U << XNANDPSU_CMD_PG_SIZE_SHIFT);
+ break;
+ case XNANDPSU_PAGE_SIZE_1K_16BIT:
+ PageSizeMask = (5U << XNANDPSU_CMD_PG_SIZE_SHIFT);
+ break;
+ default:
+ /* Not supported */
+ break;
+ }
+ /* Update Command Register */
+ XNandPsu_ReadModifyWrite(InstancePtr, XNANDPSU_CMD_OFFSET,
+ XNANDPSU_CMD_PG_SIZE_MASK, PageSizeMask);
+}
+
+/*****************************************************************************/
+/**
+*
+* This function setup the Ecc Register.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static void XNandPsu_SetEccAddrSize(XNandPsu *InstancePtr)
+{
+ u32 PageSize = InstancePtr->Geometry.BytesPerPage;
+ u32 CodeWordSize = InstancePtr->Geometry.EccCodeWordSize;
+ u32 NumEccBits = InstancePtr->Geometry.NumBitsECC;
+ u32 Index;
+ u32 Found = 0U;
+ u8 BchModeVal;
+
+ for (Index = 0U; Index < (sizeof(EccMatrix)/sizeof(XNandPsu_EccMatrix));
+ Index++) {
+ if ((EccMatrix[Index].PageSize == PageSize) &&
+ (EccMatrix[Index].CodeWordSize >= CodeWordSize)) {
+ if (EccMatrix[Index].NumEccBits >= NumEccBits) {
+ Found = Index;
+ break;
+ }
+ else {
+ Found = Index;
+ }
+ }
+ }
+
+ if (Found != 0U) {
+ if(InstancePtr->Geometry.SpareBytesPerPage < 64U) {
+ InstancePtr->EccCfg.EccAddr = (u16)PageSize;
+ }
+ else {
+ InstancePtr->EccCfg.EccAddr = ((u16)PageSize +
+ (InstancePtr->Geometry.SpareBytesPerPage
+ - EccMatrix[Found].EccSize));
+ }
+ InstancePtr->EccCfg.EccSize = EccMatrix[Found].EccSize;
+ InstancePtr->EccCfg.NumEccBits = EccMatrix[Found].NumEccBits;
+ InstancePtr->EccCfg.CodeWordSize =
+ EccMatrix[Found].CodeWordSize;
+#ifdef XNANDPSU_DEBUG
+ xil_printf("ECC: addr 0x%x size 0x%x numbits %d "
+ "codesz %d\r\n",
+ InstancePtr->EccCfg.EccAddr,
+ InstancePtr->EccCfg.EccSize,
+ InstancePtr->EccCfg.NumEccBits,
+ InstancePtr->EccCfg.CodeWordSize);
+#endif
+ if (EccMatrix[Found].IsBCH == XNANDPSU_HAMMING) {
+ InstancePtr->EccCfg.IsBCH = 0U;
+ } else {
+ InstancePtr->EccCfg.IsBCH = 1U;
+ }
+ /* Write ECC register */
+ XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ (u32)XNANDPSU_ECC_OFFSET,
+ ((u32)InstancePtr->EccCfg.EccAddr |
+ ((u32)InstancePtr->EccCfg.EccSize << (u32)16) |
+ ((u32)InstancePtr->EccCfg.IsBCH << (u32)27)));
+
+ if (EccMatrix[Found].IsBCH == XNANDPSU_BCH) {
+ /* Write memory address register 2 */
+ switch(InstancePtr->EccCfg.NumEccBits) {
+ case 16U:
+ BchModeVal = 0x0U;
+ break;
+ case 12U:
+ BchModeVal = 0x1U;
+ break;
+ case 8U:
+ BchModeVal = 0x2U;
+ break;
+ case 4U:
+ BchModeVal = 0x3U;
+ break;
+ case 24U:
+ BchModeVal = 0x4U;
+ break;
+ default:
+ BchModeVal = 0x0U;
+ break;
+ }
+ XNandPsu_ReadModifyWrite(InstancePtr,
+ XNANDPSU_MEM_ADDR2_OFFSET,
+ XNANDPSU_MEM_ADDR2_NFC_BCH_MODE_MASK,
+ ((u32)BchModeVal <<
+ (u32)XNANDPSU_MEM_ADDR2_NFC_BCH_MODE_SHIFT));
+ }
+ }
+}
+
+/*****************************************************************************/
+/**
+*
+* This function setup the Ecc Spare Command Register.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static void XNandPsu_SetEccSpareCmd(XNandPsu *InstancePtr, u16 SpareCmd,
+ u8 AddrCycles)
+{
+ XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ (u32)XNANDPSU_ECC_SPR_CMD_OFFSET,
+ (u32)SpareCmd | ((u32)AddrCycles << 28U));
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sets the chip select value in memory address2 register.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Target is the chip select value.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static void XNandPsu_SelectChip(XNandPsu *InstancePtr, u32 Target)
+{
+#if defined (XCLOCKING)
+ Xil_ClockEnable(InstancePtr->Config.RefClk);
+#endif
+ /* Update Memory Address2 register with chip select */
+ XNandPsu_ReadModifyWrite(InstancePtr, XNANDPSU_MEM_ADDR2_OFFSET,
+ XNANDPSU_MEM_ADDR2_CHIP_SEL_MASK,
+ ((Target << XNANDPSU_MEM_ADDR2_CHIP_SEL_SHIFT) &
+ XNANDPSU_MEM_ADDR2_CHIP_SEL_MASK));
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sends ONFI Reset command to the flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Target is the chip select value.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_OnfiReset(XNandPsu *InstancePtr, u32 Target)
+{
+ s32 Status = XST_FAILURE;
+
+ /* Enable Transfer Complete Interrupt in Interrupt Status Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET,
+ XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
+ /* Program Command Register */
+ XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RST, ONFI_CMD_INVALID, 0U,
+ 0U, 0U);
+ /* Program Memory Address Register2 for chip select */
+ XNandPsu_SelectChip(InstancePtr, Target);
+ /* Set Reset in Program Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET, XNANDPSU_PROG_RST_MASK);
+
+ /* Poll for Transfer Complete event */
+ Status = XNandPsu_WaitFor_Transfer_Complete(InstancePtr);
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sends ONFI Read Status command to the flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Target is the chip select value.
+* @param OnfiStatus is the ONFI status value to return.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_OnfiReadStatus(XNandPsu *InstancePtr, u32 Target,
+ u16 *OnfiStatus)
+{
+ s32 Status = XST_FAILURE;
+
+ /* Enable Transfer Complete Interrupt in Interrupt Status Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET,
+ XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
+ /* Program Command Register */
+ XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD_STS, ONFI_CMD_INVALID,
+ 0U, 0U, 0U);
+ /* Program Memory Address Register2 for chip select */
+ XNandPsu_SelectChip(InstancePtr, Target);
+ /* Program Packet Size and Packet Count */
+ if(InstancePtr->DataInterface == XNANDPSU_SDR)
+ XNandPsu_SetPktSzCnt(InstancePtr, 1U, 1U);
+ else
+ XNandPsu_SetPktSzCnt(InstancePtr, 2U, 1U);
+
+ /* Set Read Status in Program Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_STS_MASK);
+ /* Poll for Transfer Complete event */
+ Status = XNandPsu_WaitFor_Transfer_Complete(InstancePtr);
+ /* Read Flash Status */
+ *OnfiStatus = (u16) XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XNANDPSU_FLASH_STS_OFFSET);
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sends ONFI Read ID command to the flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Target is the chip select value.
+* @param Buf is the ONFI ID value to return.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_OnfiReadId(XNandPsu *InstancePtr, u32 Target, u8 IdAddr,
+ u32 IdLen, u8 *Buf)
+{
+ s32 Status = XST_FAILURE;
+ u32 Index;
+ u32 Rem;
+ u32 RegVal;
+ u32 RemIdx;
+
+ u32 *BufPtr = (u32 *)(void *)Buf;
+
+ /*
+ * Enable Buffer Read Ready Interrupt in Interrupt Status Enable
+ * Register
+ */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET,
+ XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
+ /* Program Command */
+ XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD_ID, ONFI_CMD_INVALID, 0U,
+ 0U, ONFI_READ_ID_ADDR_CYCLES);
+
+ /* Program Column, Page, Block address */
+ XNandPsu_SetPageColAddr(InstancePtr, 0U, IdAddr);
+ /* Program Memory Address Register2 for chip select */
+ XNandPsu_SelectChip(InstancePtr, Target);
+ /* Program Packet Size and Packet Count */
+ XNandPsu_SetPktSzCnt(InstancePtr, IdLen, 1U);
+ /* Set Read ID in Program Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_ID_MASK);
+
+ /* Poll for Buffer Read Ready event */
+ Status = XNandPsu_PollRegTimeout(
+ InstancePtr,
+ XNANDPSU_INTR_STS_OFFSET,
+ XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK,
+ XNANDPSU_INTR_POLL_TIMEOUT);
+ if (Status != XST_SUCCESS) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Poll for buf read ready timeout\r\n",
+ __func__);
+#endif
+ goto Out;
+ }
+ /*
+ * Enable Transfer Complete Interrupt in Interrupt
+ * Status Enable Register
+ */
+
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET,
+ XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
+
+ /*
+ * Clear Buffer Read Ready Interrupt in Interrupt Status
+ * Register
+ */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_OFFSET,
+ XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK);
+ /* Read Packet Data from Data Port Register */
+ for (Index = 0U; Index < (IdLen/4); Index++) {
+ *(BufPtr+Index) = XNandPsu_ReadReg(
+ InstancePtr->Config.BaseAddress,
+ XNANDPSU_BUF_DATA_PORT_OFFSET);
+ }
+ Rem = IdLen % 4;
+ if (Rem != 0U) {
+ RegVal = XNandPsu_ReadReg(
+ InstancePtr->Config.BaseAddress,
+ XNANDPSU_BUF_DATA_PORT_OFFSET);
+ for (RemIdx = 0U; RemIdx < Rem; RemIdx++) {
+ *(Buf + (Index * 4U) + RemIdx) = (u8) (RegVal >>
+ (RemIdx * 8U)) & 0xFFU;
+ }
+ }
+
+ Status = XNandPsu_WaitFor_Transfer_Complete(InstancePtr);
+
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sends the ONFI Read Parameter Page command to flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Target is the chip select value.
+* @param PrmIndex is the index of parameter page.
+* @param Buf is the parameter page information to return.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_OnfiReadParamPage(XNandPsu *InstancePtr, u32 Target,
+ u8 *Buf)
+{
+ s32 Status = XST_FAILURE;
+
+ /*
+ * Enable Buffer Read Ready Interrupt in Interrupt Status Enable
+ * Register
+ */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET,
+ XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
+ /* Program Command */
+ XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD_PRM_PG, ONFI_CMD_INVALID,
+ 0U, 0U, ONFI_PRM_PG_ADDR_CYCLES);
+ /* Program Column, Page, Block address */
+ XNandPsu_SetPageColAddr(InstancePtr, 0U, 0U);
+ /* Program Memory Address Register2 for chip select */
+ XNandPsu_SelectChip(InstancePtr, Target);
+ /* Program Packet Size and Packet Count */
+ XNandPsu_SetPktSzCnt(InstancePtr, ONFI_MND_PRM_PGS*ONFI_PRM_PG_LEN, 1U);
+ /* Set Read Parameter Page in Program Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_PRM_PG_MASK);
+
+ Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, 1U, ONFI_MND_PRM_PGS*ONFI_PRM_PG_LEN, 0, 0);
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function returns the length including bad blocks from a given offset and
+* length.
+*
+* @param InstancePtr is the pointer to the XNandPsu instance.
+* @param Offset is the flash data address to read from.
+* @param Length is number of bytes to read.
+*
+* @return
+* - Return actual length including bad blocks.
+*
+* @note None.
+*
+******************************************************************************/
+static s32 XNandPsu_CalculateLength(XNandPsu *InstancePtr, u64 Offset,
+ u64 Length)
+{
+ s32 Status;
+ u32 BlockSize;
+ u32 BlockLen;
+ u32 Block;
+ u64 TempLen = 0;
+ u64 OffsetVar = Offset;
+
+ BlockSize = InstancePtr->Geometry.BlockSize;
+
+ while (TempLen < Length) {
+ Block = (u32)(OffsetVar/BlockSize);
+ BlockLen = BlockSize - (u32)(OffsetVar % BlockSize);
+ if (OffsetVar >= InstancePtr->Geometry.DeviceSize) {
+ Status = XST_FAILURE;
+ goto Out;
+ }
+ /* Check if the block is bad */
+ Status = XNandPsu_IsBlockBad(InstancePtr, Block);
+ if (Status != XST_SUCCESS) {
+ /* Good block */
+ TempLen += BlockLen;
+ }
+ OffsetVar += BlockLen;
+ }
+
+ Status = XST_SUCCESS;
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function writes to the flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Offset is the starting offset of flash to write.
+* @param Length is the number of bytes to write.
+* @param SrcBuf is the source data buffer to write.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+s32 XNandPsu_Write(XNandPsu *InstancePtr, u64 Offset, u64 Length, u8 *SrcBuf)
+{
+ /* Assert the input arguments. */
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+ Xil_AssertNonvoid(SrcBuf != NULL);
+ Xil_AssertNonvoid(Length != 0U);
+ Xil_AssertNonvoid((Offset + Length) <=
+ InstancePtr->Geometry.DeviceSize);
+
+ s32 Status = XST_FAILURE;
+ u32 Page;
+ u32 Col;
+ u32 Target;
+ u32 Block;
+ u32 PartialBytes = 0;
+ u32 NumBytes;
+ u32 RemLen;
+ u8 *BufPtr;
+ u8 *SrcBufPtr = (u8 *)SrcBuf;
+ u64 OffsetVar = Offset;
+ u64 LengthVar = Length;
+
+ /*
+ * Check if write operation exceeds flash size when including
+ * bad blocks.
+ */
+ Status = XNandPsu_CalculateLength(InstancePtr, OffsetVar, LengthVar);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+
+#ifdef __rtems__
+ if (InstancePtr->PartialDataPageIndex != XNANDPSU_PAGE_CACHE_UNAVAILABLE) {
+ /* All writes invalidate the page cache */
+ InstancePtr->PartialDataPageIndex = XNANDPSU_PAGE_CACHE_NONE;
+ }
+#endif
+ while (LengthVar > 0U) {
+ Block = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize);
+ /*
+ * Skip the bad blocks. Increment the offset by block size.
+ * For better results, always program the flash starting at
+ * a block boundary.
+ */
+ if (XNandPsu_IsBlockBad(InstancePtr, Block) == XST_SUCCESS) {
+ OffsetVar += (u64)InstancePtr->Geometry.BlockSize;
+ continue;
+ }
+ /* Calculate Page and Column address values */
+ Page = (u32) (OffsetVar/InstancePtr->Geometry.BytesPerPage);
+ Col = (u32) (OffsetVar &
+ (InstancePtr->Geometry.BytesPerPage - 1U));
+ PartialBytes = 0U;
+ /*
+ * Check if partial write.
+ * If column address is > 0 or Length is < page size
+ */
+ if ((Col > 0U) ||
+ (LengthVar < InstancePtr->Geometry.BytesPerPage)) {
+ RemLen = InstancePtr->Geometry.BytesPerPage - Col;
+ PartialBytes = (RemLen < (u32)LengthVar) ?
+ RemLen : (u32)LengthVar;
+ }
+
+ Target = (u32) (OffsetVar/InstancePtr->Geometry.TargetSize);
+#ifdef __rtems__
+ {
+#else
+ if (Page > InstancePtr->Geometry.NumTargetPages) {
+#endif
+ Page %= InstancePtr->Geometry.NumTargetPages;
+ }
+
+ /* Check if partial write */
+ if (PartialBytes > 0U) {
+ BufPtr = &InstancePtr->PartialDataBuf[0];
+ (void)memset(BufPtr, 0xFF,
+ InstancePtr->Geometry.BytesPerPage);
+ (void)Xil_MemCpy(BufPtr + Col, SrcBufPtr, PartialBytes);
+
+ NumBytes = PartialBytes;
+ } else {
+ BufPtr = (u8 *)SrcBufPtr;
+ NumBytes = (InstancePtr->Geometry.BytesPerPage <
+ (u32)LengthVar) ?
+ InstancePtr->Geometry.BytesPerPage :
+ (u32)LengthVar;
+ }
+ /* Program page */
+ Status = XNandPsu_ProgramPage(InstancePtr, Target, Page, 0U,
+ BufPtr);
+ if (Status != XST_SUCCESS)
+ goto Out;
+
+ Status = XNandPsu_Device_Ready(InstancePtr, Target);
+ if (Status != XST_SUCCESS)
+ goto Out;
+
+ SrcBufPtr += NumBytes;
+ OffsetVar += NumBytes;
+ LengthVar -= NumBytes;
+ }
+
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function reads from the flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Offset is the starting offset of flash to read.
+* @param Length is the number of bytes to read.
+* @param DestBuf is the destination data buffer to fill in.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+s32 XNandPsu_Read(XNandPsu *InstancePtr, u64 Offset, u64 Length, u8 *DestBuf)
+{
+ /* Assert the input arguments. */
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+ Xil_AssertNonvoid(DestBuf != NULL);
+ Xil_AssertNonvoid(Length != 0U);
+ Xil_AssertNonvoid((Offset + Length) <=
+ InstancePtr->Geometry.DeviceSize);
+
+ s32 Status = XST_FAILURE;
+ u32 Page;
+ u32 Col;
+ u32 Target;
+ u32 Block;
+ u32 PartialBytes = 0U;
+ u32 RemLen;
+ u32 NumBytes;
+ u8 *BufPtr;
+ u8 *DestBufPtr = (u8 *)DestBuf;
+ u64 OffsetVar = Offset;
+ u64 LengthVar = Length;
+
+ /*
+ * Check if read operation exceeds flash size when including
+ * bad blocks.
+ */
+ Status = XNandPsu_CalculateLength(InstancePtr, OffsetVar, LengthVar);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+
+ while (LengthVar > 0U) {
+ Block = (u32)(OffsetVar/InstancePtr->Geometry.BlockSize);
+ /*
+ * Skip the bad block. Increment the offset by block size.
+ * The flash programming utility must make sure to start
+ * writing always at a block boundary and skip blocks if any.
+ */
+ if (XNandPsu_IsBlockBad(InstancePtr, Block) == XST_SUCCESS) {
+ OffsetVar += (u64)InstancePtr->Geometry.BlockSize;
+ continue;
+ }
+ /* Calculate Page and Column address values */
+ Page = (u32) (OffsetVar/InstancePtr->Geometry.BytesPerPage);
+ Col = (u32) (OffsetVar &
+ (InstancePtr->Geometry.BytesPerPage - 1U));
+ PartialBytes = 0U;
+ /*
+ * Check if partial write.
+ * If column address is > 0 or Length is < page size
+ */
+ if ((Col > 0U) ||
+ (LengthVar < InstancePtr->Geometry.BytesPerPage)) {
+ RemLen = InstancePtr->Geometry.BytesPerPage - Col;
+ PartialBytes = ((u32)RemLen < (u32)LengthVar) ?
+ (u32)RemLen : (u32)LengthVar;
+ }
+
+ Target = (u32) (OffsetVar/InstancePtr->Geometry.TargetSize);
+#ifdef __rtems__
+ {
+#else
+ if (Page > InstancePtr->Geometry.NumTargetPages) {
+#endif
+ Page %= InstancePtr->Geometry.NumTargetPages;
+ }
+ /* Check if partial read */
+ if (PartialBytes > 0U) {
+ BufPtr = &InstancePtr->PartialDataBuf[0];
+ NumBytes = PartialBytes;
+ } else {
+ BufPtr = DestBufPtr;
+ NumBytes = (InstancePtr->Geometry.BytesPerPage <
+ (u32)LengthVar) ?
+ InstancePtr->Geometry.BytesPerPage :
+ (u32)LengthVar;
+ }
+#ifdef __rtems__
+ if (Page == InstancePtr->PartialDataPageIndex) {
+ /*
+ * This is a whole page read for the currently cached
+ * page. It will not be taken care of below, so perform
+ * the copy here.
+ */
+ if (PartialBytes == 0U) {
+ (void)Xil_MemCpy(DestBufPtr,
+ &InstancePtr->PartialDataBuf[0],
+ NumBytes);
+ }
+ } else {
+#endif
+ /* Read page */
+ Status = XNandPsu_ReadPage(InstancePtr, Target, Page, 0U,
+ BufPtr);
+#ifdef __rtems__
+ if (PartialBytes > 0U &&
+ InstancePtr->PartialDataPageIndex != XNANDPSU_PAGE_CACHE_UNAVAILABLE) {
+ /*
+ * Partial read into page cache. Update the
+ * cached page index.
+ */
+ InstancePtr->PartialDataPageIndex = Page;
+ }
+ }
+#endif
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ if (PartialBytes > 0U) {
+ (void)Xil_MemCpy(DestBufPtr, BufPtr + Col, NumBytes);
+#ifdef __rtems__
+ /* The destination buffer is touched by hardware, synchronize */
+ if (InstancePtr->Config.IsCacheCoherent == 0) {
+ Xil_DCacheFlushRange((INTPTR)(void *)DestBufPtr, NumBytes);
+ }
+#endif
+ }
+ DestBufPtr += NumBytes;
+ OffsetVar += NumBytes;
+ LengthVar -= NumBytes;
+ }
+
+ Status = XST_SUCCESS;
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function erases the flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Offset is the starting offset of flash to erase.
+* @param Length is the number of bytes to erase.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note
+* The Offset and Length should be aligned to block size boundary
+* to get better results.
+*
+******************************************************************************/
+s32 XNandPsu_Erase(XNandPsu *InstancePtr, u64 Offset, u64 Length)
+{
+ /* Assert the input arguments. */
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+ Xil_AssertNonvoid(Length != 0U);
+ Xil_AssertNonvoid((Offset + Length) <=
+ InstancePtr->Geometry.DeviceSize);
+
+ s32 Status = XST_FAILURE;
+ u32 Target = 0;
+ u32 StartBlock;
+ u32 NumBlocks = 0;
+ u32 Block;
+ u32 AlignOff;
+ u32 EraseLen;
+ u32 BlockRemLen;
+ u64 OffsetVar = Offset;
+ u64 LengthVar = Length;
+
+ /*
+ * Check if erase operation exceeds flash size when including
+ * bad blocks.
+ */
+ Status = XNandPsu_CalculateLength(InstancePtr, OffsetVar, LengthVar);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ /* Calculate number of blocks to erase */
+ StartBlock = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize);
+
+ while (LengthVar > 0U) {
+ Block = (u32) (OffsetVar/InstancePtr->Geometry.BlockSize);
+ if (XNandPsu_IsBlockBad(InstancePtr, Block) ==
+ XST_SUCCESS) {
+ OffsetVar += (u64)InstancePtr->Geometry.BlockSize;
+ NumBlocks++;
+ continue;
+ }
+
+ AlignOff = (u32)OffsetVar &
+ (InstancePtr->Geometry.BlockSize - (u32)1);
+ if (AlignOff > 0U) {
+ BlockRemLen = InstancePtr->Geometry.BlockSize -
+ AlignOff;
+ EraseLen = (BlockRemLen < (u32)LengthVar) ?
+ BlockRemLen :(u32)LengthVar;
+ } else {
+ EraseLen = (InstancePtr->Geometry.BlockSize <
+ (u32)LengthVar) ?
+ InstancePtr->Geometry.BlockSize:
+ (u32)LengthVar;
+ }
+ NumBlocks++;
+ OffsetVar += EraseLen;
+ LengthVar -= EraseLen;
+ }
+
+ for (Block = StartBlock; Block < (StartBlock + NumBlocks); Block++) {
+ Target = Block/InstancePtr->Geometry.NumTargetBlocks;
+#ifdef __rtems__
+ u32 ModBlock = Block % InstancePtr->Geometry.NumTargetBlocks;
+#else
+ Block %= InstancePtr->Geometry.NumTargetBlocks;
+#endif
+ /* Don't erase bad block */
+ if (XNandPsu_IsBlockBad(InstancePtr, Block) ==
+ XST_SUCCESS)
+ continue;
+ /* Block Erase */
+#ifdef __rtems__
+ Status = XNandPsu_EraseBlock(InstancePtr, Target, ModBlock);
+#else
+ Status = XNandPsu_EraseBlock(InstancePtr, Target, Block);
+#endif
+ if (Status != XST_SUCCESS)
+ goto Out;
+
+ Status = XNandPsu_Device_Ready(InstancePtr, Target);
+ if (Status != XST_SUCCESS)
+ goto Out;
+
+ }
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sends ONFI Program Page command to flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Target is the chip select value.
+* @param Page is the page address value to program.
+* @param Col is the column address value to program.
+* @param Buf is the data buffer to program.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_ProgramPage(XNandPsu *InstancePtr, u32 Target, u32 Page,
+ u32 Col, u8 *Buf)
+{
+ u32 PktSize;
+ u32 PktCount;
+ s32 Status = XST_FAILURE;
+ u32 IsrValue;
+ u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles +
+ InstancePtr->Geometry.ColAddrCycles;
+
+ if (InstancePtr->EccCfg.CodeWordSize > 9U) {
+ PktSize = 1024U;
+ } else {
+ PktSize = 512U;
+ }
+ PktCount = InstancePtr->Geometry.BytesPerPage/PktSize;
+
+ XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_PG_PROG1, ONFI_CMD_PG_PROG2,
+ 1U, 1U, (u8)AddrCycles);
+
+ if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
+ IsrValue = XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK |
+ XNANDPSU_INTR_STS_EN_DMA_INT_STS_EN_MASK;
+ if (InstancePtr->Config.IsCacheCoherent == 0) {
+ Xil_DCacheFlushRange((INTPTR)(void *)Buf, (PktSize * PktCount));
+ }
+ XNandPsu_Update_DmaAddr(InstancePtr, Buf);
+ } else {
+ IsrValue = XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK;
+ }
+
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET, IsrValue);
+ /* Program Page Size */
+ XNandPsu_SetPageSize(InstancePtr);
+ /* Program Packet Size and Packet Count */
+ XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
+ /* Program Column, Page, Block address */
+ XNandPsu_SetPageColAddr(InstancePtr, Page, (u16)Col);
+ /* Program Memory Address Register2 for chip select */
+ XNandPsu_SelectChip(InstancePtr, Target);
+ /* Set ECC */
+ if (InstancePtr->EccMode == XNANDPSU_HWECC) {
+ XNandPsu_SetEccSpareCmd(InstancePtr, ONFI_CMD_CHNG_WR_COL,
+ InstancePtr->Geometry.ColAddrCycles);
+ }
+ /* Set Page Program in Program Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_PG_PROG_MASK);
+
+
+ Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 1, 1);
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sends ONFI Program Page command to flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Page is the page address value to program.
+* @param Buf is the data buffer to program.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+s32 XNandPsu_WriteSpareBytes(XNandPsu *InstancePtr, u32 Page, u8 *Buf)
+{
+ /* Assert the input arguments. */
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+ Xil_AssertNonvoid(Page < InstancePtr->Geometry.NumPages);
+ Xil_AssertNonvoid(Buf != NULL);
+
+ u32 PktCount = 1U;
+ u16 PreEccSpareCol = 0U;
+ u16 PreEccSpareWrCnt = 0U;
+ u16 PostEccSpareCol = 0U;
+ u16 PostEccSpareWrCnt = 0U;
+ u32 PostWrite = 0U;
+ OnfiCmdFormat Cmd;
+ s32 Status = XST_FAILURE;
+ u32 RegVal;
+ u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles +
+ InstancePtr->Geometry.ColAddrCycles;
+ u32 Col = InstancePtr->Geometry.BytesPerPage;
+ u32 Target = Page/InstancePtr->Geometry.NumTargetPages;
+ u32 PktSize = InstancePtr->Geometry.SpareBytesPerPage;
+ u32 *BufPtr = (u32 *)(void *)Buf;
+ u32 PageVar = Page;
+
+ PageVar %= InstancePtr->Geometry.NumTargetPages;
+
+ if (InstancePtr->EccMode == XNANDPSU_HWECC) {
+ /* Calculate ECC free positions before and after ECC code */
+ PreEccSpareCol = 0x0U;
+ PreEccSpareWrCnt = InstancePtr->EccCfg.EccAddr -
+ (u16)InstancePtr->Geometry.BytesPerPage;
+
+ PostEccSpareCol = PreEccSpareWrCnt +
+ InstancePtr->EccCfg.EccSize;
+ PostEccSpareWrCnt = InstancePtr->Geometry.SpareBytesPerPage -
+ PostEccSpareCol;
+
+ PreEccSpareWrCnt = (PreEccSpareWrCnt/4U) * 4U;
+ PostEccSpareWrCnt = (PostEccSpareWrCnt/4U) * 4U;
+
+ if (PreEccSpareWrCnt > 0U) {
+ PktSize = PreEccSpareWrCnt;
+ PktCount = 1U;
+ Col = InstancePtr->Geometry.BytesPerPage +
+ PreEccSpareCol;
+ BufPtr = (u32 *)(void *)Buf;
+ if (PostEccSpareWrCnt > 0U) {
+ PostWrite = 1U;
+ }
+ } else if (PostEccSpareWrCnt > 0U) {
+ PktSize = PostEccSpareWrCnt;
+ PktCount = 1U;
+ Col = InstancePtr->Geometry.BytesPerPage +
+ PostEccSpareCol;
+ BufPtr = (u32 *)(Buf + Col);
+ } else {
+ /* No free spare bytes available for writing */
+ Status = XST_FAILURE;
+ goto Out;
+ }
+ }
+
+ if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
+ RegVal = XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK;
+ if (InstancePtr->Config.IsCacheCoherent == 0) {
+ Xil_DCacheFlushRange((INTPTR)(void *)BufPtr, (PktSize * PktCount));
+ }
+ XNandPsu_Update_DmaAddr(InstancePtr, (u8 *)BufPtr);
+ } else {
+ RegVal = XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK;
+ }
+
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET, RegVal);
+ /* Program Command hack for change write column */
+ if (PostWrite > 0U) {
+ Cmd.Command1 = 0x80U;
+ Cmd.Command2 = 0x00U;
+ XNandPsu_Prepare_Cmd(InstancePtr, Cmd.Command1, Cmd.Command2,
+ 0U , 1U, (u8)AddrCycles);
+
+ } else {
+ XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_PG_PROG1,
+ ONFI_CMD_PG_PROG2, 0U , 1U, (u8)AddrCycles);
+ }
+ /* Program Page Size */
+ XNandPsu_SetPageSize(InstancePtr);
+ /* Program Packet Size and Packet Count */
+ XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
+ /* Program Column, Page, Block address */
+ XNandPsu_SetPageColAddr(InstancePtr, PageVar, (u16)Col);
+ /* Program Memory Address Register2 for chip select */
+ XNandPsu_SelectChip(InstancePtr, Target);
+ /* Set Page Program in Program Register */
+ if (PostWrite > 0U) {
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET,((u32)XNANDPSU_PROG_PG_PROG_MASK |
+ (u32)XNANDPSU_PROG_CHNG_ROW_ADDR_MASK));
+ } else {
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_PG_PROG_MASK);
+ }
+
+ Status = XNandPsu_Data_ReadWrite(InstancePtr, (u8 *)BufPtr, PktCount,
+ PktSize, 1, 1);
+
+ if (InstancePtr->EccMode == XNANDPSU_HWECC) {
+ if (PostWrite > 0U) {
+ BufPtr = (u32 *)(Buf + PostEccSpareCol);
+ Status = XNandPsu_ChangeWriteColumn(InstancePtr,
+ Target,
+ PostEccSpareCol, PostEccSpareWrCnt, 1U,
+ (u8 *)(void *)BufPtr);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ }
+ }
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sends ONFI Read Page command to flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Target is the chip select value.
+* @param Page is the page address value to read.
+* @param Col is the column address value to read.
+* @param Buf is the data buffer to fill in.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_ReadPage(XNandPsu *InstancePtr, u32 Target, u32 Page,
+ u32 Col, u8 *Buf)
+{
+ u32 PktSize;
+ u32 PktCount;
+ s32 Status = XST_FAILURE;
+ u32 RegVal;
+ u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles +
+ InstancePtr->Geometry.ColAddrCycles;
+
+ if (InstancePtr->EccCfg.CodeWordSize > 9U) {
+ PktSize = 1024U;
+ } else {
+ PktSize = 512U;
+ }
+ PktCount = InstancePtr->Geometry.BytesPerPage/PktSize;
+
+ XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD1, ONFI_CMD_RD2,
+ 1U, 1U, (u8)AddrCycles);
+
+ if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
+ RegVal = XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK |
+ XNANDPSU_INTR_STS_EN_DMA_INT_STS_EN_MASK;
+ if (InstancePtr->Config.IsCacheCoherent == 0) {
+ Xil_DCacheInvalidateRange((INTPTR)(void *)Buf, (PktSize * PktCount));
+ }
+ XNandPsu_Update_DmaAddr(InstancePtr, Buf);
+ } else {
+ RegVal = XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK;
+ }
+ /* Enable Single bit error and Multi bit error */
+ if (InstancePtr->EccMode == XNANDPSU_HWECC)
+ RegVal |= XNANDPSU_INTR_STS_EN_MUL_BIT_ERR_STS_EN_MASK |
+ XNANDPSU_INTR_STS_EN_ERR_INTR_STS_EN_MASK;
+
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET, RegVal);
+ /* Program Page Size */
+ XNandPsu_SetPageSize(InstancePtr);
+ /* Program Column, Page, Block address */
+ XNandPsu_SetPageColAddr(InstancePtr, Page, (u16)Col);
+ /* Program Packet Size and Packet Count */
+ XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
+ /* Program Memory Address Register2 for chip select */
+ XNandPsu_SelectChip(InstancePtr, Target);
+ /* Set ECC */
+ if (InstancePtr->EccMode == XNANDPSU_HWECC) {
+ XNandPsu_SetEccSpareCmd(InstancePtr,
+ (ONFI_CMD_CHNG_RD_COL1 |
+ (ONFI_CMD_CHNG_RD_COL2 << (u8)8U)),
+ InstancePtr->Geometry.ColAddrCycles);
+ }
+
+ /* Set Read command in Program Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_MASK);
+
+ Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 0, 1);
+
+#ifdef __rtems__
+ if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
+ if (InstancePtr->Config.IsCacheCoherent == 0) {
+ Xil_DCacheInvalidateRange((INTPTR)(void *)Buf, (PktSize * PktCount));
+ }
+ }
+#endif
+
+ /* Check ECC Errors */
+ if (InstancePtr->EccMode == XNANDPSU_HWECC) {
+ /* Hamming Multi Bit Errors */
+ if (((u32)XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XNANDPSU_INTR_STS_OFFSET) &
+ (u32)XNANDPSU_INTR_STS_MUL_BIT_ERR_STS_EN_MASK) != 0U) {
+
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_OFFSET,
+ XNANDPSU_INTR_STS_MUL_BIT_ERR_STS_EN_MASK);
+
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: ECC Hamming multi bit error\r\n",
+ __func__);
+#endif
+ InstancePtr->Ecc_Stat_PerPage_flips =
+ ((XNandPsu_ReadReg(
+ InstancePtr->Config.BaseAddress,
+ XNANDPSU_ECC_ERR_CNT_OFFSET) &
+ 0x1FF00U) >> 8U);
+ InstancePtr->Ecc_Stats_total_flips +=
+ InstancePtr->Ecc_Stat_PerPage_flips;
+ Status = XST_FAILURE;
+ }
+ /* Hamming Single Bit or BCH Errors */
+ if (((u32)XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XNANDPSU_INTR_STS_OFFSET) &
+ (u32)XNANDPSU_INTR_STS_ERR_INTR_STS_EN_MASK) != 0U) {
+
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_OFFSET,
+ XNANDPSU_INTR_STS_ERR_INTR_STS_EN_MASK);
+
+ if (InstancePtr->EccCfg.IsBCH == 1U) {
+ InstancePtr->Ecc_Stat_PerPage_flips =
+ ((XNandPsu_ReadReg(
+ InstancePtr->Config.BaseAddress,
+ XNANDPSU_ECC_ERR_CNT_OFFSET)&
+ 0x1FF00U) >> 8U);
+ InstancePtr->Ecc_Stats_total_flips +=
+ InstancePtr->Ecc_Stat_PerPage_flips;
+ Status = XST_SUCCESS;
+ }
+ }
+ }
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function reads spare bytes from flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Page is the page address value to read.
+* @param Buf is the data buffer to fill in.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+s32 XNandPsu_ReadSpareBytes(XNandPsu *InstancePtr, u32 Page, u8 *Buf)
+{
+ /* Assert the input arguments. */
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+ Xil_AssertNonvoid(Page < InstancePtr->Geometry.NumPages);
+ Xil_AssertNonvoid(Buf != NULL);
+
+ u32 PktCount = 1U;
+ s32 Status = XST_FAILURE;
+ u32 RegVal;
+ u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles +
+ InstancePtr->Geometry.ColAddrCycles;
+ u32 Col = InstancePtr->Geometry.BytesPerPage;
+ u32 Target = Page/InstancePtr->Geometry.NumTargetPages;
+ u32 PktSize = InstancePtr->Geometry.SpareBytesPerPage;
+ u32 PageVar = Page;
+
+ PageVar %= InstancePtr->Geometry.NumTargetPages;
+
+ if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
+ RegVal = XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK;
+ if (InstancePtr->Config.IsCacheCoherent == 0) {
+ Xil_DCacheInvalidateRange((INTPTR)(void *)Buf, (PktSize * PktCount));
+ }
+ XNandPsu_Update_DmaAddr(InstancePtr, Buf);
+ } else {
+ RegVal = XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK;
+ }
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET, RegVal);
+ /* Program Command */
+ XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_RD1, ONFI_CMD_RD2, 0U,
+ 1U, (u8)AddrCycles);
+ /* Program Page Size */
+ XNandPsu_SetPageSize(InstancePtr);
+ /* Program Column, Page, Block address */
+ XNandPsu_SetPageColAddr(InstancePtr, PageVar, (u16)Col);
+ /* Program Packet Size and Packet Count */
+ XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
+ /* Program Memory Address Register2 for chip select */
+ XNandPsu_SelectChip(InstancePtr, Target);
+ /* Set Read command in Program Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_MASK);
+
+ Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 0, 1);
+
+#ifdef __rtems__
+ if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
+ if (InstancePtr->Config.IsCacheCoherent == 0) {
+ Xil_DCacheInvalidateRange((INTPTR)(void *)Buf, (PktSize * PktCount));
+ }
+ }
+#endif
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sends ONFI block erase command to the flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Target is the chip select value.
+* @param Block is the block to erase.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+s32 XNandPsu_EraseBlock(XNandPsu *InstancePtr, u32 Target, u32 Block)
+{
+ /* Assert the input arguments. */
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+ Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
+#ifdef __rtems__
+ Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumTargetBlocks);
+#else
+ Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks);
+#endif
+
+ s32 Status = XST_FAILURE;
+ u32 Page;
+ u32 ErasePage;
+ u32 EraseCol;
+ u32 AddrCycles = InstancePtr->Geometry.RowAddrCycles;
+
+ Page = Block * InstancePtr->Geometry.PagesPerBlock;
+ ErasePage = (Page >> 16U) & 0xFFFFU;
+ EraseCol = Page & 0xFFFFU;
+
+ /*
+ * Enable Transfer Complete Interrupt in Interrupt Status Enable
+ * Register
+ */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET,
+ XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
+
+ /* Program Command */
+ XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_BLK_ERASE1,
+ ONFI_CMD_BLK_ERASE2, 0U , 0U, (u8)AddrCycles);
+ /* Program Column, Page, Block address */
+ XNandPsu_SetPageColAddr(InstancePtr, ErasePage, (u16)EraseCol);
+ /* Program Memory Address Register2 for chip select */
+ XNandPsu_SelectChip(InstancePtr, Target);
+ /* Set Block Erase in Program Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_BLK_ERASE_MASK);
+ /* Poll for Transfer Complete event */
+ Status = XNandPsu_WaitFor_Transfer_Complete(InstancePtr);
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sends ONFI Get Feature command to flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Target is the chip select value.
+* @param Feature is the feature selector.
+* @param Buf is the buffer to fill feature value.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+s32 XNandPsu_GetFeature(XNandPsu *InstancePtr, u32 Target, u8 Feature,
+ u8 *Buf)
+{
+ /* Assert the input arguments. */
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY)
+ Xil_AssertNonvoid(Buf != NULL);
+ Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
+
+ s32 Status;
+ u32 PktSize = 4;
+ u32 PktCount = 1;
+
+ if (InstancePtr->DataInterface == XNANDPSU_NVDDR) {
+ PktSize = 8U;
+ }
+
+ /*
+ * Enable Buffer Read Ready Interrupt in Interrupt Status
+ * Enable Register
+ */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET,
+ XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK);
+ /* Program Command */
+ XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_GET_FEATURES,
+ ONFI_CMD_INVALID, 0U, 0U, 1U);
+ /* Program Column, Page, Block address */
+ XNandPsu_SetPageColAddr(InstancePtr, 0x0U, Feature);
+ /* Program Memory Address Register2 for chip select */
+ XNandPsu_SelectChip(InstancePtr, Target);
+ /* Program Packet Size and Packet Count */
+ XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
+ /* Set Read Parameter Page in Program Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_GET_FEATURES_MASK);
+
+ Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 0, 0);
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sends ONFI Set Feature command to flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Target is the chip select value.
+* @param Feature is the feature selector.
+* @param Buf is the feature value to send.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+s32 XNandPsu_SetFeature(XNandPsu *InstancePtr, u32 Target, u8 Feature,
+ u8 *Buf)
+{
+ /* Assert the input arguments. */
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY)
+ Xil_AssertNonvoid(Buf != NULL);
+ Xil_AssertNonvoid(Target < XNANDPSU_MAX_TARGETS);
+
+ s32 Status;
+ u32 PktSize = 4U;
+ u32 PktCount = 1U;
+
+ if (InstancePtr->DataInterface == XNANDPSU_NVDDR) {
+ PktSize = 8U;
+ }
+
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET, 0U);
+
+ /*
+ * Enable Buffer Write Ready Interrupt in Interrupt Status
+ * Enable Register
+ */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET,
+ XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK);
+
+ /* Program Command */
+ XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_SET_FEATURES,
+ ONFI_CMD_INVALID, 0U , 0U, 1U);
+ /* Program Column, Page, Block address */
+ XNandPsu_SetPageColAddr(InstancePtr, 0x0U, Feature);
+ /* Program Memory Address Register2 for chip select */
+ XNandPsu_SelectChip(InstancePtr, Target);
+ /* Program Packet Size and Packet Count */
+ XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
+ /* Set Read Parameter Page in Program Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_SET_FEATURES_MASK);
+
+ Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 1, 0);
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function changes clock frequency of flash controller.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param ClockFreq is the clock frequency to change.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static void XNandPsu_ChangeClockFreq(XNandPsu *InstancePtr, u32 ClockFreq)
+{
+ (void) InstancePtr;
+ (void) ClockFreq;
+
+ /* Not implemented */
+}
+/*****************************************************************************/
+/**
+*
+* This function changes the data interface and timing mode.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param NewIntf is the new data interface.
+* @param NewMode is the new timing mode.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+s32 XNandPsu_ChangeTimingMode(XNandPsu *InstancePtr,
+ XNandPsu_DataInterface NewIntf,
+ XNandPsu_TimingMode NewMode)
+{
+ /* Assert the input arguments. */
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ s32 Status = XST_SUCCESS;
+ u32 Target;
+ u32 RegVal;
+ u8 Buf[4] = {0U};
+ u32 *Feature = (u32 *)(void *)&Buf[0];
+ u32 SetFeature = 0U;
+ u32 NewModeVar = (u32)NewMode;
+
+ /* Check for valid input arguments */
+ if(((NewIntf != XNANDPSU_SDR) && (NewIntf != XNANDPSU_NVDDR)) ||
+ (NewModeVar > 5U)){
+ Status = XST_FAILURE;
+ goto Out;
+ }
+
+ if(NewIntf == XNANDPSU_NVDDR){
+ NewModeVar = NewModeVar | (u32)0x10;
+ }
+ /* Get current data interface type and timing mode */
+ XNandPsu_DataInterface CurIntf = InstancePtr->DataInterface;
+ XNandPsu_TimingMode CurMode = InstancePtr->TimingMode;
+
+ /* Check if the flash is in same mode */
+ if ((CurIntf == NewIntf) && (CurMode == NewModeVar)) {
+ Status = XST_SUCCESS;
+ goto Out;
+ }
+
+ if ((CurIntf == XNANDPSU_NVDDR) && (NewIntf == XNANDPSU_SDR)) {
+
+ NewModeVar = XNANDPSU_SDR0;
+
+ /* Change the clock frequency */
+ XNandPsu_ChangeClockFreq(InstancePtr, XNANDPSU_SDR_CLK);
+
+ /* Update Data Interface Register */
+ RegVal = ((NewModeVar % 6U) << ((NewIntf == XNANDPSU_NVDDR) ? 3U : 0U)) |
+ ((u32)NewIntf << XNANDPSU_DATA_INTF_DATA_INTF_SHIFT);
+ XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XNANDPSU_DATA_INTF_OFFSET, RegVal);
+
+ for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
+ Target++) {
+ Status = XNandPsu_OnfiReset(InstancePtr, Target);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ }
+
+ /* Set Feature */
+ for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
+ Target++) {
+ Status = XNandPsu_SetFeature(InstancePtr, Target, 0x01U,
+ (u8 *)(void *)&NewModeVar);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ }
+
+ InstancePtr->DataInterface = NewIntf;
+ InstancePtr->TimingMode = NewModeVar;
+
+ for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
+ Target++) {
+ Status = XNandPsu_GetFeature(InstancePtr, Target, 0x01U,
+ &Buf[0]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ /* Check if set_feature was successful */
+ if (*Feature != NewModeVar) {
+ Status = XST_FAILURE;
+ goto Out;
+ }
+ }
+
+ goto Out;
+ }
+
+ SetFeature = NewModeVar;
+ if((CurIntf == XNANDPSU_NVDDR) && (NewIntf == XNANDPSU_NVDDR)){
+ SetFeature |= SetFeature << 8U;
+ }
+ /* Set Feature */
+ for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
+ Target++) {
+ Status = XNandPsu_SetFeature(InstancePtr, Target, 0x01U,
+ (u8 *)(void *)&SetFeature);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ }
+
+ InstancePtr->DataInterface = NewIntf;
+ InstancePtr->TimingMode = NewModeVar;
+ /* Update Data Interface Register */
+ RegVal = ((NewMode % 6U) << ((NewIntf == XNANDPSU_NVDDR) ? 3U : 0U)) |
+ ((u32)NewIntf << XNANDPSU_DATA_INTF_DATA_INTF_SHIFT);
+ XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XNANDPSU_DATA_INTF_OFFSET, RegVal);
+
+ /* Get Feature */
+ for (Target = 0U; Target < InstancePtr->Geometry.NumTargets;
+ Target++) {
+ Status = XNandPsu_GetFeature(InstancePtr, Target, 0x01U,
+ &Buf[0]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+
+ /* Check if set_feature was successful */
+ if (*Feature != NewModeVar) {
+ Status = XST_FAILURE;
+ goto Out;
+ }
+ }
+
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function issues change read column and reads the data into buffer
+* specified by user.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Target is the chip select value.
+* @param Col is the coulmn address.
+* @param PktSize is the number of bytes to read.
+* @param PktCount is the number of transactions to read.
+* @param Buf is the data buffer to fill in.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_ChangeReadColumn(XNandPsu *InstancePtr, u32 Target,
+ u32 Col, u32 PktSize, u32 PktCount,
+ u8 *Buf)
+{
+ s32 Status = XST_FAILURE;
+ u32 RegVal;
+ u32 AddrCycles = InstancePtr->Geometry.ColAddrCycles;
+
+ if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
+ RegVal = XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK |
+ XNANDPSU_INTR_STS_EN_DMA_INT_STS_EN_MASK;
+ Xil_DCacheInvalidateRange((INTPTR)(void *)Buf, (PktSize * PktCount));
+ XNandPsu_Update_DmaAddr(InstancePtr, Buf);
+ } else {
+ RegVal = XNANDPSU_INTR_STS_EN_BUFF_RD_RDY_STS_EN_MASK;
+ }
+
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET, RegVal);
+ /* Program Command */
+ XNandPsu_Prepare_Cmd(InstancePtr, ONFI_CMD_CHNG_RD_COL1,
+ ONFI_CMD_CHNG_RD_COL2, 0U , 1U, (u8)AddrCycles);
+ /* Program Page Size */
+ XNandPsu_SetPageSize(InstancePtr);
+ /* Program Column, Page, Block address */
+ XNandPsu_SetPageColAddr(InstancePtr, 0U, (u16)Col);
+ /* Program Packet Size and Packet Count */
+ XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
+ /* Program Memory Address Register2 for chip select */
+ XNandPsu_SelectChip(InstancePtr, Target);
+ /* Set Read command in Program Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_RD_MASK);
+
+ Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 0, 1);
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function issues change read column and reads the data into buffer
+* specified by user.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Target is the chip select value.
+* @param Col is the coulmn address.
+* @param PktSize is the number of bytes to read.
+* @param PktCount is the number of transactions to read.
+* @param Buf is the data buffer to fill in.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_ChangeWriteColumn(XNandPsu *InstancePtr, u32 Target,
+ u32 Col, u32 PktSize, u32 PktCount,
+ u8 *Buf)
+{
+ s32 Status = XST_FAILURE;
+ OnfiCmdFormat OnfiCommand;
+ u32 RegVal;
+ u32 AddrCycles = InstancePtr->Geometry.ColAddrCycles;
+
+ if (PktCount == 0U) {
+ return XST_SUCCESS;
+ }
+
+ if (InstancePtr->DmaMode == XNANDPSU_MDMA) {
+ RegVal = XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK |
+ XNANDPSU_INTR_STS_EN_DMA_INT_STS_EN_MASK;
+#ifdef __rtems__
+ if (InstancePtr->Config.IsCacheCoherent == 0) {
+ Xil_DCacheFlushRange((INTPTR)(void *)Buf, (PktSize * PktCount));
+ }
+#endif
+ XNandPsu_Update_DmaAddr(InstancePtr, Buf);
+ } else {
+ RegVal = XNANDPSU_INTR_STS_EN_BUFF_WR_RDY_STS_EN_MASK;
+ }
+
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET, RegVal);
+ /* Change write column hack */
+ OnfiCommand.Command1 = 0x85U;
+ OnfiCommand.Command2 = 0x10U;
+ XNandPsu_Prepare_Cmd(InstancePtr, OnfiCommand.Command1,
+ OnfiCommand.Command2, 0U , 0U, (u8)AddrCycles);
+
+ /* Program Page Size */
+ XNandPsu_SetPageSize(InstancePtr);
+ /* Program Column, Page, Block address */
+ XNandPsu_SetPageColAddr(InstancePtr, 0U, (u16)Col);
+ /* Program Packet Size and Packet Count */
+ XNandPsu_SetPktSzCnt(InstancePtr, PktSize, PktCount);
+ /* Program Memory Address Register2 for chip select */
+ XNandPsu_SelectChip(InstancePtr, Target);
+ /* Set Page Program in Program Register */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_PROG_OFFSET,XNANDPSU_PROG_CHNG_ROW_ADDR_END_MASK);
+
+ Status = XNandPsu_Data_ReadWrite(InstancePtr, Buf, PktCount, PktSize, 1, 0);
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function initializes extended parameter page ECC information.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param ExtPrm is the Extended parameter page buffer.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_InitExtEcc(XNandPsu *InstancePtr, OnfiExtPrmPage *ExtPrm)
+{
+ s32 Status = XST_FAILURE;
+ u32 Offset = 0U;
+ u32 Found = 0U;
+ OnfiExtEccBlock *EccBlock;
+
+ if (ExtPrm->Section0Type != 0x2U) {
+ Offset += (u32)ExtPrm->Section0Len;
+ if (ExtPrm->Section1Type != 0x2U) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Extended ECC section not found\r\n",__func__);
+#endif
+ Status = XST_FAILURE;
+ } else {
+ Found = 1U;
+ }
+ } else {
+ Found = 1U;
+ }
+
+ if (Found != 0U) {
+ EccBlock = (OnfiExtEccBlock *)&ExtPrm->SectionData[Offset];
+ Xil_AssertNonvoid(EccBlock != NULL);
+ if (EccBlock->CodeWordSize == 0U) {
+ Status = XST_FAILURE;
+ } else {
+ InstancePtr->Geometry.NumBitsECC =
+ EccBlock->NumEccBits;
+ InstancePtr->Geometry.EccCodeWordSize =
+ (u32)EccBlock->CodeWordSize;
+ Status = XST_SUCCESS;
+ }
+ }
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function prepares command to be written into command register.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Cmd1 is the first Onfi Command.
+* @param Cmd2 is the second Onfi Command.
+* @param EccState is the flag to set Ecc State.
+* @param DmaMode is the flag to set DMA mode.
+* @param AddrCycles is the number of Address Cycles.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+void XNandPsu_Prepare_Cmd(XNandPsu *InstancePtr, u8 Cmd1, u8 Cmd2, u8 EccState,
+ u8 DmaMode, u8 AddrCycles)
+{
+ Xil_AssertVoid(InstancePtr != NULL);
+
+ u32 RegValue = 0U;
+
+ RegValue = (u32)Cmd1 | (((u32)Cmd2 << (u32)XNANDPSU_CMD_CMD2_SHIFT) &
+ (u32)XNANDPSU_CMD_CMD2_MASK);
+
+ if ((EccState != 0U) && (InstancePtr->EccMode == XNANDPSU_HWECC)) {
+ RegValue |= 1U << XNANDPSU_CMD_ECC_ON_SHIFT;
+ }
+
+ if ((DmaMode != 0U) && (InstancePtr->DmaMode == XNANDPSU_MDMA)) {
+ RegValue |= XNANDPSU_MDMA << XNANDPSU_CMD_DMA_EN_SHIFT;
+ }
+
+ if (AddrCycles != 0U) {
+ RegValue |= (u32)AddrCycles <<
+ (u32)XNANDPSU_CMD_ADDR_CYCLES_SHIFT;
+ }
+
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_CMD_OFFSET, RegValue);
+}
+
+/*****************************************************************************/
+/**
+*
+* This function Read/Writes data from the nand controller.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Buf is the data buffer.
+* @param PktCount is the number packet chunks.
+* @param PktSize is the size of the packet.
+* @param Operation is 1 for write and 0 for read.
+* @param DmaMode is 1 for Dma and 0 for PIO.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_Data_ReadWrite(XNandPsu *InstancePtr, u8* Buf, u32 PktCount,
+ u32 PktSize, u32 Operation, u8 DmaMode)
+{
+ u32 BufRwCnt = 0U;
+ s32 Status = XST_FAILURE;
+ u32 Event = XNANDPSU_INTR_STS_BUFF_RD_RDY_STS_EN_MASK;
+
+ if ((DmaMode != 0U) && (InstancePtr->DmaMode == XNANDPSU_MDMA))
+ goto DmaDone;
+
+ if (Operation)
+ Event = XNANDPSU_INTR_STS_BUFF_WR_RDY_STS_EN_MASK;
+
+ while (BufRwCnt < PktCount) {
+ /* Poll for Buffer Write Ready event */
+ Status = XNandPsu_PollRegTimeout(InstancePtr,
+ XNANDPSU_INTR_STS_OFFSET, Event,
+ XNANDPSU_INTR_POLL_TIMEOUT);
+ if (Status != XST_SUCCESS) {
+ xil_printf("%s: Poll for buf write ready timeout\r\n",
+ __func__);
+ goto Out;
+ }
+
+ /* Increment Buffer Write Interrupt Count */
+ BufRwCnt++;
+
+ if (BufRwCnt == PktCount)
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET,
+ XNANDPSU_INTR_STS_EN_TRANS_COMP_STS_EN_MASK);
+
+ else
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET, 0U);
+ /*
+ * Clear Buffer Write Ready Interrupt in Interrupt Status
+ * Register
+ */
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_OFFSET, Event);
+ /* Write Packet Data to Data Port Register */
+ if (Operation)
+ XNandPsu_Fifo_Write(InstancePtr, Buf, PktSize);
+ else
+ XNandPsu_Fifo_Read(InstancePtr, Buf, PktSize);
+
+ Buf += PktSize;
+
+ if (BufRwCnt < PktCount)
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET, Event);
+ else
+ break;
+ }
+
+DmaDone:
+ Status = XNandPsu_WaitFor_Transfer_Complete(InstancePtr);
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function writes data to the fifo.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Buf is the buffer pointer.
+* @param Size of the Buffer.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static void XNandPsu_Fifo_Write(XNandPsu *InstancePtr, u8* Buffer, u32 Size)
+{
+ u32 *BufPtr = (u32 *)(void *)Buffer;
+ u32 Index;
+
+ for (Index = 0U; Index < Size/4U; Index++)
+ XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XNANDPSU_BUF_DATA_PORT_OFFSET,
+ BufPtr[Index]);
+}
+
+/*****************************************************************************/
+/**
+*
+* This function reads data from the fifo.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Buf is the buffer pointer.
+* @param Size of the Buffer.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static void XNandPsu_Fifo_Read(XNandPsu *InstancePtr, u8* Buf, u32 Size)
+{
+ u32 *BufPtr = (u32 *)(void *)Buf;
+ u32 Index;
+
+ for (Index = 0U; Index < Size/4U; Index++)
+ BufPtr[Index] = XNandPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XNANDPSU_BUF_DATA_PORT_OFFSET);
+}
+
+/*****************************************************************************/
+/**
+*
+* This function configures the given dma address to the controller.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Buf is the buffer pointer.
+*
+* @return
+* None
+*
+* @note None
+*
+******************************************************************************/
+static void XNandPsu_Update_DmaAddr(XNandPsu *InstancePtr, u8* Buf)
+{
+#if defined(__aarch64__) || defined(__arch64__)
+ XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XNANDPSU_DMA_SYS_ADDR1_OFFSET,
+ (u32) (((INTPTR)Buf >> 32U) & 0xFFFFFFFFU));
+#endif
+ XNandPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XNANDPSU_DMA_SYS_ADDR0_OFFSET,
+ (u32) ((INTPTR)(void *)Buf & 0xFFFFFFFFU));
+
+}
+
+/*****************************************************************************/
+/**
+*
+* This function waits for the device ready stataus.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Target is the chipselect value.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note None
+*
+******************************************************************************/
+static s32 XNandPsu_Device_Ready(XNandPsu *InstancePtr, u32 Target)
+{
+ s32 Status = XST_SUCCESS;
+ u16 OnfiStatus = 0U;
+
+ do {
+ Status = XNandPsu_OnfiReadStatus(InstancePtr, Target,
+ &OnfiStatus);
+ if (Status != XST_SUCCESS)
+ goto Out;
+ if ((OnfiStatus & (1U << 6U)) != 0U) {
+ if ((OnfiStatus & (1U << 0U)) != 0U) {
+ Status = XST_FAILURE;
+ goto Out;
+ }
+ }
+ } while (((OnfiStatus >> 6U) & 0x1U) == 0U);
+
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function waits for the transfer complete event.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if failed.
+*
+* @note Expects that transfer complete event was set before calling
+* this function.
+*
+******************************************************************************/
+static s32 XNandPsu_WaitFor_Transfer_Complete(XNandPsu *InstancePtr)
+{
+s32 Status = XST_FAILURE;
+
+ /* Poll for Transfer Complete event */
+ Status = XNandPsu_PollRegTimeout(
+ InstancePtr,
+ XNANDPSU_INTR_STS_OFFSET,
+ XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK,
+ XNANDPSU_INTR_POLL_TIMEOUT);
+ if (Status != XST_SUCCESS) {
+ xil_printf("%s: Poll for xfer complete timeout\r\n", __func__);
+ goto Out;
+ }
+
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_EN_OFFSET, 0U);
+
+ XNandPsu_WriteReg((InstancePtr)->Config.BaseAddress,
+ XNANDPSU_INTR_STS_OFFSET,
+ XNANDPSU_INTR_STS_TRANS_COMP_STS_EN_MASK);
+#if defined (XCLOCKING)
+ Xil_ClockDisable(InstancePtr->Config.RefClk);
+#endif
+Out:
+ return Status;
+}
+/** @} */
diff --git a/bsps/shared/dev/nand/xnandpsu_bbm.c b/bsps/shared/dev/nand/xnandpsu_bbm.c
new file mode 100644
index 0000000000..40cf798965
--- /dev/null
+++ b/bsps/shared/dev/nand/xnandpsu_bbm.c
@@ -0,0 +1,1001 @@
+/******************************************************************************
+* Copyright (C) 2015 - 2022 Xilinx, Inc. All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+*
+* @file xnandpsu_bbm.c
+* @addtogroup Overview
+* @{
+*
+* This file implements the Bad Block Management (BBM) functionality.
+* See xnandpsu_bbm.h for more details.
+*
+* @note None
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ---- ---------- -----------------------------------------------
+* 1.0 nm 05/06/2014 First release
+* 2.0 sb 01/12/2015 Added support for writing BBT signature and version
+* in page section by enabling XNANDPSU_BBT_NO_OOB.
+* Modified Bbt Signature and Version Offset value for
+* Oob and No-Oob region.
+* 1.1 nsk 11/07/16 Change memcpy to Xil_MemCpy to handle word aligned
+* data access.
+* 1.4 nsk 04/10/18 Added ICCARM compiler support.
+* 1.10 akm 01/05/22 Remove assert checks form static and internal APIs.
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+#include <string.h> /**< For Xil_MemCpy and memset */
+#include "xil_types.h"
+#include "xnandpsu.h"
+#include "xnandpsu_bbm.h"
+#include "xil_mem.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+static s32 XNandPsu_ReadBbt(XNandPsu *InstancePtr, u32 Target);
+
+static s32 XNandPsu_SearchBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
+ u32 Target);
+
+static void XNandPsu_CreateBbt(XNandPsu *InstancePtr, u32 Target);
+
+static void XNandPsu_ConvertBbt(XNandPsu *InstancePtr, u8 *Buf, u32 Target);
+
+static s32 XNandPsu_WriteBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
+ XNandPsu_BbtDesc *MirrorDesc, u32 Target);
+
+static s32 XNandPsu_MarkBbt(XNandPsu* InstancePtr, XNandPsu_BbtDesc *Desc,
+ u32 Target);
+
+#ifndef __rtems__
+static s32 XNandPsu_UpdateBbt(XNandPsu *InstancePtr, u32 Target);
+#endif
+
+/************************** Variable Definitions *****************************/
+
+/*****************************************************************************/
+/**
+* This function initializes the Bad Block Table(BBT) descriptors with a
+* predefined pattern for searching Bad Block Table(BBT) in flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+*
+* @return
+* - NONE
+*
+******************************************************************************/
+void XNandPsu_InitBbtDesc(XNandPsu *InstancePtr)
+{
+ u32 Index;
+
+ /* Initialize primary Bad Block Table(BBT) */
+ for (Index = 0U; Index < XNANDPSU_MAX_TARGETS; Index++) {
+ InstancePtr->BbtDesc.PageOffset[Index] =
+ XNANDPSU_BBT_DESC_PAGE_OFFSET;
+ }
+ if (InstancePtr->EccMode == XNANDPSU_ONDIE) {
+ InstancePtr->BbtDesc.SigOffset = XNANDPSU_ONDIE_SIG_OFFSET;
+ InstancePtr->BbtDesc.VerOffset = XNANDPSU_ONDIE_VER_OFFSET;
+ } else {
+ InstancePtr->BbtDesc.SigOffset = XNANDPSU_BBT_DESC_SIG_OFFSET;
+ InstancePtr->BbtDesc.VerOffset = XNANDPSU_BBT_DESC_VER_OFFSET;
+ }
+ InstancePtr->BbtDesc.SigLength = XNANDPSU_BBT_DESC_SIG_LEN;
+ InstancePtr->BbtDesc.MaxBlocks = XNANDPSU_BBT_DESC_MAX_BLOCKS;
+ (void)strcpy(&InstancePtr->BbtDesc.Signature[0], "Bbt0");
+ for (Index = 0U; Index < XNANDPSU_MAX_TARGETS; Index++) {
+ InstancePtr->BbtDesc.Version[Index] = 0U;
+ }
+ InstancePtr->BbtDesc.Valid = 0U;
+
+ /* Assuming that the flash device will have at least 4 blocks. */
+ if (InstancePtr->Geometry.NumTargetBlocks <= InstancePtr->
+ BbtDesc.MaxBlocks){
+ InstancePtr->BbtDesc.MaxBlocks = 4U;
+ }
+
+ /* Initialize mirror Bad Block Table(BBT) */
+ for (Index = 0U; Index < XNANDPSU_MAX_TARGETS; Index++) {
+ InstancePtr->BbtMirrorDesc.PageOffset[Index] =
+ XNANDPSU_BBT_DESC_PAGE_OFFSET;
+ }
+ if (InstancePtr->EccMode == XNANDPSU_ONDIE) {
+ InstancePtr->BbtMirrorDesc.SigOffset =
+ XNANDPSU_ONDIE_SIG_OFFSET;
+ InstancePtr->BbtMirrorDesc.VerOffset =
+ XNANDPSU_ONDIE_VER_OFFSET;
+ } else {
+ InstancePtr->BbtMirrorDesc.SigOffset =
+ XNANDPSU_BBT_DESC_SIG_OFFSET;
+ InstancePtr->BbtMirrorDesc.VerOffset =
+ XNANDPSU_BBT_DESC_VER_OFFSET;
+ }
+ InstancePtr->BbtMirrorDesc.SigLength = XNANDPSU_BBT_DESC_SIG_LEN;
+ InstancePtr->BbtMirrorDesc.MaxBlocks = XNANDPSU_BBT_DESC_MAX_BLOCKS;
+ (void)strcpy(&InstancePtr->BbtMirrorDesc.Signature[0], "1tbB");
+ for (Index = 0U; Index < XNANDPSU_MAX_TARGETS; Index++) {
+ InstancePtr->BbtMirrorDesc.Version[Index] = 0U;
+ }
+ InstancePtr->BbtMirrorDesc.Valid = 0U;
+
+ /* Assuming that the flash device will have at least 4 blocks. */
+ if (InstancePtr->Geometry.NumTargetBlocks <= InstancePtr->
+ BbtMirrorDesc.MaxBlocks){
+ InstancePtr->BbtMirrorDesc.MaxBlocks = 4U;
+ }
+
+ /* Initialize Bad block search pattern structure */
+ if (InstancePtr->Geometry.BytesPerPage > 512U) {
+ /* For flash page size > 512 bytes */
+ InstancePtr->BbPattern.Options = XNANDPSU_BBT_SCAN_2ND_PAGE;
+ InstancePtr->BbPattern.Offset =
+ XNANDPSU_BB_PTRN_OFF_LARGE_PAGE;
+ InstancePtr->BbPattern.Length =
+ XNANDPSU_BB_PTRN_LEN_LARGE_PAGE;
+ } else {
+ InstancePtr->BbPattern.Options = XNANDPSU_BBT_SCAN_2ND_PAGE;
+ InstancePtr->BbPattern.Offset =
+ XNANDPSU_BB_PTRN_OFF_SML_PAGE;
+ InstancePtr->BbPattern.Length =
+ XNANDPSU_BB_PTRN_LEN_SML_PAGE;
+ }
+ for(Index = 0U; Index < XNANDPSU_BB_PTRN_LEN_LARGE_PAGE; Index++) {
+ InstancePtr->BbPattern.Pattern[Index] = XNANDPSU_BB_PATTERN;
+ }
+}
+
+/*****************************************************************************/
+/**
+* This function scans the NAND flash for factory marked bad blocks and creates
+* a RAM based Bad Block Table(BBT).
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+*
+* @return
+* - NONE
+*
+******************************************************************************/
+static void XNandPsu_CreateBbt(XNandPsu *InstancePtr, u32 Target)
+{
+ u32 BlockIndex;
+ u32 PageIndex;
+ u32 Length;
+ u32 BlockOffset;
+ u8 BlockShift;
+ u32 NumPages;
+ u32 Page;
+#ifdef __ICCARM__
+#pragma pack(push, 1)
+ u8 Buf[XNANDPSU_MAX_SPARE_SIZE] = {0U};
+#pragma pack(pop)
+#else
+ u8 Buf[XNANDPSU_MAX_SPARE_SIZE] __attribute__ ((aligned(64))) = {0U};
+#endif
+ u32 StartBlock = Target * InstancePtr->Geometry.NumTargetBlocks;
+ u32 NumBlocks = InstancePtr->Geometry.NumTargetBlocks;
+ s32 Status;
+
+ /* Number of pages to search for bad block pattern */
+ if ((InstancePtr->BbPattern.Options & XNANDPSU_BBT_SCAN_2ND_PAGE) != 0U)
+ {
+ NumPages = 2U;
+ } else {
+ NumPages = 1U;
+ }
+ /* Scan all the blocks for factory marked bad blocks */
+ for(BlockIndex = StartBlock; BlockIndex < (StartBlock + NumBlocks);
+ BlockIndex++) {
+ /* Block offset in Bad Block Table(BBT) entry */
+ BlockOffset = BlockIndex >> XNANDPSU_BBT_BLOCK_SHIFT;
+ /* Block shift value in the byte */
+ BlockShift = XNandPsu_BbtBlockShift(BlockIndex);
+ Page = BlockIndex * InstancePtr->Geometry.PagesPerBlock;
+ /* Search for the bad block pattern */
+ for(PageIndex = 0U; PageIndex < NumPages; PageIndex++) {
+ Status = XNandPsu_ReadSpareBytes(InstancePtr,
+ (Page + PageIndex), &Buf[0]);
+
+ if (Status != XST_SUCCESS) {
+ /* Marking as bad block */
+ InstancePtr->Bbt[BlockOffset] |=
+ (u8)(XNANDPSU_BLOCK_FACTORY_BAD <<
+ BlockShift);
+ break;
+ }
+ /*
+ * Read the spare bytes to check for bad block
+ * pattern
+ */
+ for(Length = 0U; Length <
+ InstancePtr->BbPattern.Length; Length++) {
+ if (Buf[InstancePtr->BbPattern.Offset + Length]
+ !=
+ InstancePtr->BbPattern.Pattern[Length])
+ {
+ /* Bad block found */
+ InstancePtr->Bbt[BlockOffset] |=
+ (u8)
+ (XNANDPSU_BLOCK_FACTORY_BAD <<
+ BlockShift);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/*****************************************************************************/
+/**
+* This function reads the Bad Block Table(BBT) if present in flash. If not it
+* scans the flash for detecting factory marked bad blocks and creates a bad
+* block table and write the Bad Block Table(BBT) into the flash.
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if fail.
+*
+******************************************************************************/
+s32 XNandPsu_ScanBbt(XNandPsu *InstancePtr)
+{
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY)
+
+ s32 Status;
+ u32 Index;
+ u32 BbtLen;
+
+ /* Zero the RAM based Bad Block Table(BBT) entries */
+ BbtLen = InstancePtr->Geometry.NumBlocks >>
+ XNANDPSU_BBT_BLOCK_SHIFT;
+ (void)memset(&InstancePtr->Bbt[0], 0, BbtLen);
+
+ for (Index = 0U; Index < InstancePtr->Geometry.NumTargets; Index++) {
+
+ if (XNandPsu_ReadBbt(InstancePtr, Index) != XST_SUCCESS) {
+ /* Create memory based Bad Block Table(BBT) */
+ XNandPsu_CreateBbt(InstancePtr, Index);
+ /* Write the Bad Block Table(BBT) to the flash */
+ Status = XNandPsu_WriteBbt(InstancePtr,
+ &InstancePtr->BbtDesc,
+ &InstancePtr->BbtMirrorDesc, Index);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ /* Write the Mirror Bad Block Table(BBT) to the flash */
+ Status = XNandPsu_WriteBbt(InstancePtr,
+ &InstancePtr->BbtMirrorDesc,
+ &InstancePtr->BbtDesc, Index);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ /*
+ * Mark the blocks containing Bad Block Table
+ * (BBT) as Reserved
+ */
+ Status = XNandPsu_MarkBbt(InstancePtr,
+ &InstancePtr->BbtDesc,
+ Index);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ Status = XNandPsu_MarkBbt(InstancePtr,
+ &InstancePtr->BbtMirrorDesc,
+ Index);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ }
+ }
+
+ Status = XST_SUCCESS;
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+* This function converts the Bad Block Table(BBT) read from the flash to the
+* RAM based Bad Block Table(BBT).
+*
+* @param InstancePtr is a pointer to the XNandPsu instance.
+* @param Buf is the buffer which contains BBT read from flash.
+*
+* @return
+* - NONE.
+*
+******************************************************************************/
+static void XNandPsu_ConvertBbt(XNandPsu *InstancePtr, u8 *Buf, u32 Target)
+{
+#ifndef __rtems__
+ u32 BlockOffset;
+ u8 BlockShift;
+ u32 Data;
+ u8 BlockType;
+ u32 BlockIndex;
+#endif
+ u32 BbtLen = InstancePtr->Geometry.NumTargetBlocks >>
+ XNANDPSU_BBT_BLOCK_SHIFT;
+#ifdef __rtems__
+ u32 BbtOffset = Target * InstancePtr->Geometry.NumTargetBlocks / XNANDPSU_BBT_ENTRY_NUM_BLOCKS;
+
+ for(u32 BbtIndex = 0; BbtIndex < BbtLen; BbtIndex++) {
+ /* Invert the byte to convert from in-flash BBT to in-memory BBT */
+ InstancePtr->Bbt[BbtIndex + BbtOffset] = ~Buf[BbtIndex];
+ }
+#else
+ u32 StartBlock = Target * InstancePtr->Geometry.NumTargetBlocks;
+
+ for(BlockOffset = StartBlock; BlockOffset < (StartBlock + BbtLen);
+ BlockOffset++) {
+ Data = *(Buf + BlockOffset);
+ /* Clear the RAM based Bad Block Table(BBT) contents */
+ InstancePtr->Bbt[BlockOffset] = 0x0U;
+ /* Loop through the every 4 blocks in the bitmap */
+ for(BlockIndex = 0U; BlockIndex < XNANDPSU_BBT_ENTRY_NUM_BLOCKS;
+ BlockIndex++) {
+ BlockShift = XNandPsu_BbtBlockShift(BlockIndex);
+ BlockType = (u8) ((Data >> BlockShift) &
+ XNANDPSU_BLOCK_TYPE_MASK);
+ switch(BlockType) {
+ case XNANDPSU_FLASH_BLOCK_FAC_BAD:
+ /* Factory bad block */
+ InstancePtr->Bbt[BlockOffset] |=
+ (u8)
+ (XNANDPSU_BLOCK_FACTORY_BAD <<
+ BlockShift);
+ break;
+ case XNANDPSU_FLASH_BLOCK_RESERVED:
+ /* Reserved block */
+ InstancePtr->Bbt[BlockOffset] |=
+ (u8)
+ (XNANDPSU_BLOCK_RESERVED <<
+ BlockShift);
+ break;
+ case XNANDPSU_FLASH_BLOCK_BAD:
+ /* Bad block due to wear */
+ InstancePtr->Bbt[BlockOffset] |=
+ (u8)(XNANDPSU_BLOCK_BAD <<
+ BlockShift);
+ break;
+ default:
+ /* Good block */
+ /* The BBT entry already defaults to
+ * zero */
+ break;
+ }
+ }
+ }
+#endif
+}
+
+/*****************************************************************************/
+/**
+* This function searches the Bad Bloock Table(BBT) in flash and loads into the
+* memory based Bad Block Table(BBT).
+*
+* @param InstancePtr is the pointer to the XNandPsu instance.
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if fail.
+*
+******************************************************************************/
+static s32 XNandPsu_ReadBbt(XNandPsu *InstancePtr, u32 Target)
+{
+ u64 Offset;
+#ifdef __ICCARM__
+#pragma pack(push, 1)
+ u8 Buf[XNANDPSU_BBT_BUF_LENGTH]= {0U};
+#pragma pack(pop)
+#else
+ u8 Buf[XNANDPSU_BBT_BUF_LENGTH] __attribute__ ((aligned(64))) = {0U};
+#endif
+ s32 Status1;
+ s32 Status2;
+ s32 Status;
+ u32 BufLen;
+
+ XNandPsu_BbtDesc *Desc = &InstancePtr->BbtDesc;
+ XNandPsu_BbtDesc *MirrorDesc = &InstancePtr->BbtMirrorDesc;
+#ifdef __rtems__
+ BufLen = InstancePtr->Geometry.NumTargetBlocks >>
+#else
+ BufLen = InstancePtr->Geometry.NumBlocks >>
+#endif
+ XNANDPSU_BBT_BLOCK_SHIFT;
+ /* Search the Bad Block Table(BBT) in flash */
+ Status1 = XNandPsu_SearchBbt(InstancePtr, Desc, Target);
+ Status2 = XNandPsu_SearchBbt(InstancePtr, MirrorDesc, Target);
+ if ((Status1 != XST_SUCCESS) && (Status2 != XST_SUCCESS)) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Bad block table not found\r\n",__func__);
+#endif
+ Status = XST_FAILURE;
+ goto Out;
+ }
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Bad block table found\r\n",__func__);
+#endif
+ /* Bad Block Table found */
+ if ((Desc->Valid != 0U) && (MirrorDesc->Valid != 0U)) {
+ /* Valid BBT & Mirror BBT found */
+ if (Desc->Version[Target] > MirrorDesc->Version[Target]) {
+ Offset = (u64)Desc->PageOffset[Target] *
+ (u64)InstancePtr->Geometry.BytesPerPage;
+ Status = XNandPsu_Read(InstancePtr, Offset, BufLen,
+ &Buf[0]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ /* Convert flash BBT to memory based BBT */
+ XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target);
+ MirrorDesc->Version[Target] = Desc->Version[Target];
+
+ /* Write the BBT to Mirror BBT location in flash */
+ Status = XNandPsu_WriteBbt(InstancePtr, MirrorDesc,
+ Desc, Target);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ } else if (Desc->Version[Target] <
+ MirrorDesc->Version[Target]) {
+ Offset = (u64)MirrorDesc->PageOffset[Target] *
+ (u64)InstancePtr->Geometry.BytesPerPage;
+ Status = XNandPsu_Read(InstancePtr, Offset, BufLen,
+ &Buf[0]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ /* Convert flash BBT to memory based BBT */
+ XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target);
+ Desc->Version[Target] = MirrorDesc->Version[Target];
+
+ /* Write the Mirror BBT to BBT location in flash */
+ Status = XNandPsu_WriteBbt(InstancePtr, Desc,
+ MirrorDesc, Target);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ } else {
+ /* Both are up-to-date */
+ Offset = (u64)Desc->PageOffset[Target] *
+ (u64)InstancePtr->Geometry.BytesPerPage;
+ Status = XNandPsu_Read(InstancePtr, Offset, BufLen,
+ &Buf[0]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ /* Convert flash BBT to memory based BBT */
+ XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target);
+ }
+ } else if (Desc->Valid != 0U) {
+ /* Valid Primary BBT found */
+ Offset = (u64)Desc->PageOffset[Target] *
+ (u64)InstancePtr->Geometry.BytesPerPage;
+ Status = XNandPsu_Read(InstancePtr, Offset, BufLen, &Buf[0]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ /* Convert flash BBT to memory based BBT */
+ XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target);
+ MirrorDesc->Version[Target] = Desc->Version[Target];
+
+ /* Write the BBT to Mirror BBT location in flash */
+ Status = XNandPsu_WriteBbt(InstancePtr, MirrorDesc, Desc,
+ Target);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ } else {
+ /* Valid Mirror BBT found */
+ Offset = (u64)MirrorDesc->PageOffset[Target] *
+ (u64)InstancePtr->Geometry.BytesPerPage;
+ Status = XNandPsu_Read(InstancePtr, Offset, BufLen, &Buf[0]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ /* Convert flash BBT to memory based BBT */
+ XNandPsu_ConvertBbt(InstancePtr, &Buf[0], Target);
+ Desc->Version[Target] = MirrorDesc->Version[Target];
+
+ /* Write the Mirror BBT to BBT location in flash */
+ Status = XNandPsu_WriteBbt(InstancePtr, Desc, MirrorDesc,
+ Target);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ }
+
+ Status = XST_SUCCESS;
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+* This function searches the BBT in flash.
+*
+* @param InstancePtr is the pointer to the XNandPsu instance.
+* @param Desc is the BBT descriptor pattern to search.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if fail.
+*
+******************************************************************************/
+static s32 XNandPsu_SearchBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
+ u32 Target)
+{
+ u32 StartBlock;
+ u32 SigOffset;
+ u32 VerOffset;
+ u32 MaxBlocks;
+ u32 PageOff;
+ u32 SigLength;
+#ifdef __ICCARM__
+#pragma pack(push, 1)
+ u8 Buf[XNANDPSU_MAX_SPARE_SIZE] = {0U};
+#pragma pack(pop)
+#else
+ u8 Buf[XNANDPSU_MAX_SPARE_SIZE] __attribute__ ((aligned(64))) = {0U};
+#endif
+ u32 Block;
+ u32 Offset;
+ s32 Status;
+
+ StartBlock = ((Target + (u32)1) *
+ InstancePtr->Geometry.NumTargetBlocks) - (u32)1;
+ SigOffset = Desc->SigOffset;
+ VerOffset = Desc->VerOffset;
+ MaxBlocks = Desc->MaxBlocks;
+ SigLength = Desc->SigLength;
+#ifdef __rtems__
+ Desc->Valid = 0;
+#endif
+
+ /* Read the last 4 blocks for Bad Block Table(BBT) signature */
+ for(Block = 0U; Block < MaxBlocks; Block++) {
+ PageOff = (StartBlock - Block) *
+ InstancePtr->Geometry.PagesPerBlock;
+
+ Status = XNandPsu_ReadSpareBytes(InstancePtr, PageOff, &Buf[0]);
+ if (Status != XST_SUCCESS) {
+ continue;
+ }
+ /* Check the Bad Block Table(BBT) signature */
+ for(Offset = 0U; Offset < SigLength; Offset++) {
+ if (Buf[Offset + SigOffset] !=
+ (u8)(Desc->Signature[Offset]))
+ {
+ break; /* Check the next blocks */
+ }
+ }
+ if (Offset >= SigLength) {
+ /* Bad Block Table(BBT) found */
+ Desc->PageOffset[Target] = PageOff;
+ Desc->Version[Target] = Buf[VerOffset];
+ Desc->Valid = 1U;
+
+ Status = XST_SUCCESS;
+ goto Out;
+ }
+ }
+ /* Bad Block Table(BBT) not found */
+ Status = XST_FAILURE;
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+* This function writes Bad Block Table(BBT) from RAM to flash.
+*
+* @param InstancePtr is the pointer to the XNandPsu instance.
+* @param Desc is the BBT descriptor to be written to flash.
+* @param MirrorDesc is the mirror BBT descriptor.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if fail.
+*
+******************************************************************************/
+static s32 XNandPsu_WriteBbt(XNandPsu *InstancePtr, XNandPsu_BbtDesc *Desc,
+ XNandPsu_BbtDesc *MirrorDesc, u32 Target)
+{
+ u64 Offset;
+ u32 Block = {0U};
+ u32 EndBlock = ((Target + (u32)1) *
+ InstancePtr->Geometry.NumTargetBlocks) - (u32)1;
+#ifdef __ICCARM__
+#pragma pack(push, 1)
+ u8 Buf[XNANDPSU_BBT_BUF_LENGTH]= {0U};
+ u8 SpareBuf[XNANDPSU_MAX_SPARE_SIZE]= {0U};
+#pragma pack(pop)
+#else
+ u8 Buf[XNANDPSU_BBT_BUF_LENGTH] __attribute__ ((aligned(64))) = {0U};
+ u8 SpareBuf[XNANDPSU_MAX_SPARE_SIZE] __attribute__ ((aligned(64))) = {0U};
+#endif
+
+#ifndef __rtems__
+ u8 Mask[4] = {0x00U, 0x01U, 0x02U, 0x03U};
+ u8 Data;
+ u32 BlockOffset;
+ u8 BlockShift;
+ s32 Status;
+ u32 BlockIndex;
+ u32 Index;
+ u8 BlockType;
+ u32 BbtLen = InstancePtr->Geometry.NumBlocks >>
+#else
+ s32 Status;
+ u32 Index;
+ u32 BbtLen = InstancePtr->Geometry.NumTargetBlocks >>
+#endif
+ XNANDPSU_BBT_BLOCK_SHIFT;
+ /* Find a valid block to write the Bad Block Table(BBT) */
+ if ((!Desc->Valid) != 0U) {
+ for(Index = 0U; Index < Desc->MaxBlocks; Index++) {
+ Block = (EndBlock - Index);
+#ifdef __rtems__
+ if (XNandPsu_IsBlockBad(InstancePtr, Block) != XST_FAILURE) {
+ continue;
+ }
+#else
+ BlockOffset = Block >> XNANDPSU_BBT_BLOCK_SHIFT;
+ BlockShift = XNandPsu_BbtBlockShift(Block);
+ BlockType = (InstancePtr->Bbt[BlockOffset] >>
+ BlockShift) & XNANDPSU_BLOCK_TYPE_MASK;
+ switch(BlockType)
+ {
+ case XNANDPSU_BLOCK_BAD:
+ case XNANDPSU_BLOCK_FACTORY_BAD:
+ continue;
+ default:
+ /* Good Block */
+ break;
+ }
+#endif
+ Desc->PageOffset[Target] = Block *
+ InstancePtr->Geometry.PagesPerBlock;
+ if (Desc->PageOffset[Target] !=
+ MirrorDesc->PageOffset[Target]) {
+ /* Free block found */
+ Desc->Valid = 1U;
+ break;
+ }
+ }
+
+
+ /* Block not found for writing Bad Block Table(BBT) */
+ if (Index >= Desc->MaxBlocks) {
+#ifdef XNANDPSU_DEBUG
+ xil_printf("%s: Blocks unavailable for writing BBT\r\n",
+ __func__);
+#endif
+ Status = XST_FAILURE;
+ goto Out;
+ }
+ } else {
+ Block = Desc->PageOffset[Target] /
+ InstancePtr->Geometry.PagesPerBlock;
+ }
+ /* Convert the memory based BBT to flash based table */
+ (void)memset(Buf, 0xff, BbtLen);
+
+#ifdef __rtems__
+ u32 BbtTargetOffset = BbtLen * Target;
+ /* Loop through the BBT entries */
+ for(u32 BbtIndex = 0U; BbtIndex < BbtLen; BbtIndex++) {
+ /* Invert byte to convert from in-memory BBT to in-flash BBT */
+ Buf[BbtIndex] = ~InstancePtr->Bbt[BbtIndex + BbtTargetOffset];
+ }
+#else
+ /* Loop through the number of blocks */
+ for(BlockOffset = 0U; BlockOffset < BbtLen; BlockOffset++) {
+ Data = InstancePtr->Bbt[BlockOffset];
+ /* Calculate the bit mask for 4 blocks at a time in loop */
+ for(BlockIndex = 0U; BlockIndex < XNANDPSU_BBT_ENTRY_NUM_BLOCKS;
+ BlockIndex++) {
+ BlockShift = XNandPsu_BbtBlockShift(BlockIndex);
+ Buf[BlockOffset] &= ~(Mask[Data &
+ XNANDPSU_BLOCK_TYPE_MASK] <<
+ BlockShift);
+ Data >>= XNANDPSU_BBT_BLOCK_SHIFT;
+ }
+ }
+#endif
+ /* Write the Bad Block Table(BBT) to flash */
+#ifdef __rtems__
+ Status = XNandPsu_EraseBlock(InstancePtr, Target,
+ Block % InstancePtr->Geometry.NumTargetBlocks);
+#else
+ Status = XNandPsu_EraseBlock(InstancePtr, 0U, Block);
+#endif
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+
+ /* Write the BBT to page offset */
+ Offset = (u64)Desc->PageOffset[Target] *
+ (u64)InstancePtr->Geometry.BytesPerPage;
+ Status = XNandPsu_Write(InstancePtr, Offset, BbtLen, &Buf[0]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ /* Write the signature and version in the spare data area */
+ (void)memset(SpareBuf, 0xff, InstancePtr->Geometry.SpareBytesPerPage);
+ Status = XNandPsu_ReadSpareBytes(InstancePtr, Desc->PageOffset[Target],
+ &SpareBuf[0]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+
+ (void)Xil_MemCpy(SpareBuf + Desc->SigOffset, &Desc->Signature[0],
+ Desc->SigLength);
+ (void)memcpy(SpareBuf + Desc->VerOffset, &Desc->Version[Target], 1U);
+
+ Status = XNandPsu_WriteSpareBytes(InstancePtr,
+ Desc->PageOffset[Target], &SpareBuf[0]);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+
+ Status = XST_SUCCESS;
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+* This function updates the primary and mirror Bad Block Table(BBT) in the
+* flash.
+*
+* @param InstancePtr is the pointer to the XNandPsu instance.
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if fail.
+*
+******************************************************************************/
+#ifdef __rtems__
+s32 XNandPsu_UpdateBbt(XNandPsu *InstancePtr, u32 Target)
+#else
+static s32 XNandPsu_UpdateBbt(XNandPsu *InstancePtr, u32 Target)
+#endif
+{
+ s32 Status;
+ u8 Version;
+
+ /* Update the version number */
+ Version = InstancePtr->BbtDesc.Version[Target];
+ InstancePtr->BbtDesc.Version[Target] = (u8)(((u16)Version +
+ (u16)1) % (u16)256U);
+
+ Version = InstancePtr->BbtMirrorDesc.Version[Target];
+ InstancePtr->BbtMirrorDesc.Version[Target] = (u8)(((u16)Version +
+ (u16)1) % (u16)256);
+ /* Update the primary Bad Block Table(BBT) in flash */
+ Status = XNandPsu_WriteBbt(InstancePtr, &InstancePtr->BbtDesc,
+ &InstancePtr->BbtMirrorDesc,
+ Target);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+
+ /* Update the mirrored Bad Block Table(BBT) in flash */
+ Status = XNandPsu_WriteBbt(InstancePtr, &InstancePtr->BbtMirrorDesc,
+ &InstancePtr->BbtDesc,
+ Target);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+
+ Status = XST_SUCCESS;
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+* This function marks the block containing Bad Block Table as reserved
+* and updates the BBT.
+*
+* @param InstancePtr is the pointer to the XNandPsu instance.
+* @param Desc is the BBT descriptor pointer.
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if fail.
+*
+******************************************************************************/
+static s32 XNandPsu_MarkBbt(XNandPsu* InstancePtr, XNandPsu_BbtDesc *Desc,
+ u32 Target)
+{
+ u32 BlockIndex;
+ u32 BlockOffset;
+ u8 BlockShift;
+ u8 OldVal;
+ u8 NewVal;
+ s32 Status;
+ u32 UpdateBbt = 0U;
+ u32 Index;
+
+ /* Mark the last four blocks as Reserved */
+ BlockIndex = ((Target + (u32)1) * InstancePtr->Geometry.NumTargetBlocks) -
+#ifdef __rtems__
+ Desc->MaxBlocks;
+#else
+ Desc->MaxBlocks - (u32)1;
+#endif
+
+ for(Index = 0U; Index < Desc->MaxBlocks; Index++) {
+
+ BlockOffset = BlockIndex >> XNANDPSU_BBT_BLOCK_SHIFT;
+ BlockShift = XNandPsu_BbtBlockShift(BlockIndex);
+ OldVal = InstancePtr->Bbt[BlockOffset];
+ NewVal = (u8) (OldVal | (XNANDPSU_BLOCK_RESERVED <<
+ BlockShift));
+ InstancePtr->Bbt[BlockOffset] = NewVal;
+
+ if (OldVal != NewVal) {
+ UpdateBbt = 1U;
+ }
+ BlockIndex++;
+ }
+
+ /* Update the BBT to flash */
+ if (UpdateBbt != 0U) {
+ Status = XNandPsu_UpdateBbt(InstancePtr, Target);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ }
+
+ Status = XST_SUCCESS;
+Out:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function checks whether a block is bad or not.
+*
+* @param InstancePtr is the pointer to the XNandPsu instance.
+*
+* @param Block is the block number.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if fail.
+*
+******************************************************************************/
+s32 XNandPsu_IsBlockBad(XNandPsu *InstancePtr, u32 Block)
+{
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY)
+ Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks);
+
+ u8 Data;
+ u8 BlockShift;
+ u8 BlockType;
+ u32 BlockOffset;
+ s32 Status;
+
+ BlockOffset = Block >> XNANDPSU_BBT_BLOCK_SHIFT;
+ BlockShift = XNandPsu_BbtBlockShift(Block);
+ Data = InstancePtr->Bbt[BlockOffset]; /* Block information in BBT */
+ BlockType = (Data >> BlockShift) & XNANDPSU_BLOCK_TYPE_MASK;
+
+ if ((BlockType != XNANDPSU_BLOCK_GOOD) &&
+ (BlockType != XNANDPSU_BLOCK_RESERVED)) {
+ Status = XST_SUCCESS;
+ }
+ else {
+ Status = XST_FAILURE;
+ }
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+* This function marks a block as bad in the RAM based Bad Block Table(BBT). It
+* also updates the Bad Block Table(BBT) in the flash.
+*
+* @param InstancePtr is the pointer to the XNandPsu instance.
+* @param Block is the block number.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_FAILURE if fail.
+*
+******************************************************************************/
+s32 XNandPsu_MarkBlockBad(XNandPsu *InstancePtr, u32 Block)
+#ifdef __rtems__
+{
+ return XNandPsu_MarkBlock(InstancePtr, Block, XNANDPSU_BLOCK_BAD );
+}
+
+s32 XNandPsu_MarkBlock(XNandPsu *InstancePtr, u32 Block, u8 BlockMark)
+#endif
+{
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY)
+ Xil_AssertNonvoid(Block < InstancePtr->Geometry.NumBlocks);
+
+#ifdef __rtems__
+ BlockMark &= XNANDPSU_BLOCK_TYPE_MASK;
+#endif
+
+ u8 Data;
+ u8 BlockShift;
+ u32 BlockOffset;
+ u8 OldVal;
+ u8 NewVal;
+ s32 Status;
+ u32 Target;
+
+ Target = Block / InstancePtr->Geometry.NumTargetBlocks;
+
+ BlockOffset = Block >> XNANDPSU_BBT_BLOCK_SHIFT;
+ BlockShift = XNandPsu_BbtBlockShift(Block);
+ Data = InstancePtr->Bbt[BlockOffset]; /* Block information in BBT */
+
+ /* Mark the block as bad in the RAM based Bad Block Table */
+ OldVal = Data;
+ Data &= ~(XNANDPSU_BLOCK_TYPE_MASK << BlockShift);
+#ifdef __rtems__
+ Data |= (BlockMark << BlockShift);
+#else
+ Data |= (XNANDPSU_BLOCK_BAD << BlockShift);
+#endif
+ NewVal = Data;
+ InstancePtr->Bbt[BlockOffset] = Data;
+
+ /* Update the Bad Block Table(BBT) in flash */
+ if (OldVal != NewVal) {
+ Status = XNandPsu_UpdateBbt(InstancePtr, Target);
+ if (Status != XST_SUCCESS) {
+ goto Out;
+ }
+ }
+
+ Status = XST_SUCCESS;
+Out:
+ return Status;
+}
+
+#ifdef __rtems__
+bool XNandPsu_StageBlockMark(XNandPsu *InstancePtr, u32 Block, u8 BlockMark)
+{
+ u8 BlockShift;
+ u32 BlockOffset;
+ u8 OldVal;
+
+ BlockMark &= XNANDPSU_BLOCK_TYPE_MASK;
+
+ BlockOffset = Block >> XNANDPSU_BBT_BLOCK_SHIFT;
+ BlockShift = XNandPsu_BbtBlockShift(Block);
+ OldVal = InstancePtr->Bbt[BlockOffset] >> BlockShift;
+ OldVal &= XNANDPSU_BLOCK_TYPE_MASK;
+ InstancePtr->Bbt[BlockOffset] &= ~(XNANDPSU_BLOCK_TYPE_MASK << BlockShift);
+ InstancePtr->Bbt[BlockOffset] |= (BlockMark << BlockShift);
+ return BlockMark != OldVal;
+}
+#endif
+
+/** @} */
diff --git a/bsps/shared/dev/nand/xnandpsu_onfi.c b/bsps/shared/dev/nand/xnandpsu_onfi.c
new file mode 100644
index 0000000000..0009722bfe
--- /dev/null
+++ b/bsps/shared/dev/nand/xnandpsu_onfi.c
@@ -0,0 +1,91 @@
+/******************************************************************************
+* Copyright (C) 2015 - 2022 Xilinx, Inc. All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+*
+* @file xnandpsu_onfi.c
+* @addtogroup Overview
+* @{
+*
+* This file contains the implementation of ONFI specific functions.
+*
+* @note None
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ---- ---------- -----------------------------------------------
+* 1.0 nm 05/06/2014 First release
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+#include "xnandpsu_onfi.h"
+#include "xnandpsu.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/*****************************************************************************/
+/**
+*
+* This function calculates ONFI parameter page CRC.
+*
+* @param ParamBuf is a pointer to the ONFI parameter page buffer.
+* @param StartOff is the starting offset in buffer to calculate CRC.
+* @param Length is the number of bytes for which CRC is calculated.
+*
+* @return
+* CRC value.
+* @note
+* None.
+*
+******************************************************************************/
+u32 XNandPsu_OnfiParamPageCrc(u8 *ParamBuf, u32 StartOff, u32 Length)
+{
+ const u32 CrcInit = 0x4F4EU;
+ const u32 Order = 16U;
+ const u32 Polynom = 0x8005U;
+ u32 i, j, c, Bit;
+ u32 Crc = CrcInit;
+ u32 DataIn;
+ u32 DataByteCount = 0U;
+ u32 CrcMask, CrcHighBit;
+
+ CrcMask = ((u32)(((u32)1 << (Order - (u32)1)) -(u32)1) << (u32)1) | (u32)1;
+ CrcHighBit = (u32)((u32)1 << (Order - (u32)1));
+ /*
+ * CRC covers the data bytes between byte 0 and byte 253
+ * (ONFI 1.0, section 5.4.1.36)
+ */
+ for(i = StartOff; i < Length; i++) {
+ DataIn = *(ParamBuf + i);
+ c = (u32)DataIn;
+ DataByteCount++;
+ j = 0x80U;
+ while(j != 0U) {
+ Bit = Crc & CrcHighBit;
+ Crc <<= 1U;
+ if ((c & j) != 0U) {
+ Bit ^= CrcHighBit;
+ }
+ if (Bit != 0U) {
+ Crc ^= Polynom;
+ }
+ j >>= 1U;
+ }
+ Crc &= CrcMask;
+ }
+ return Crc;
+}
+/** @} */
diff --git a/bsps/shared/dev/rtc/icm7170.c b/bsps/shared/dev/rtc/icm7170.c
index 1cc9e980f7..8c8b44ccff 100644
--- a/bsps/shared/dev/rtc/icm7170.c
+++ b/bsps/shared/dev/rtc/icm7170.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file interfaces with the real-time clock found in
* a Harris ICM7170
@@ -16,9 +18,26 @@
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems.h>
diff --git a/bsps/shared/dev/rtc/icm7170_reg.c b/bsps/shared/dev/rtc/icm7170_reg.c
index 747f1f218d..da70722f2e 100644
--- a/bsps/shared/dev/rtc/icm7170_reg.c
+++ b/bsps/shared/dev/rtc/icm7170_reg.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the icm7170 chip if accesses to the chip are as follows:
@@ -8,9 +10,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems.h>
diff --git a/bsps/shared/dev/rtc/icm7170_reg2.c b/bsps/shared/dev/rtc/icm7170_reg2.c
index 179d76c6f5..f428e16df4 100644
--- a/bsps/shared/dev/rtc/icm7170_reg2.c
+++ b/bsps/shared/dev/rtc/icm7170_reg2.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the icm7170 chip if accesses to the chip are as follows:
@@ -8,9 +10,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#define _ICM7170_MULTIPLIER 2
diff --git a/bsps/shared/dev/rtc/icm7170_reg4.c b/bsps/shared/dev/rtc/icm7170_reg4.c
index dada40961c..2735b272ba 100644
--- a/bsps/shared/dev/rtc/icm7170_reg4.c
+++ b/bsps/shared/dev/rtc/icm7170_reg4.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the icm7170 chip if accesses to the chip are as follows:
@@ -8,9 +10,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#define _ICM7170_MULTIPLIER 4
diff --git a/bsps/shared/dev/rtc/icm7170_reg8.c b/bsps/shared/dev/rtc/icm7170_reg8.c
index a1fb1a5ea2..36505dcec1 100644
--- a/bsps/shared/dev/rtc/icm7170_reg8.c
+++ b/bsps/shared/dev/rtc/icm7170_reg8.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the icm7170 chip if accesses to the chip are as follows:
@@ -8,9 +10,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#define _ICM7170_MULTIPLIER 8
diff --git a/bsps/shared/dev/rtc/m48t08.c b/bsps/shared/dev/rtc/m48t08.c
index 3b600bd995..1933e17ab0 100644
--- a/bsps/shared/dev/rtc/m48t08.c
+++ b/bsps/shared/dev/rtc/m48t08.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file interfaces with the real-time clock found in
* a Mostek M48T08 or M48T18 or compatibles.
@@ -16,9 +18,26 @@
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems.h>
diff --git a/bsps/shared/dev/rtc/m48t08_reg.c b/bsps/shared/dev/rtc/m48t08_reg.c
index 2174496fda..ef0d6b3b19 100644
--- a/bsps/shared/dev/rtc/m48t08_reg.c
+++ b/bsps/shared/dev/rtc/m48t08_reg.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the m48t08 chip if accesses to the chip are as follows:
@@ -8,9 +10,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems.h>
diff --git a/bsps/shared/dev/rtc/m48t08_reg2.c b/bsps/shared/dev/rtc/m48t08_reg2.c
index 87d2041946..b469f9258f 100644
--- a/bsps/shared/dev/rtc/m48t08_reg2.c
+++ b/bsps/shared/dev/rtc/m48t08_reg2.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the m48t08 chip if accesses to the chip are as follows:
@@ -8,9 +10,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#define _M48T08_MULTIPLIER 2
diff --git a/bsps/shared/dev/rtc/m48t08_reg4.c b/bsps/shared/dev/rtc/m48t08_reg4.c
index 2203249503..069664b3ba 100644
--- a/bsps/shared/dev/rtc/m48t08_reg4.c
+++ b/bsps/shared/dev/rtc/m48t08_reg4.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the m48t08 chip if accesses to the chip are as follows:
@@ -8,9 +10,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#define _M48T08_MULTIPLIER 4
diff --git a/bsps/shared/dev/rtc/m48t08_reg8.c b/bsps/shared/dev/rtc/m48t08_reg8.c
index 83044d752b..8e1bccbf14 100644
--- a/bsps/shared/dev/rtc/m48t08_reg8.c
+++ b/bsps/shared/dev/rtc/m48t08_reg8.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the m48t08 chip if accesses to the chip are as follows:
@@ -8,9 +10,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#define _M48T08_MULTIPLIER 8
diff --git a/bsps/shared/dev/rtc/mc146818a.c b/bsps/shared/dev/rtc/mc146818a.c
index 2720ce5e8a..a048c6c606 100644
--- a/bsps/shared/dev/rtc/mc146818a.c
+++ b/bsps/shared/dev/rtc/mc146818a.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file interfaces with the real-time clock found in
* a Motorola MC146818A (common on PC hardware)
@@ -16,9 +18,26 @@
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems.h>
#include <libchip/rtc.h>
diff --git a/bsps/shared/dev/rtc/mc146818a_ioreg.c b/bsps/shared/dev/rtc/mc146818a_ioreg.c
index 4c438a516a..e51279ed18 100644
--- a/bsps/shared/dev/rtc/mc146818a_ioreg.c
+++ b/bsps/shared/dev/rtc/mc146818a_ioreg.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the MC146818A chip if accesses to the chip are as follows:
@@ -11,9 +13,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems.h>
diff --git a/bsps/shared/dev/rtc/mcp7940m.c b/bsps/shared/dev/rtc/mcp7940m.c
new file mode 100644
index 0000000000..1abc5faaad
--- /dev/null
+++ b/bsps/shared/dev/rtc/mcp7940m.c
@@ -0,0 +1,361 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2023 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Note: This driver implements only the basic RTC functionality of the
+ * MCP7940M. It tries not to touch any register fields except for the basic
+ * date/time fields in the get/set time functions. That way it should be
+ * possible to re-use the driver for similar RTCs by just replacing the
+ * initialization function. Suggested method for that: Add a field to the struct
+ * mcp7940m_rtc with a function pointer that points to the initialization
+ * function.
+ *
+ * All flags that are considered MCP7940M specific have a MCP7940M in the name.
+ *
+ * Only 24 hour format is supported. If this driver is the only ones who write
+ * the RTC, that shouldn't be a problem.
+ *
+ * The weekday register is not used. It has a user-defined representation anyway
+ * and therefore doesn't really matter.
+ */
+
+#include <dev/i2c/i2c.h>
+#include <libchip/mcp7940m-rtc.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/todimpl.h>
+
+#include <fcntl.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define REG_RTCSEC 0x00u
+
+#define RTCSEC_SECBCD_SHIFT 0u
+#define RTCSEC_SECBCD_MASK (0x7fu << RTCSEC_SECBCD_SHIFT)
+#define RTCSEC_SECBCD(x) (((x) << RTCSEC_SECBCD_SHIFT) & RTCSEC_SECBCD_MASK)
+#define RTCSEC_SECBCD_GET(x) (((x) & RTCSEC_SECBCD_MASK) >> RTCSEC_SECBCD_SHIFT)
+
+#define MCP7940M_RTCSEC_ST (0x01u << 7)
+
+#define REG_RTCMIN 0x01
+
+#define RTCMIN_MINBCD_SHIFT 0u
+#define RTCMIN_MINBCD_MASK (0x7fu << RTCMIN_MINBCD_SHIFT)
+#define RTCMIN_MINBCD(x) (((x) << RTCMIN_MINBCD_SHIFT) & RTCMIN_MINBCD_MASK)
+#define RTCMIN_MINBCD_GET(x) (((x) & RTCMIN_MINBCD_MASK) >> RTCMIN_MINBCD_SHIFT)
+
+#define REG_RTCHOUR 0x02
+
+#define RTCHOUR_HRBCD12_SHIFT 0u
+#define RTCHOUR_HRBCD12_MASK (0x1fu << RTCHOUR_HRBCD12_SHIFT)
+#define RTCHOUR_HRBCD12(x) (((x) << RTCHOUR_HRBCD12_SHIFT) & RTCHOUR_HRBCD12_MASK)
+#define RTCHOUR_HRBCD12_GET(x) (((x) & RTCHOUR_HRBCD12_MASK) >> RTCHOUR_HRBCD12_SHIFT)
+
+#define RTCHOUR_HRBCD24_SHIFT 0u
+#define RTCHOUR_HRBCD24_MASK (0x3fu << RTCHOUR_HRBCD24_SHIFT)
+#define RTCHOUR_HRBCD24(x) (((x) << RTCHOUR_HRBCD24_SHIFT) & RTCHOUR_HRBCD24_MASK)
+#define RTCHOUR_HRBCD24_GET(x) (((x) & RTCHOUR_HRBCD24_MASK) >> RTCHOUR_HRBCD24_SHIFT)
+
+#define RTCHOUR_AMPM (0x01u << 5)
+#define RTCHOUR_1224 (0x01u << 6)
+
+#define REG_RTCWKDAY 0x03
+
+#define RTCWKDAY_WKDAY_SHIFT 0u
+#define RTCWKDAY_WKDAY_MASK (0x7u << RTCWKDAY_WKDAY_SHIFT)
+#define RTCWKDAY_WKDAY(x) (((x) << RTCWKDAY_WKDAY_SHIFT) & RTCWKDAY_WKDAY_MASK)
+#define RTCWKDAY_WKDAY_GET(x) (((x) & RTCWKDAY_WKDAY_MASK) >> RTCWKDAY_WKDAY_SHIFT)
+
+#define REG_RTCDATE 0x04
+
+#define RTCDATE_DATEBCD_SHIFT 0u
+#define RTCDATE_DATEBCD_MASK (0x3fu << RTCDATE_DATEBCD_SHIFT)
+#define RTCDATE_DATEBCD(x) (((x) << RTCDATE_DATEBCD_SHIFT) & RTCDATE_DATEBCD_MASK)
+#define RTCDATE_DATEBCD_GET(x) (((x) & RTCDATE_DATEBCD_MASK) >> RTCDATE_DATEBCD_SHIFT)
+
+#define REG_RTCMTH 0x05
+
+#define RTCMTH_MTHBCD_SHIFT 0u
+#define RTCMTH_MTHBCD_MASK (0x1fu << RTCMTH_MTHBCD_SHIFT)
+#define RTCMTH_MTHBCD(x) (((x) << RTCMTH_MTHBCD_SHIFT) & RTCMTH_MTHBCD_MASK)
+#define RTCMTH_MTHBCD_GET(x) (((x) & RTCMTH_MTHBCD_MASK) >> RTCMTH_MTHBCD_SHIFT)
+
+#define MCP7940M_RTCMTH_LPYR (0x01u << 5)
+
+#define REG_RTCYEAR 0x06
+
+#define RTCYEAR_YRBCD_SHIFT 0u
+#define RTCYEAR_YRBCD_MASK (0xffu << RTCYEAR_YRBCD_SHIFT)
+#define RTCYEAR_YRBCD(x) (((x) << RTCYEAR_YRBCD_SHIFT) & RTCYEAR_YRBCD_MASK)
+#define RTCYEAR_YRBCD_GET(x) (((x) & RTCYEAR_YRBCD_MASK) >> RTCYEAR_YRBCD_SHIFT)
+
+#define REG_MCP7940M_CONTROL 0x07
+
+#define MCP7940M_CONTROL_OUT (0x1u << 7)
+#define MCP7940M_CONTROL_SQWEN (0x1u << 6)
+#define MCP7940M_CONTROL_ALM1EN (0x1u << 5)
+#define MCP7940M_CONTROL_ALM0EN (0x1u << 4)
+#define MCP7940M_CONTROL_EXTOSC (0x1u << 3)
+#define MCP7940M_CONTROL_CRSTRIM (0x1u << 2)
+#define MCP7940M_CONTROL_SQWFS1 (0x1u << 1)
+#define MCP7940M_CONTROL_SQWFS0 (0x1u << 0)
+
+static inline uint8_t bcd_to_bin(uint8_t bcd)
+{
+ uint8_t bin;
+ bin = bcd & 0x0f;
+ bin += ((bcd >> 4) & 0x0f) * 10;
+ return bin;
+}
+
+static inline uint8_t bin_to_bcd(uint8_t bin)
+{
+ uint8_t bcd;
+ bcd = bin % 10;
+ bcd |= (bin / 10) << 4;
+ return bcd;
+}
+
+static struct mcp7940m_rtc *mcp7940m_get_context(int minor)
+{
+ return (struct mcp7940m_rtc *) RTC_Table[minor].pDeviceParams;
+}
+
+static int mcp7940m_i2c_read(
+ struct mcp7940m_rtc *ctx,
+ uint8_t addr,
+ uint8_t *buf,
+ size_t len
+)
+{
+ int fd;
+ int rv;
+ struct i2c_msg msgs[] = {{
+ .addr = ctx->i2c_addr,
+ .flags = 0,
+ .buf = &addr,
+ .len = 1,
+ }, {
+ .addr = ctx->i2c_addr,
+ .flags = I2C_M_RD,
+ .buf = buf,
+ .len = len,
+ }};
+ struct i2c_rdwr_ioctl_data payload = {
+ .msgs = msgs,
+ .nmsgs = sizeof(msgs)/sizeof(msgs[0]),
+ };
+
+ fd = open(ctx->i2c_bus_path, O_RDWR);
+ if (fd < 0) {
+ return fd;
+ }
+
+ rv = ioctl(fd, I2C_RDWR, &payload);
+
+ close(fd);
+
+ return rv;
+}
+
+static int mcp7940m_i2c_write(
+ struct mcp7940m_rtc *ctx,
+ uint8_t addr,
+ const uint8_t *buf,
+ size_t len
+)
+{
+ int fd;
+ int rv;
+ uint8_t writebuf[len + 1];
+ struct i2c_msg msgs[] = {{
+ .addr = ctx->i2c_addr,
+ .flags = 0,
+ .buf = writebuf,
+ .len = len + 1,
+ }};
+ struct i2c_rdwr_ioctl_data payload = {
+ .msgs = msgs,
+ .nmsgs = sizeof(msgs)/sizeof(msgs[0]),
+ };
+
+ writebuf[0] = addr;
+ memcpy(&writebuf[1], buf, len);
+
+ fd = open(ctx->i2c_bus_path, O_RDWR);
+ if (fd < 0) {
+ return fd;
+ }
+
+ rv = ioctl(fd, I2C_RDWR, &payload);
+
+ close(fd);
+
+ return rv;
+}
+
+static int mcp7940m_initialize_once(struct mcp7940m_rtc *ctx)
+{
+ uint8_t reg;
+ ssize_t rv;
+
+ if (ctx->initialized) {
+ return 0;
+ }
+
+ /*
+ * Make sure that all alarms and outputs are disabled. Enable or disable
+ * oscillator.
+ *
+ * This makes sure that we can start with an uninitialized device that has a
+ * random value in the control register.
+ */
+ reg = 0;
+ if (!ctx->crystal) {
+ reg |= MCP7940M_CONTROL_EXTOSC;
+ }
+ rv = mcp7940m_i2c_write(ctx, REG_MCP7940M_CONTROL, &reg, 1);
+
+ if (rv == 0 && ctx->crystal) {
+ rv = mcp7940m_i2c_read(ctx, REG_RTCSEC, &reg, 1);
+ if (rv == 0 && (reg & MCP7940M_RTCSEC_ST) == 0) {
+ reg |= MCP7940M_RTCSEC_ST;
+ rv = mcp7940m_i2c_write(ctx, REG_RTCSEC, &reg, 1);
+ }
+ }
+
+ ctx->initialized = true;
+
+ return rv;
+}
+
+static int mcp7940m_get_time(int minor, rtems_time_of_day *time)
+{
+ int rv = 0;
+ uint8_t buf[REG_RTCYEAR + 1];
+ struct mcp7940m_rtc *ctx = mcp7940m_get_context(minor);
+
+ if (!_System_state_Is_up(_System_state_Get())) {
+ return -1;
+ }
+
+ rtems_mutex_lock(&ctx->mutex);
+
+ rv = mcp7940m_initialize_once(ctx);
+
+ if (rv == 0) {
+ rv = mcp7940m_i2c_read(ctx, REG_RTCSEC, buf, sizeof(buf));
+ }
+
+ if (rv == 0) {
+ unsigned year = bcd_to_bin(RTCYEAR_YRBCD_GET(buf[REG_RTCYEAR])) +
+ (TOD_BASE_YEAR / 100 * 100);
+ if (year < TOD_BASE_YEAR) {
+ year += 100;
+ }
+ time->year = year;
+ time->month = bcd_to_bin(RTCMTH_MTHBCD_GET(buf[REG_RTCMTH]));
+ time->day = bcd_to_bin(RTCDATE_DATEBCD_GET(buf[REG_RTCDATE]));
+ time->hour = bcd_to_bin(RTCHOUR_HRBCD24_GET(buf[REG_RTCHOUR]));
+ time->minute = bcd_to_bin(RTCMIN_MINBCD_GET(buf[REG_RTCMIN]));
+ time->second = bcd_to_bin(RTCSEC_SECBCD_GET(buf[REG_RTCSEC]));
+ time->ticks = 0;
+ }
+
+ rtems_mutex_unlock(&ctx->mutex);
+
+ return rv;
+}
+
+static int mcp7940m_set_time(int minor, const rtems_time_of_day *time)
+{
+ int rv = 0;
+ uint8_t buf[REG_RTCYEAR + 1];
+ struct mcp7940m_rtc *ctx = mcp7940m_get_context(minor);
+
+ if (!_System_state_Is_up(_System_state_Get())) {
+ return -1;
+ }
+
+ rtems_mutex_lock(&ctx->mutex);
+
+ rv = mcp7940m_initialize_once(ctx);
+
+ if (rv == 0) {
+ rv = mcp7940m_i2c_read(ctx, REG_RTCSEC, buf, sizeof(buf));
+ }
+
+ if (rv == 0) {
+ /* Make sure weekday is not 0 (out of range). Otherwise it's not used. */
+ if (RTCWKDAY_WKDAY_GET(buf[REG_RTCWKDAY]) < 1) {
+ buf[REG_RTCWKDAY] &= ~RTCWKDAY_WKDAY_MASK;
+ buf[REG_RTCWKDAY] |= RTCWKDAY_WKDAY(1);
+ }
+
+ buf[REG_RTCYEAR] &= ~RTCYEAR_YRBCD_MASK;
+ buf[REG_RTCYEAR] |= RTCYEAR_YRBCD(bin_to_bcd(time->year % 100));
+
+ buf[REG_RTCMTH] &= ~RTCMTH_MTHBCD_MASK;
+ buf[REG_RTCMTH] |= RTCMTH_MTHBCD(bin_to_bcd(time->month));
+
+ buf[REG_RTCDATE] &= ~RTCDATE_DATEBCD_MASK;
+ buf[REG_RTCDATE] |= RTCDATE_DATEBCD(bin_to_bcd(time->day));
+
+ buf[REG_RTCHOUR] &= ~(RTCHOUR_HRBCD24_MASK | RTCHOUR_1224);
+ buf[REG_RTCHOUR] |= RTCHOUR_HRBCD24(bin_to_bcd(time->hour));
+
+ buf[REG_RTCMIN] &= ~RTCMIN_MINBCD_MASK;
+ buf[REG_RTCMIN] |= RTCMIN_MINBCD(bin_to_bcd(time->minute));
+
+ buf[REG_RTCSEC] &= ~RTCSEC_SECBCD_MASK;
+ buf[REG_RTCSEC] |= RTCSEC_SECBCD(bin_to_bcd(time->second));
+
+ rv = mcp7940m_i2c_write(ctx, REG_RTCSEC, buf, sizeof(buf));
+ }
+
+ rtems_mutex_unlock(&ctx->mutex);
+
+ return rv;
+}
+
+static void mcp7940m_init(int minor)
+{
+ (void) minor;
+}
+
+bool rtc_mcp7940m_probe(int minor)
+{
+ return true;
+}
+
+const rtc_fns rtc_mcp7940m_fns = {
+ .deviceInitialize = mcp7940m_init,
+ .deviceGetTime = mcp7940m_get_time,
+ .deviceSetTime = mcp7940m_set_time,
+};
diff --git a/bsps/shared/dev/rtc/rtcprobe.c b/bsps/shared/dev/rtc/rtcprobe.c
index 71472ffd7c..0d85831d62 100644
--- a/bsps/shared/dev/rtc/rtcprobe.c
+++ b/bsps/shared/dev/rtc/rtcprobe.c
@@ -1,12 +1,31 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains the default Real-Time Clock probe routine.
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems.h>
diff --git a/bsps/shared/dev/serial/arm-pl011.c b/bsps/shared/dev/serial/arm-pl011.c
index 6822f71592..e9a8e3f5a4 100644
--- a/bsps/shared/dev/serial/arm-pl011.c
+++ b/bsps/shared/dev/serial/arm-pl011.c
@@ -1,9 +1,28 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
- * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved.
+ * Copyright (C) 2013, 2014 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <dev/serial/arm-pl011.h>
diff --git a/bsps/shared/dev/serial/console-output-char.c b/bsps/shared/dev/serial/console-output-char.c
index 3577969fd4..477fd1ffde 100644
--- a/bsps/shared/dev/serial/console-output-char.c
+++ b/bsps/shared/dev/serial/console-output-char.c
@@ -1,9 +1,28 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
- * Copyright (c) 2013 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2013 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <libchip/serial.h>
diff --git a/bsps/shared/dev/serial/console-polled.c b/bsps/shared/dev/serial/console-polled.c
index 26c9817bdb..37ad5b8f18 100644
--- a/bsps/shared/dev/serial/console-polled.c
+++ b/bsps/shared/dev/serial/console-polled.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains the hardware independent portion of a polled
* console device driver. If a BSP chooses to use this, then it
@@ -8,9 +10,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <bsp.h>
@@ -94,7 +113,7 @@ rtems_device_driver console_open(
NULL, /* setAttributes */
NULL, /* stopRemoteTx */
NULL, /* startRemoteTx */
- 0 /* outputUsesInterrupts */
+ TERMIOS_POLLED /* outputUsesInterrupts */
};
assert( minor == 0 );
diff --git a/bsps/shared/dev/serial/console-termios-init.c b/bsps/shared/dev/serial/console-termios-init.c
index eb565c6809..c144549cb4 100644
--- a/bsps/shared/dev/serial/console-termios-init.c
+++ b/bsps/shared/dev/serial/console-termios-init.c
@@ -1,9 +1,28 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
- * Copyright (c) 2014, 2016 embedded brains GmbH. All rights reserved.
+ * Copyright (C) 2014, 2016 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <bsp/console-termios.h>
diff --git a/bsps/shared/dev/serial/console-termios.c b/bsps/shared/dev/serial/console-termios.c
index 9136c8d48f..bdea1a0284 100644
--- a/bsps/shared/dev/serial/console-termios.c
+++ b/bsps/shared/dev/serial/console-termios.c
@@ -1,9 +1,28 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
- * Copyright (c) 2014, 2016 embedded brains GmbH. All rights reserved.
+ * Copyright (C) 2014, 2016 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems/console.h>
diff --git a/bsps/shared/dev/serial/getserialmouseps2.c b/bsps/shared/dev/serial/getserialmouseps2.c
index 375e383fac..451a62d716 100644
--- a/bsps/shared/dev/serial/getserialmouseps2.c
+++ b/bsps/shared/dev/serial/getserialmouseps2.c
@@ -1,9 +1,28 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
- * Copyright (c) 2013 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2013 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems/serial_mouse.h>
diff --git a/bsps/shared/dev/serial/legacy-console-control.c b/bsps/shared/dev/serial/legacy-console-control.c
index 01c6793c67..36497b27be 100644
--- a/bsps/shared/dev/serial/legacy-console-control.c
+++ b/bsps/shared/dev/serial/legacy-console-control.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
*
@@ -14,9 +16,26 @@
* COPYRIGHT (c) 1989-2011.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <bsp.h>
diff --git a/bsps/shared/dev/serial/legacy-console-select.c b/bsps/shared/dev/serial/legacy-console-select.c
index 8d545e7737..d398503406 100644
--- a/bsps/shared/dev/serial/legacy-console-select.c
+++ b/bsps/shared/dev/serial/legacy-console-select.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
*
@@ -13,9 +15,26 @@
* COPYRIGHT (c) 2011.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <bsp.h>
diff --git a/bsps/shared/dev/serial/legacy-console.c b/bsps/shared/dev/serial/legacy-console.c
index 998e4aa6fd..698439b247 100644
--- a/bsps/shared/dev/serial/legacy-console.c
+++ b/bsps/shared/dev/serial/legacy-console.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
*
@@ -10,9 +12,26 @@
* COPYRIGHT (c) 1989-2011, 2016.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <bsp.h>
@@ -215,7 +234,11 @@ rtems_device_driver console_open(
Callbacks.stopRemoteTx = NULL;
Callbacks.startRemoteTx = NULL;
}
- Callbacks.outputUsesInterrupts = cptr->pDeviceFns->deviceOutputUsesInterrupts;
+ if (cptr->pDeviceFns->deviceOutputUsesInterrupts) {
+ Callbacks.outputUsesInterrupts = TERMIOS_IRQ_DRIVEN;
+ } else {
+ Callbacks.outputUsesInterrupts = TERMIOS_POLLED;
+ }
/* XXX what about
* Console_Port_Tbl[minor].ulMargin,
diff --git a/bsps/shared/dev/serial/legacy-console.h b/bsps/shared/dev/serial/legacy-console.h
index 3855e83100..424b55c574 100644
--- a/bsps/shared/dev/serial/legacy-console.h
+++ b/bsps/shared/dev/serial/legacy-console.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
*
@@ -10,9 +12,26 @@
* COPYRIGHT (c) 1989-2011, 2016.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _PC386_CONSOLE_PRIVATE_h
diff --git a/bsps/shared/dev/serial/mc68681.c b/bsps/shared/dev/serial/mc68681.c
index f4ddbd6a50..62f5cd1fbf 100644
--- a/bsps/shared/dev/serial/mc68681.c
+++ b/bsps/shared/dev/serial/mc68681.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains the termios TTY driver for the Motorola MC68681.
*
@@ -9,9 +11,26 @@
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems.h>
diff --git a/bsps/shared/dev/serial/mc68681_p.h b/bsps/shared/dev/serial/mc68681_p.h
index 4623276303..eee7613508 100644
--- a/bsps/shared/dev/serial/mc68681_p.h
+++ b/bsps/shared/dev/serial/mc68681_p.h
@@ -1,11 +1,30 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MC68681_P_H_
diff --git a/bsps/shared/dev/serial/mc68681_reg.c b/bsps/shared/dev/serial/mc68681_reg.c
index fb92b8fcd3..a1a70ba2e6 100644
--- a/bsps/shared/dev/serial/mc68681_reg.c
+++ b/bsps/shared/dev/serial/mc68681_reg.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the mc68681 chip if accesses to the chip are as follows:
@@ -8,9 +10,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems.h>
diff --git a/bsps/shared/dev/serial/mc68681_reg2.c b/bsps/shared/dev/serial/mc68681_reg2.c
index 0e0121eb40..4cd79d93e1 100644
--- a/bsps/shared/dev/serial/mc68681_reg2.c
+++ b/bsps/shared/dev/serial/mc68681_reg2.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the mc68681 chip if accesses to the chip are as follows:
@@ -8,9 +10,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#define _MC68681_MULTIPLIER 2
diff --git a/bsps/shared/dev/serial/mc68681_reg4.c b/bsps/shared/dev/serial/mc68681_reg4.c
index e9dd94ce4b..1d46d1a121 100644
--- a/bsps/shared/dev/serial/mc68681_reg4.c
+++ b/bsps/shared/dev/serial/mc68681_reg4.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the mc68681 chip if accesses to the chip are as follows:
@@ -8,9 +10,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#define _MC68681_MULTIPLIER 4
diff --git a/bsps/shared/dev/serial/mc68681_reg8.c b/bsps/shared/dev/serial/mc68681_reg8.c
index 402c2ffe1b..e7268b0304 100644
--- a/bsps/shared/dev/serial/mc68681_reg8.c
+++ b/bsps/shared/dev/serial/mc68681_reg8.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the mc68681 chip if accesses to the chip are as follows:
@@ -8,9 +10,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#define _MC68681_MULTIPLIER 8
diff --git a/bsps/shared/dev/serial/printk-dummy.c b/bsps/shared/dev/serial/printk-dummy.c
index 8273edb83a..4febd8832f 100644
--- a/bsps/shared/dev/serial/printk-dummy.c
+++ b/bsps/shared/dev/serial/printk-dummy.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
* @brief Stub printk() support
@@ -10,9 +12,26 @@
* COPYRIGHT (c) 1989-2014.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
/*
diff --git a/bsps/shared/dev/serial/uart-output-char.c b/bsps/shared/dev/serial/uart-output-char.c
index ecfe325b5f..6ec58a6588 100644
--- a/bsps/shared/dev/serial/uart-output-char.c
+++ b/bsps/shared/dev/serial/uart-output-char.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
*
@@ -7,11 +9,28 @@
*/
/*
- * Copyright (c) 2010-2011 embedded brains GmbH. All rights reserved.
+ * Copyright (C) 2010, 2011 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems/bspIo.h>
diff --git a/bsps/shared/dev/serial/z85c30_reg.c b/bsps/shared/dev/serial/z85c30_reg.c
index 6e7b5d3494..ecc4074538 100644
--- a/bsps/shared/dev/serial/z85c30_reg.c
+++ b/bsps/shared/dev/serial/z85c30_reg.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* This file contains a typical set of register access routines which may be
* used with the z85c30 chip if accesses to the chip are as follows:
@@ -7,9 +9,26 @@
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
#include <rtems.h>
diff --git a/bsps/shared/dev/serial/zynq-uart-kernel-io.c b/bsps/shared/dev/serial/zynq-uart-kernel-io.c
new file mode 100644
index 0000000000..61b1043cd2
--- /dev/null
+++ b/bsps/shared/dev/serial/zynq-uart-kernel-io.c
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup zynq_uart
+ *
+ * @brief This source file contains the definition of ::BSP_output_char and
+ * ::BSP_poll_char.
+ */
+
+/*
+ * Copyright (C) 2013, 2024 embedded brains GmbH & Co. KG
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <rtems/bspIo.h>
+
+#include <bsp.h>
+#include <dev/serial/zynq-uart-regs.h>
+#include <rtems/sysinit.h>
+
+static void zynq_uart_kernel_output_char(char c)
+{
+ volatile zynq_uart *regs =
+ (volatile zynq_uart *) ZYNQ_UART_KERNEL_IO_BASE_ADDR;
+
+ zynq_uart_write_char_polled(regs, c);
+}
+
+static int zynq_uart_kernel_poll_char(void)
+{
+ volatile zynq_uart *regs =
+ (volatile zynq_uart *) ZYNQ_UART_KERNEL_IO_BASE_ADDR;
+
+ return zynq_uart_read_char_polled(regs);
+}
+
+static void zynq_uart_kernel_early_init(char c);
+
+static void zynq_uart_kernel_init(void)
+{
+ volatile zynq_uart *regs =
+ (volatile zynq_uart *) ZYNQ_UART_KERNEL_IO_BASE_ADDR;
+
+ if (BSP_output_char != zynq_uart_kernel_early_init) {
+ return;
+ }
+
+ zynq_uart_initialize(regs);
+ BSP_output_char = zynq_uart_kernel_output_char;
+}
+
+static void zynq_uart_kernel_early_init(char c)
+{
+ zynq_uart_kernel_init();
+ zynq_uart_kernel_output_char(c);
+}
+
+BSP_output_char_function_type BSP_output_char = zynq_uart_kernel_early_init;
+
+BSP_polling_getchar_function_type BSP_poll_char = zynq_uart_kernel_poll_char;
+
+RTEMS_SYSINIT_ITEM(
+ zynq_uart_kernel_init,
+ RTEMS_SYSINIT_BSP_START,
+ RTEMS_SYSINIT_ORDER_LAST_BUT_5
+);
diff --git a/bsps/shared/dev/serial/zynq-uart-polled.c b/bsps/shared/dev/serial/zynq-uart-polled.c
index 6865fa8d6f..dbf75539f6 100644
--- a/bsps/shared/dev/serial/zynq-uart-polled.c
+++ b/bsps/shared/dev/serial/zynq-uart-polled.c
@@ -1,7 +1,16 @@
-/*
- * SPDX-License-Identifier: BSD-2-Clause
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
*
- * Copyright (C) 2013, 2017 embedded brains GmbH
+ * @ingroup RTEMSBSPsARMZynq
+ *
+ * @brief This source file contains the implementation of the polled Zynq UART
+ * support.
+ */
+
+/*
+ * Copyright (C) 2013, 2017 embedded brains GmbH & Co. KG
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -115,10 +124,8 @@ int zynq_cal_baud_rate(uint32_t baudrate,
return 0;
}
-void zynq_uart_initialize(rtems_termios_device_context *base)
+void zynq_uart_initialize(volatile zynq_uart *regs)
{
- zynq_uart_context *ctx = (zynq_uart_context *) base;
- volatile zynq_uart *regs = ctx->regs;
uint32_t brgr = 0x3e;
uint32_t bauddiv = 0x6;
uint32_t mode_clks = regs->mode & ZYNQ_UART_MODE_CLKS;
@@ -145,18 +152,15 @@ void zynq_uart_initialize(rtems_termios_device_context *base)
| ZYNQ_UART_MODE_CHRL(ZYNQ_UART_MODE_CHRL_8)
| mode_clks;
- while (zynq_uart_read_polled(base) >= 0) {
+ while (zynq_uart_read_char_polled(regs) >= 0) {
/* Drop */
}
- zynq_uart_reset_tx_flush(ctx);
+ zynq_uart_reset_tx_flush(regs);
}
-int zynq_uart_read_polled(rtems_termios_device_context *base)
+int zynq_uart_read_char_polled(volatile zynq_uart *regs)
{
- zynq_uart_context *ctx = (zynq_uart_context *) base;
- volatile zynq_uart *regs = ctx->regs;
-
if ((regs->channel_sts & ZYNQ_UART_CHANNEL_STS_REMPTY) != 0) {
return -1;
} else {
@@ -164,14 +168,8 @@ int zynq_uart_read_polled(rtems_termios_device_context *base)
}
}
-void zynq_uart_write_polled(
- rtems_termios_device_context *base,
- char c
-)
+void zynq_uart_write_char_polled(volatile zynq_uart *regs, char c)
{
- zynq_uart_context *ctx = (zynq_uart_context *) base;
- volatile zynq_uart *regs = ctx->regs;
-
while ((regs->channel_sts & ZYNQ_UART_CHANNEL_STS_TNFUL) != 0) {
/* Wait */
}
@@ -179,13 +177,12 @@ void zynq_uart_write_polled(
regs->tx_rx_fifo = ZYNQ_UART_TX_RX_FIFO_FIFO(c);
}
-void zynq_uart_reset_tx_flush(zynq_uart_context *ctx)
+void zynq_uart_reset_tx_flush(volatile zynq_uart *regs)
{
- volatile zynq_uart *regs = ctx->regs;
- int c = 4;
+ int c = 4;
while (c-- > 0)
- zynq_uart_write_polled(&ctx->base, '\r');
+ zynq_uart_write_char_polled(regs, '\r');
while ((regs->channel_sts & ZYNQ_UART_CHANNEL_STS_TEMPTY) == 0 ||
(regs->channel_sts & ZYNQ_UART_CHANNEL_STS_TACTIVE) != 0) {
diff --git a/bsps/shared/dev/serial/zynq-uart.c b/bsps/shared/dev/serial/zynq-uart.c
index 8ff1d25da0..0489288271 100644
--- a/bsps/shared/dev/serial/zynq-uart.c
+++ b/bsps/shared/dev/serial/zynq-uart.c
@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (C) 2013, 2017 embedded brains GmbH
+ * Copyright (C) 2013, 2017 embedded brains GmbH & Co. KG
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,6 +28,7 @@
#include <dev/serial/zynq-uart.h>
#include <dev/serial/zynq-uart-regs.h>
#include <bsp/irq.h>
+#include <rtems/termiostypes.h>
#include <bspopts.h>
@@ -66,14 +67,14 @@ static bool zynq_uart_first_open(
rtems_libio_open_close_args_t *args
)
{
-#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS
zynq_uart_context *ctx = (zynq_uart_context *) base;
volatile zynq_uart *regs = ctx->regs;
+#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS
rtems_status_code sc;
#endif
rtems_termios_set_initial_baud(tty, ZYNQ_UART_DEFAULT_BAUD);
- zynq_uart_initialize(base);
+ zynq_uart_initialize(regs);
#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS
regs->rx_fifo_trg_lvl = 1;
@@ -108,15 +109,23 @@ static void zynq_uart_last_close(
}
#endif
+#ifndef ZYNQ_CONSOLE_USE_INTERRUPTS
+static int zynq_uart_read_polled(rtems_termios_device_context *base)
+{
+ zynq_uart_context *ctx = (zynq_uart_context *) base;
+ return zynq_uart_read_char_polled(ctx->regs);
+}
+#endif
+
static void zynq_uart_write_support(
rtems_termios_device_context *base,
const char *buf,
size_t len
)
{
-#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS
zynq_uart_context *ctx = (zynq_uart_context *) base;
volatile zynq_uart *regs = ctx->regs;
+#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS
regs->irq_dis = ZYNQ_UART_TEMPTY;
@@ -134,9 +143,9 @@ static void zynq_uart_write_support(
regs->irq_en = ZYNQ_UART_TEMPTY;
}
#else
- ssize_t i;
+ size_t i;
for (i = 0; i < len; ++i) {
- zynq_uart_write_polled(base, buf[i]);
+ zynq_uart_write_char_polled(regs, buf[i]);
}
#endif
}
diff --git a/bsps/shared/dev/spi/VERSION b/bsps/shared/dev/spi/VERSION
new file mode 100644
index 0000000000..a0acb181b6
--- /dev/null
+++ b/bsps/shared/dev/spi/VERSION
@@ -0,0 +1,29 @@
+The information in this file describes the source of the following files in
+bsps/shared/dev/spi/ and bsps/include/dev/spi/:
+
+- xqspipsu_control.c
+- xqspipsu_control.h
+- xqspipsu_flash_config.h
+- xqspipsu_hw.c
+- xqspipsu_hw.h
+- xqspipsu_options.c
+- xqspipsu.c
+- xqspipsu.h
+
+Import from:
+
+https://github.com/Xilinx/embeddedsw.git
+
+commit 8a89579489c88ea5acd23d7d439ac928659c26cf
+Author: msreeram <manikanta.sreeram@xilinx.com>
+AuthorDate: Wed Apr 6 23:24:38 2022 -0600
+Commit: Siva Addepalli <sivaprasad.addepalli@xilinx.com>
+CommitDate: Fri Apr 8 16:47:15 2022 +0530
+
+ update license file for EmbeddedSW 2022.1 release
+
+ Update license file for EmbeddedSW 2022.1 release
+
+ Signed-off-by: Manikanta Sreeram <msreeram@xilinx.com>
+
+ Acked-by : Meena Paleti <meena.paleti@xilinx.com>
diff --git a/bsps/shared/dev/spi/xqspipsu-flash-helper.c b/bsps/shared/dev/spi/xqspipsu-flash-helper.c
new file mode 100644
index 0000000000..10e1066173
--- /dev/null
+++ b/bsps/shared/dev/spi/xqspipsu-flash-helper.c
@@ -0,0 +1,2341 @@
+/******************************************************************************
+* Copyright (C) 2018 - 2022 Xilinx, Inc. All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/**
+ * @file xqspipsu_flash_helper.c
+ *
+ * This file contains flash helper functions for the QSPIPSU driver. It
+ * consists of modified functions from Xilinx's flash example in
+ * examples/xqspipsu_generic_flash_interrupt_example.c of the qspipsu driver.
+ *
+ */
+
+#include "xqspipsu_flash_config.h"
+#include "xqspipsu-flash-helper.h"
+
+#include <rtems.h>
+
+/*
+ * Number of flash pages to be written.
+ */
+#define PAGE_COUNT 32
+
+/*
+ * Max page size to initialize write and read buffer
+ */
+#define MAX_PAGE_SIZE 1024
+
+#define TEST_ADDRESS 0x000000
+
+#define ENTER_4B 1
+#define EXIT_4B 0
+
+u8 ReadCmd;
+u8 WriteCmd;
+u8 StatusCmd;
+u8 SectorEraseCmd;
+u8 FSRFlag;
+
+static int FlashReadID(XQspiPsu *QspiPsuPtr);
+
+static int MultiDieRead(
+ XQspiPsu *QspiPsuPtr,
+ u32 Address,
+ u32 ByteCount,
+ u8 Command,
+ u8 *WriteBfrPtr,
+ u8 *ReadBfrPtr
+);
+
+static u32 GetRealAddr(
+ XQspiPsu *QspiPsuPtr,
+ u32 Address
+);
+
+static int BulkErase(
+ XQspiPsu *QspiPsuPtr,
+ u8 *WriteBfrPtr
+);
+
+static int DieErase(
+ XQspiPsu *QspiPsuPtr,
+ u8 *WriteBfrPtr
+);
+
+static int QspiPsuSetupIntrSystem(
+ XQspiPsu *QspiPsuInstancePtr,
+ u16 QspiPsuIntrId
+);
+
+static void QspiPsuHandler(
+ void *CallBackRef,
+ u32 StatusEvent,
+ unsigned int ByteCount
+);
+
+static int FlashEnterExit4BAddMode(
+ XQspiPsu *QspiPsuPtr,
+ unsigned int Enable
+);
+
+static int FlashEnableQuadMode(XQspiPsu *QspiPsuPtr);
+
+u8 TxBfrPtr;
+u8 ReadBfrPtr[3];
+u32 FlashMake;
+u32 FCTIndex; /* Flash configuration table index */
+
+static XQspiPsu_Msg FlashMsg[5];
+
+/*
+ * The following variables are shared between non-interrupt processing and
+ * interrupt processing such that they must be global.
+ */
+volatile int TransferInProgress;
+
+/*
+ * The following variable tracks any errors that occur during interrupt
+ * processing
+ */
+int Error;
+
+/*
+ * The following variable allows a test value to be added to the values that
+ * are written to the Flash such that unique values can be generated to
+ * guarantee the writes to the Flash were successful
+ */
+int Test = 1;
+
+/*
+ * The following variables are used to read and write to the flash and they
+ * are global to avoid having large buffers on the stack
+ * The buffer size accounts for maximum page size and maximum banks -
+ * for each bank separate read will be performed leading to that many
+ * (overhead+dummy) bytes
+ */
+#ifdef __ICCARM__
+#pragma data_alignment = 32
+u8 ReadBuffer[(PAGE_COUNT * MAX_PAGE_SIZE) + (DATA_OFFSET + DUMMY_SIZE)*8];
+#else
+u8 ReadBuffer[(PAGE_COUNT * MAX_PAGE_SIZE) + (DATA_OFFSET + DUMMY_SIZE)*8] __attribute__ ((aligned(64)));
+#endif
+u8 WriteBuffer[(PAGE_COUNT * MAX_PAGE_SIZE) + DATA_OFFSET];
+u8 CmdBfr[8];
+
+/*
+ * The following constants specify the max amount of data and the size of the
+ * the buffer required to hold the data and overhead to transfer the data to
+ * and from the Flash. Initialized to single flash page size.
+ */
+u32 MaxData = PAGE_COUNT*256;
+
+int QspiPsu_NOR_Initialize(
+ XQspiPsu *QspiPsuInstancePtr,
+ u16 QspiPsuIntrId
+)
+{
+ int Status;
+
+ if (QspiPsuInstancePtr == NULL) {
+ return XST_FAILURE;
+ }
+
+ /*
+ * Connect the QspiPsu device to the interrupt subsystem such that
+ * interrupts can occur. This function is application specific
+ */
+ Status = QspiPsuSetupIntrSystem(QspiPsuInstancePtr, QspiPsuIntrId);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+
+ /*
+ * Setup the handler for the QSPIPSU that will be called from the
+ * interrupt context when an QSPIPSU status occurs, specify a pointer to
+ * the QSPIPSU driver instance as the callback reference
+ * so the handler is able to access the instance data
+ */
+ XQspiPsu_SetStatusHandler(QspiPsuInstancePtr, QspiPsuInstancePtr,
+ (XQspiPsu_StatusHandler) QspiPsuHandler);
+
+ /*
+ * Set Manual Start
+ */
+ XQspiPsu_SetOptions(QspiPsuInstancePtr, XQSPIPSU_MANUAL_START_OPTION);
+
+ /*
+ * Set the prescaler for QSPIPSU clock
+ */
+ XQspiPsu_SetClkPrescaler(QspiPsuInstancePtr, XQSPIPSU_CLK_PRESCALE_8);
+
+ XQspiPsu_SelectFlash(QspiPsuInstancePtr,
+ XQSPIPSU_SELECT_FLASH_CS_LOWER,
+ XQSPIPSU_SELECT_FLASH_BUS_LOWER);
+
+ /*
+ * Read flash ID and obtain all flash related information
+ * It is important to call the read id function before
+ * performing proceeding to any operation, including
+ * preparing the WriteBuffer
+ */
+
+ Status = FlashReadID(QspiPsuInstancePtr);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+
+ /*
+ * Some flash needs to enable Quad mode before using
+ * quad commands.
+ */
+ Status = FlashEnableQuadMode(QspiPsuInstancePtr);
+ if (Status != XST_SUCCESS)
+ return XST_FAILURE;
+
+ /*
+ * Address size and read command selection
+ * Micron flash on REMUS doesn't support these 4B write/erase commands
+ */
+ if(QspiPsuInstancePtr->Config.BusWidth == BUSWIDTH_SINGLE)
+ ReadCmd = FAST_READ_CMD;
+ else if(QspiPsuInstancePtr->Config.BusWidth == BUSWIDTH_DOUBLE)
+ ReadCmd = DUAL_READ_CMD;
+ else
+ ReadCmd = QUAD_READ_CMD;
+
+ WriteCmd = WRITE_CMD;
+ SectorEraseCmd = SEC_ERASE_CMD;
+
+ if ((Flash_Config_Table[FCTIndex].NumDie > 1) &&
+ (FlashMake == MICRON_ID_BYTE0)) {
+ StatusCmd = READ_FLAG_STATUS_CMD;
+ FSRFlag = 1;
+ } else {
+ StatusCmd = READ_STATUS_CMD;
+ FSRFlag = 0;
+ }
+
+ if (Flash_Config_Table[FCTIndex].FlashDeviceSize > SIXTEENMB) {
+ Status = FlashEnterExit4BAddMode(QspiPsuInstancePtr, ENTER_4B);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ if (FlashMake == SPANSION_ID_BYTE0) {
+ if(QspiPsuInstancePtr->Config.BusWidth == BUSWIDTH_SINGLE)
+ ReadCmd = FAST_READ_CMD_4B;
+ else if(QspiPsuInstancePtr->Config.BusWidth == BUSWIDTH_DOUBLE)
+ ReadCmd = DUAL_READ_CMD_4B;
+ else
+ ReadCmd = QUAD_READ_CMD_4B;
+
+ WriteCmd = WRITE_CMD_4B;
+ SectorEraseCmd = SEC_ERASE_CMD_4B;
+ }
+ }
+
+ return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * Callback handler.
+ *
+ * @param CallBackRef is the upper layer callback reference passed back
+ * when the callback function is invoked.
+ * @param StatusEvent is the event that just occurred.
+ * @param ByteCount is the number of bytes transferred up until the event
+ * occurred.
+ *
+ * @return None
+ *
+ * @note None.
+ *
+ *****************************************************************************/
+static void QspiPsuHandler(
+ void *CallBackRef,
+ u32 StatusEvent,
+ unsigned int ByteCount
+)
+{
+ /*
+ * Indicate the transfer on the QSPIPSU bus is no longer in progress
+ * regardless of the status event
+ */
+ TransferInProgress = FALSE;
+
+ /*
+ * If the event was not transfer done, then track it as an error
+ */
+ if (StatusEvent != XST_SPI_TRANSFER_DONE) {
+ Error++;
+ }
+}
+
+int QspiPsu_NOR_RDSFDP(
+ XQspiPsu *QspiPsuPtr,
+ u32 Address,
+ u32 ByteCount,
+ u8 **ReadBfrPtr
+)
+{
+ int Status;
+
+ *ReadBfrPtr = ReadBuffer;
+
+ CmdBfr[COMMAND_OFFSET] = READ_SFDP;
+ CmdBfr[ADDRESS_1_OFFSET] =
+ (u8)((Address & 0xFF0000) >> 16);
+ CmdBfr[ADDRESS_2_OFFSET] =
+ (u8)((Address & 0xFF00) >> 8);
+ CmdBfr[ADDRESS_3_OFFSET] =
+ (u8)(Address & 0xFF);
+
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].TxBfrPtr = CmdBfr;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 4;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = NULL;
+ FlashMsg[1].ByteCount = DUMMY_CLOCKS;
+ FlashMsg[1].Flags = 0;
+
+ FlashMsg[2].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[2].TxBfrPtr = NULL;
+ FlashMsg[2].RxBfrPtr = *ReadBfrPtr;
+ FlashMsg[2].ByteCount = ByteCount;
+ FlashMsg[2].Flags = XQSPIPSU_MSG_FLAG_RX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 3);
+ if (Status != XST_SUCCESS)
+ return XST_FAILURE;
+
+ while (TransferInProgress);
+
+ rtems_cache_invalidate_multiple_data_lines(ReadBuffer, ByteCount);
+ return 0;
+}
+
+int QspiPsu_NOR_RDID(XQspiPsu *QspiPsuPtr, u8 *ReadBfrPtr, u32 ReadLen)
+{
+ int Status;
+
+ /*
+ * Read ID
+ */
+ TxBfrPtr = READ_ID;
+ FlashMsg[0].TxBfrPtr = &TxBfrPtr;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = ReadBfrPtr;
+ FlashMsg[1].ByteCount = ReadLen;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ rtems_cache_invalidate_multiple_data_lines(ReadBfrPtr, ReadLen);
+ return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * Reads the flash ID and identifies the flash in FCT table.
+ *
+ * @param QspiPsuPtr is a pointer to the QSPIPSU driver component to use.
+ *
+ * @return XST_SUCCESS if successful, else XST_FAILURE.
+ *
+ * @note None.
+ *
+ *****************************************************************************/
+static int FlashReadID(XQspiPsu *QspiPsuPtr)
+{
+ u32 ReadId = 0;
+ u32 ReadLen = 3;
+ int Status;
+
+ Status = QspiPsu_NOR_RDID(QspiPsuPtr, ReadBfrPtr, ReadLen);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+
+ /* In case of dual, read both and ensure they are same make/size */
+
+ /*
+ * Deduce flash make
+ */
+ FlashMake = ReadBfrPtr[0];
+
+ ReadId = ((ReadBfrPtr[0] << 16) | (ReadBfrPtr[1] << 8) | ReadBfrPtr[2]);
+ /*
+ * Assign corresponding index in the Flash configuration table
+ */
+ Status = CalculateFCTIndex(ReadId, &FCTIndex);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+
+ return XST_SUCCESS;
+}
+
+int QspiPsu_NOR_Write_Page(
+ XQspiPsu *QspiPsuPtr,
+ u32 Address,
+ u32 ByteCount,
+ u8 *WriteBfrPtr
+)
+{
+ u8 WriteEnableCmd;
+ u8 ReadStatusCmd;
+ u8 FlashStatus[2];
+ u8 WriteCmdBfr[5];
+ u32 RealAddr;
+ u32 CmdByteCount;
+ int Status;
+
+ WriteEnableCmd = WRITE_ENABLE_CMD;
+ /*
+ * Translate address based on type of connection
+ * If stacked assert the slave select based on address
+ */
+ RealAddr = GetRealAddr(QspiPsuPtr, Address);
+
+ /*
+ * Send the write enable command to the Flash so that it can be
+ * written to, this needs to be sent as a separate transfer before
+ * the write
+ */
+ FlashMsg[0].TxBfrPtr = &WriteEnableCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ TransferInProgress = TRUE;
+
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+
+ while (TransferInProgress);
+
+ WriteCmdBfr[COMMAND_OFFSET] = WriteCmd;
+
+ /* To be used only if 4B address program cmd is supported by flash */
+ if (Flash_Config_Table[FCTIndex].FlashDeviceSize > SIXTEENMB) {
+ WriteCmdBfr[ADDRESS_1_OFFSET] =
+ (u8)((RealAddr & 0xFF000000) >> 24);
+ WriteCmdBfr[ADDRESS_2_OFFSET] =
+ (u8)((RealAddr & 0xFF0000) >> 16);
+ WriteCmdBfr[ADDRESS_3_OFFSET] =
+ (u8)((RealAddr & 0xFF00) >> 8);
+ WriteCmdBfr[ADDRESS_4_OFFSET] =
+ (u8)(RealAddr & 0xFF);
+ CmdByteCount = 5;
+ } else {
+ WriteCmdBfr[ADDRESS_1_OFFSET] =
+ (u8)((RealAddr & 0xFF0000) >> 16);
+ WriteCmdBfr[ADDRESS_2_OFFSET] =
+ (u8)((RealAddr & 0xFF00) >> 8);
+ WriteCmdBfr[ADDRESS_3_OFFSET] =
+ (u8)(RealAddr & 0xFF);
+ CmdByteCount = 4;
+ }
+
+ FlashMsg[0].TxBfrPtr = WriteCmdBfr;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = CmdByteCount;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = WriteBfrPtr;
+ FlashMsg[1].RxBfrPtr = NULL;
+ FlashMsg[1].ByteCount = ByteCount;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_TX;
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
+ }
+
+ TransferInProgress = TRUE;
+
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+
+ while (TransferInProgress);
+
+ /*
+ * Wait for the write command to the Flash to be completed, it takes
+ * some time for the data to be written
+ */
+ while (1) {
+ ReadStatusCmd = StatusCmd;
+ FlashMsg[0].TxBfrPtr = &ReadStatusCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = FlashStatus;
+ FlashMsg[1].ByteCount = 2;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
+ }
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ if (FSRFlag) {
+ FlashStatus[1] &= FlashStatus[0];
+ } else {
+ FlashStatus[1] |= FlashStatus[0];
+ }
+ }
+
+ if (FSRFlag) {
+ if ((FlashStatus[1] & 0x80) != 0) {
+ break;
+ }
+ } else {
+ if ((FlashStatus[1] & 0x01) == 0) {
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int QspiPsu_NOR_Write(
+ XQspiPsu *QspiPsuPtr,
+ u32 Address,
+ u32 ByteCount,
+ u8 *WriteBfrPtr
+)
+{
+ int Status;
+ size_t ByteCountRemaining = ByteCount;
+ unsigned char *WriteBfrPartial = WriteBfrPtr;
+ uint32_t AddressPartial = Address;
+ uint32_t PageSize = Flash_Config_Table[FCTIndex].PageSize;
+ if(QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ PageSize *= 2;
+ }
+
+ while (ByteCountRemaining > 0) {
+ /* Get write boundary */
+ size_t WriteChunkLen = RTEMS_ALIGN_UP(AddressPartial + 1, PageSize);
+
+ /* Get offset to write boundary */
+ WriteChunkLen -= (size_t)AddressPartial;
+
+ /* Cap short writes */
+ if (WriteChunkLen > ByteCountRemaining) {
+ WriteChunkLen = ByteCountRemaining;
+ }
+
+ Status = QspiPsu_NOR_Write_Page(
+ QspiPsuPtr,
+ AddressPartial,
+ WriteChunkLen,
+ WriteBfrPartial
+ );
+ if ( Status != XST_SUCCESS ) {
+ return Status;
+ }
+
+ ByteCountRemaining -= WriteChunkLen;
+ AddressPartial += WriteChunkLen;
+ WriteBfrPartial += WriteChunkLen;
+ }
+ return Status;
+}
+
+int QspiPsu_NOR_Erase(
+ XQspiPsu *QspiPsuPtr,
+ u32 Address,
+ u32 ByteCount
+)
+{
+ u8 WriteEnableCmd;
+ u8 ReadStatusCmd;
+ u8 FlashStatus[2];
+ int Sector;
+ u32 RealAddr;
+ u32 NumSect;
+ int Status;
+ u32 SectSize;
+
+ WriteEnableCmd = WRITE_ENABLE_CMD;
+
+ if(QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ SectSize = (Flash_Config_Table[FCTIndex]).SectSize * 2;
+ NumSect = (Flash_Config_Table[FCTIndex]).NumSect;
+ } else if (QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_STACKED) {
+ NumSect = (Flash_Config_Table[FCTIndex]).NumSect * 2;
+ SectSize = (Flash_Config_Table[FCTIndex]).SectSize;
+ } else {
+ SectSize = (Flash_Config_Table[FCTIndex]).SectSize;
+ NumSect = (Flash_Config_Table[FCTIndex]).NumSect;
+ }
+
+ /*
+ * If erase size is same as the total size of the flash, use bulk erase
+ * command or die erase command multiple times as required
+ */
+ if (ByteCount == NumSect * SectSize) {
+
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_STACKED) {
+ XQspiPsu_SelectFlash(QspiPsuPtr,
+ XQSPIPSU_SELECT_FLASH_CS_LOWER,
+ XQSPIPSU_SELECT_FLASH_BUS_LOWER);
+ }
+
+ if (Flash_Config_Table[FCTIndex].NumDie == 1) {
+ /*
+ * Call Bulk erase
+ */
+ BulkErase(QspiPsuPtr, CmdBfr);
+ }
+
+ if (Flash_Config_Table[FCTIndex].NumDie > 1) {
+ /*
+ * Call Die erase
+ */
+ DieErase(QspiPsuPtr, CmdBfr);
+ }
+ /*
+ * If stacked mode, bulk erase second flash
+ */
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_STACKED) {
+
+ XQspiPsu_SelectFlash(QspiPsuPtr,
+ XQSPIPSU_SELECT_FLASH_CS_UPPER,
+ XQSPIPSU_SELECT_FLASH_BUS_LOWER);
+
+ if (Flash_Config_Table[FCTIndex].NumDie == 1) {
+ /*
+ * Call Bulk erase
+ */
+ BulkErase(QspiPsuPtr, CmdBfr);
+ }
+
+ if (Flash_Config_Table[FCTIndex].NumDie > 1) {
+ /*
+ * Call Die erase
+ */
+ DieErase(QspiPsuPtr, CmdBfr);
+ }
+ }
+
+ return 0;
+ }
+
+ /*
+ * If the erase size is less than the total size of the flash, use
+ * sector erase command
+ */
+
+ /*
+ * Calculate no. of sectors to erase based on byte count
+ */
+ u32 SectorStartBase = RTEMS_ALIGN_DOWN(Address, SectSize);
+ u32 SectorEndTop = RTEMS_ALIGN_UP(Address + ByteCount, SectSize);
+ NumSect = (SectorEndTop - SectorStartBase)/SectSize;
+
+ for (Sector = 0; Sector < NumSect; Sector++) {
+
+ /*
+ * Translate address based on type of connection
+ * If stacked assert the slave select based on address
+ */
+ RealAddr = GetRealAddr(QspiPsuPtr, Address);
+
+ /*
+ * Send the write enable command to the Flash so that it can be
+ * written to, this needs to be sent as a separate
+ * transfer before the write
+ */
+ FlashMsg[0].TxBfrPtr = &WriteEnableCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ CmdBfr[COMMAND_OFFSET] = SectorEraseCmd;
+
+ /*
+ * To be used only if 4B address sector erase cmd is
+ * supported by flash
+ */
+ if (Flash_Config_Table[FCTIndex].FlashDeviceSize > SIXTEENMB) {
+ CmdBfr[ADDRESS_1_OFFSET] =
+ (u8)((RealAddr & 0xFF000000) >> 24);
+ CmdBfr[ADDRESS_2_OFFSET] =
+ (u8)((RealAddr & 0xFF0000) >> 16);
+ CmdBfr[ADDRESS_3_OFFSET] =
+ (u8)((RealAddr & 0xFF00) >> 8);
+ CmdBfr[ADDRESS_4_OFFSET] =
+ (u8)(RealAddr & 0xFF);
+ FlashMsg[0].ByteCount = 5;
+ } else {
+ CmdBfr[ADDRESS_1_OFFSET] =
+ (u8)((RealAddr & 0xFF0000) >> 16);
+ CmdBfr[ADDRESS_2_OFFSET] =
+ (u8)((RealAddr & 0xFF00) >> 8);
+ CmdBfr[ADDRESS_3_OFFSET] =
+ (u8)(RealAddr & 0xFF);
+ FlashMsg[0].ByteCount = 4;
+ }
+
+ FlashMsg[0].TxBfrPtr = CmdBfr;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ /*
+ * Wait for the erase command to be completed
+ */
+ while (1) {
+ ReadStatusCmd = StatusCmd;
+ FlashMsg[0].TxBfrPtr = &ReadStatusCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = FlashStatus;
+ FlashMsg[1].ByteCount = 2;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
+ }
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr,
+ FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ if (FSRFlag) {
+ FlashStatus[1] &= FlashStatus[0];
+ } else {
+ FlashStatus[1] |= FlashStatus[0];
+ }
+ }
+
+ if (FSRFlag) {
+ if ((FlashStatus[1] & 0x80) != 0) {
+ break;
+ }
+ } else {
+ if ((FlashStatus[1] & 0x01) == 0) {
+ break;
+ }
+ }
+ }
+ Address += SectSize;
+ }
+
+ return 0;
+}
+
+int QspiPsu_NOR_Read(
+ XQspiPsu *QspiPsuPtr,
+ u32 Address,
+ u32 ByteCount,
+ u8 **ReadBfrPtr
+)
+{
+ u32 RealAddr;
+ u32 DiscardByteCnt;
+ u32 FlashMsgCnt;
+ int Status;
+
+ *ReadBfrPtr = ReadBuffer;
+
+ /* Check die boundary conditions if required for any flash */
+ if (Flash_Config_Table[FCTIndex].NumDie > 1) {
+
+ Status = MultiDieRead(QspiPsuPtr, Address, ByteCount, ReadCmd,
+ CmdBfr, *ReadBfrPtr);
+ if (Status != XST_SUCCESS)
+ return XST_FAILURE;
+ } else {
+ /* For Dual Stacked, split and read for boundary crossing */
+ /*
+ * Translate address based on type of connection
+ * If stacked assert the slave select based on address
+ */
+ RealAddr = GetRealAddr(QspiPsuPtr, Address);
+
+ CmdBfr[COMMAND_OFFSET] = ReadCmd;
+ if (Flash_Config_Table[FCTIndex].FlashDeviceSize > SIXTEENMB) {
+ CmdBfr[ADDRESS_1_OFFSET] =
+ (u8)((RealAddr & 0xFF000000) >> 24);
+ CmdBfr[ADDRESS_2_OFFSET] =
+ (u8)((RealAddr & 0xFF0000) >> 16);
+ CmdBfr[ADDRESS_3_OFFSET] =
+ (u8)((RealAddr & 0xFF00) >> 8);
+ CmdBfr[ADDRESS_4_OFFSET] =
+ (u8)(RealAddr & 0xFF);
+ DiscardByteCnt = 5;
+ } else {
+ CmdBfr[ADDRESS_1_OFFSET] =
+ (u8)((RealAddr & 0xFF0000) >> 16);
+ CmdBfr[ADDRESS_2_OFFSET] =
+ (u8)((RealAddr & 0xFF00) >> 8);
+ CmdBfr[ADDRESS_3_OFFSET] =
+ (u8)(RealAddr & 0xFF);
+ DiscardByteCnt = 4;
+ }
+
+ FlashMsg[0].TxBfrPtr = CmdBfr;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = DiscardByteCnt;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsgCnt = 1;
+
+ /* It is recommended to have a separate entry for dummy */
+ if (ReadCmd == FAST_READ_CMD || ReadCmd == DUAL_READ_CMD ||
+ ReadCmd == QUAD_READ_CMD || ReadCmd == FAST_READ_CMD_4B ||
+ ReadCmd == DUAL_READ_CMD_4B ||
+ ReadCmd == QUAD_READ_CMD_4B) {
+ /* Update Dummy cycles as per flash specs for QUAD IO */
+
+ /*
+ * It is recommended that Bus width value during dummy
+ * phase should be same as data phase
+ */
+ if (ReadCmd == FAST_READ_CMD ||
+ ReadCmd == FAST_READ_CMD_4B) {
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ }
+
+ if (ReadCmd == DUAL_READ_CMD ||
+ ReadCmd == DUAL_READ_CMD_4B) {
+ FlashMsg[1].BusWidth =
+ XQSPIPSU_SELECT_MODE_DUALSPI;
+ }
+
+ if (ReadCmd == QUAD_READ_CMD ||
+ ReadCmd == QUAD_READ_CMD_4B) {
+ FlashMsg[1].BusWidth =
+ XQSPIPSU_SELECT_MODE_QUADSPI;
+ }
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = NULL;
+ FlashMsg[1].ByteCount = DUMMY_CLOCKS;
+ FlashMsg[1].Flags = 0;
+
+ FlashMsgCnt++;
+ }
+
+ /* Dummy cycles need to be changed as per flash specs
+ * for QUAD IO
+ */
+ if (ReadCmd == FAST_READ_CMD || ReadCmd == FAST_READ_CMD_4B)
+ FlashMsg[FlashMsgCnt].BusWidth =
+ XQSPIPSU_SELECT_MODE_SPI;
+
+ if (ReadCmd == DUAL_READ_CMD || ReadCmd == DUAL_READ_CMD_4B)
+ FlashMsg[FlashMsgCnt].BusWidth =
+ XQSPIPSU_SELECT_MODE_DUALSPI;
+
+ if (ReadCmd == QUAD_READ_CMD || ReadCmd == QUAD_READ_CMD_4B)
+ FlashMsg[FlashMsgCnt].BusWidth =
+ XQSPIPSU_SELECT_MODE_QUADSPI;
+
+ FlashMsg[FlashMsgCnt].TxBfrPtr = NULL;
+ FlashMsg[FlashMsgCnt].RxBfrPtr = *ReadBfrPtr;
+ FlashMsg[FlashMsgCnt].ByteCount = ByteCount;
+ FlashMsg[FlashMsgCnt].Flags = XQSPIPSU_MSG_FLAG_RX;
+
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ FlashMsg[FlashMsgCnt].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
+ }
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg,
+ FlashMsgCnt + 1);
+ if (Status != XST_SUCCESS)
+ return XST_FAILURE;
+
+ while (TransferInProgress);
+
+ }
+ rtems_cache_invalidate_multiple_data_lines(ReadBuffer, ByteCount);
+ return 0;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function performs a read operation for multi die flash devices.
+ * Default setting is in DMA mode.
+ *
+ * @param QspiPsuPtr is a pointer to the QSPIPSU driver component to use.
+ * @param Address contains the address of the first sector which needs to
+ * be erased.
+ * @param ByteCount contains the total size to be erased.
+ * @param Command is the command used to read data from the flash.
+ * Supports normal, fast, dual and quad read commands.
+ * @param WriteBfrPtr is pointer to the write buffer which contains data to be
+ * transmitted
+ * @param ReadBfrPtr is pointer to the read buffer to which valid received data
+ * should be written
+ *
+ * @return XST_SUCCESS if successful, else XST_FAILURE.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+static int MultiDieRead(
+ XQspiPsu *QspiPsuPtr,
+ u32 Address,
+ u32 ByteCount,
+ u8 Command,
+ u8 *WriteBfrPtr,
+ u8 *ReadBfrPtr
+)
+{
+ u32 RealAddr;
+ u32 DiscardByteCnt;
+ u32 FlashMsgCnt;
+ int Status;
+ u32 cur_bank = 0;
+ u32 nxt_bank = 0;
+ u32 bank_size;
+ u32 remain_len = ByteCount;
+ u32 data_len;
+ u32 transfer_len;
+ u8 *ReadBuffer = ReadBfrPtr;
+
+ /*
+ * Some flash devices like N25Q512 have multiple dies
+ * in it. Read operation in these devices is bounded
+ * by its die segment. In a continuous read, across
+ * multiple dies, when the last byte of the selected
+ * die segment is read, the next byte read is the
+ * first byte of the same die segment. This is Die
+ * cross over issue. So to handle this issue, split
+ * a read transaction, that spans across multiple
+ * banks, into one read per bank. Bank size is 16MB
+ * for single and dual stacked mode and 32MB for dual
+ * parallel mode.
+ */
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL)
+ bank_size = SIXTEENMB << 1;
+ else
+ bank_size = SIXTEENMB;
+
+ while (remain_len) {
+ cur_bank = Address / bank_size;
+ nxt_bank = (Address + remain_len) / bank_size;
+
+ if (cur_bank != nxt_bank) {
+ transfer_len = (bank_size * (cur_bank + 1)) - Address;
+ if (remain_len < transfer_len)
+ data_len = remain_len;
+ else
+ data_len = transfer_len;
+ } else {
+ data_len = remain_len;
+ }
+ /*
+ * Translate address based on type of connection
+ * If stacked assert the slave select based on address
+ */
+ RealAddr = GetRealAddr(QspiPsuPtr, Address);
+
+ WriteBfrPtr[COMMAND_OFFSET] = Command;
+ if (Flash_Config_Table[FCTIndex].FlashDeviceSize > SIXTEENMB) {
+ WriteBfrPtr[ADDRESS_1_OFFSET] =
+ (u8)((RealAddr & 0xFF000000) >> 24);
+ WriteBfrPtr[ADDRESS_2_OFFSET] =
+ (u8)((RealAddr & 0xFF0000) >> 16);
+ WriteBfrPtr[ADDRESS_3_OFFSET] =
+ (u8)((RealAddr & 0xFF00) >> 8);
+ WriteBfrPtr[ADDRESS_4_OFFSET] =
+ (u8)(RealAddr & 0xFF);
+ DiscardByteCnt = 5;
+ } else {
+ WriteBfrPtr[ADDRESS_1_OFFSET] =
+ (u8)((RealAddr & 0xFF0000) >> 16);
+ WriteBfrPtr[ADDRESS_2_OFFSET] =
+ (u8)((RealAddr & 0xFF00) >> 8);
+ WriteBfrPtr[ADDRESS_3_OFFSET] =
+ (u8)(RealAddr & 0xFF);
+ DiscardByteCnt = 4;
+ }
+
+ FlashMsg[0].TxBfrPtr = WriteBfrPtr;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = DiscardByteCnt;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsgCnt = 1;
+
+ /* It is recommended to have a separate entry for dummy */
+ if (Command == FAST_READ_CMD || Command == DUAL_READ_CMD ||
+ Command == QUAD_READ_CMD || Command == FAST_READ_CMD_4B ||
+ Command == DUAL_READ_CMD_4B ||
+ Command == QUAD_READ_CMD_4B) {
+ /* Update Dummy cycles as per flash specs for QUAD IO */
+
+ /*
+ * It is recommended that Bus width value during dummy
+ * phase should be same as data phase
+ */
+ if (Command == FAST_READ_CMD ||
+ Command == FAST_READ_CMD_4B) {
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ }
+
+ if (Command == DUAL_READ_CMD ||
+ Command == DUAL_READ_CMD_4B) {
+ FlashMsg[1].BusWidth =
+ XQSPIPSU_SELECT_MODE_DUALSPI;
+ }
+
+ if (Command == QUAD_READ_CMD ||
+ Command == QUAD_READ_CMD_4B) {
+ FlashMsg[1].BusWidth =
+ XQSPIPSU_SELECT_MODE_QUADSPI;
+ }
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = NULL;
+ FlashMsg[1].ByteCount = DUMMY_CLOCKS;
+ FlashMsg[1].Flags = 0;
+
+ FlashMsgCnt++;
+ }
+
+ /* Dummy cycles need to be changed as per flash
+ * specs for QUAD IO
+ */
+ if (Command == FAST_READ_CMD || Command == FAST_READ_CMD_4B)
+ FlashMsg[FlashMsgCnt].BusWidth =
+ XQSPIPSU_SELECT_MODE_SPI;
+
+ if (Command == DUAL_READ_CMD || Command == DUAL_READ_CMD_4B)
+ FlashMsg[FlashMsgCnt].BusWidth =
+ XQSPIPSU_SELECT_MODE_DUALSPI;
+
+ if (Command == QUAD_READ_CMD || Command == QUAD_READ_CMD_4B)
+ FlashMsg[FlashMsgCnt].BusWidth =
+ XQSPIPSU_SELECT_MODE_QUADSPI;
+
+ FlashMsg[FlashMsgCnt].TxBfrPtr = NULL;
+ FlashMsg[FlashMsgCnt].RxBfrPtr = ReadBuffer;
+ FlashMsg[FlashMsgCnt].ByteCount = data_len;
+ FlashMsg[FlashMsgCnt].Flags = XQSPIPSU_MSG_FLAG_RX;
+
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL)
+ FlashMsg[FlashMsgCnt].Flags |=
+ XQSPIPSU_MSG_FLAG_STRIPE;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg,
+ FlashMsgCnt + 1);
+ if (Status != XST_SUCCESS)
+ return XST_FAILURE;
+
+ while (TransferInProgress);
+
+
+ ReadBuffer += data_len;
+ Address += data_len;
+ remain_len -= data_len;
+ }
+ rtems_cache_invalidate_multiple_data_lines(ReadBfrPtr, ByteCount);
+ return 0;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This functions performs a bulk erase operation when the
+ * flash device has a single die. Works for both Spansion and Micron
+ *
+ * @param QspiPsuPtr is a pointer to the QSPIPSU driver component to use.
+ * @param WriteBfrPtr is the pointer to command+address to be sent
+ *
+ * @return XST_SUCCESS if successful, else XST_FAILURE.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+static int BulkErase(
+ XQspiPsu *QspiPsuPtr,
+ u8 *WriteBfrPtr
+)
+{
+ u8 WriteEnableCmd;
+ u8 ReadStatusCmd;
+ u8 FlashStatus[2];
+ int Status;
+
+ WriteEnableCmd = WRITE_ENABLE_CMD;
+ /*
+ * Send the write enable command to the Flash so that it can be
+ * written to, this needs to be sent as a separate transfer before
+ * the write
+ */
+ FlashMsg[0].TxBfrPtr = &WriteEnableCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ WriteBfrPtr[COMMAND_OFFSET] = BULK_ERASE_CMD;
+ FlashMsg[0].TxBfrPtr = WriteBfrPtr;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ /*
+ * Wait for the write command to the Flash to be completed, it takes
+ * some time for the data to be written
+ */
+ while (1) {
+ ReadStatusCmd = StatusCmd;
+ FlashMsg[0].TxBfrPtr = &ReadStatusCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = FlashStatus;
+ FlashMsg[1].ByteCount = 2;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
+ }
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ if (FSRFlag) {
+ FlashStatus[1] &= FlashStatus[0];
+ } else {
+ FlashStatus[1] |= FlashStatus[0];
+ }
+ }
+
+ if (FSRFlag) {
+ if ((FlashStatus[1] & 0x80) != 0) {
+ break;
+ }
+ } else {
+ if ((FlashStatus[1] & 0x01) == 0) {
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This functions performs a die erase operation on all the die in
+ * the flash device. This function uses the die erase command for
+ * Micron 512Mbit and 1Gbit
+ *
+ * @param QspiPsuPtr is a pointer to the QSPIPSU driver component to use.
+ * @param WriteBfrPtr is the pointer to command+address to be sent
+ *
+ * @return XST_SUCCESS if successful, else XST_FAILURE.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+static int DieErase(
+ XQspiPsu *QspiPsuPtr,
+ u8 *WriteBfrPtr
+)
+{
+ u8 WriteEnableCmd;
+ u8 DieCnt;
+ u8 ReadStatusCmd;
+ u8 FlashStatus[2];
+ int Status;
+ u32 DieSize = 0;
+ u32 Address;
+ u32 RealAddr;
+ u32 SectSize = 0;
+ u32 NumSect = 0;
+
+ WriteEnableCmd = WRITE_ENABLE_CMD;
+
+ if (QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ SectSize = (Flash_Config_Table[FCTIndex]).SectSize * 2;
+ } else if (QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_STACKED) {
+ NumSect = (Flash_Config_Table[FCTIndex]).NumSect * 2;
+ } else {
+ SectSize = (Flash_Config_Table[FCTIndex]).SectSize;
+ NumSect = (Flash_Config_Table[FCTIndex]).NumSect;
+ }
+ DieSize = (NumSect * SectSize) / Flash_Config_Table[FCTIndex].NumDie;
+
+ for (DieCnt = 0;
+ DieCnt < Flash_Config_Table[FCTIndex].NumDie;
+ DieCnt++) {
+ /*
+ * Send the write enable command to the Flash so that it can be
+ * written to, this needs to be sent as a separate transfer
+ * before the write
+ */
+ FlashMsg[0].TxBfrPtr = &WriteEnableCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ WriteBfrPtr[COMMAND_OFFSET] = DIE_ERASE_CMD;
+
+ Address = DieSize * DieCnt;
+ RealAddr = GetRealAddr(QspiPsuPtr, Address);
+ /*
+ * To be used only if 4B address sector erase cmd is
+ * supported by flash
+ */
+ if (Flash_Config_Table[FCTIndex].FlashDeviceSize > SIXTEENMB) {
+ WriteBfrPtr[ADDRESS_1_OFFSET] =
+ (u8)((RealAddr & 0xFF000000) >> 24);
+ WriteBfrPtr[ADDRESS_2_OFFSET] =
+ (u8)((RealAddr & 0xFF0000) >> 16);
+ WriteBfrPtr[ADDRESS_3_OFFSET] =
+ (u8)((RealAddr & 0xFF00) >> 8);
+ WriteBfrPtr[ADDRESS_4_OFFSET] =
+ (u8)(RealAddr & 0xFF);
+ FlashMsg[0].ByteCount = 5;
+ } else {
+ WriteBfrPtr[ADDRESS_1_OFFSET] =
+ (u8)((RealAddr & 0xFF0000) >> 16);
+ WriteBfrPtr[ADDRESS_2_OFFSET] =
+ (u8)((RealAddr & 0xFF00) >> 8);
+ WriteBfrPtr[ADDRESS_3_OFFSET] =
+ (u8)(RealAddr & 0xFF);
+ FlashMsg[0].ByteCount = 4;
+ }
+ FlashMsg[0].TxBfrPtr = WriteBfrPtr;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ /*
+ * Wait for the write command to the Flash to be completed,
+ * it takes some time for the data to be written
+ */
+ while (1) {
+ ReadStatusCmd = StatusCmd;
+ FlashMsg[0].TxBfrPtr = &ReadStatusCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = FlashStatus;
+ FlashMsg[1].ByteCount = 2;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
+ }
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr,
+ FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ if (FSRFlag) {
+ FlashStatus[1] &= FlashStatus[0];
+ } else {
+ FlashStatus[1] |= FlashStatus[0];
+ }
+ }
+
+ if (FSRFlag) {
+ if ((FlashStatus[1] & 0x80) != 0) {
+ break;
+ }
+ } else {
+ if ((FlashStatus[1] & 0x01) == 0) {
+ break;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This functions translates the address based on the type of interconnection.
+ * In case of stacked, this function asserts the corresponding slave select.
+ *
+ * @param QspiPsuPtr is a pointer to the QSPIPSU driver component to use.
+ * @param Address which is to be accessed (for erase, write or read)
+ *
+ * @return RealAddr is the translated address - for single it is unchanged;
+ * for stacked, the lower flash size is subtracted;
+ * for parallel the address is divided by 2.
+ *
+ * @note In addition to get the actual address to work on flash this
+ * function also selects the CS and BUS based on the configuration
+ * detected.
+ *
+ ******************************************************************************/
+static u32 GetRealAddr(
+ XQspiPsu *QspiPsuPtr,
+ u32 Address
+)
+{
+ u32 RealAddr = 0;
+
+ switch (QspiPsuPtr->Config.ConnectionMode) {
+ case XQSPIPSU_CONNECTION_MODE_SINGLE:
+ XQspiPsu_SelectFlash(QspiPsuPtr,
+ XQSPIPSU_SELECT_FLASH_CS_LOWER,
+ XQSPIPSU_SELECT_FLASH_BUS_LOWER);
+ RealAddr = Address;
+ break;
+ case XQSPIPSU_CONNECTION_MODE_STACKED:
+ /* Select lower or upper Flash based on sector address */
+ if (Address & Flash_Config_Table[FCTIndex].FlashDeviceSize) {
+
+ XQspiPsu_SelectFlash(QspiPsuPtr,
+ XQSPIPSU_SELECT_FLASH_CS_UPPER,
+ XQSPIPSU_SELECT_FLASH_BUS_LOWER);
+ /*
+ * Subtract first flash size when accessing second flash
+ */
+ RealAddr = Address &
+ (~Flash_Config_Table[FCTIndex].FlashDeviceSize);
+ }else{
+ /*
+ * Set selection to L_PAGE
+ */
+ XQspiPsu_SelectFlash(QspiPsuPtr,
+ XQSPIPSU_SELECT_FLASH_CS_LOWER,
+ XQSPIPSU_SELECT_FLASH_BUS_LOWER);
+
+ RealAddr = Address;
+
+ }
+ break;
+ case XQSPIPSU_CONNECTION_MODE_PARALLEL:
+ /*
+ * The effective address in each flash is the actual
+ * address / 2
+ */
+ XQspiPsu_SelectFlash(QspiPsuPtr,
+ XQSPIPSU_SELECT_FLASH_CS_BOTH,
+ XQSPIPSU_SELECT_FLASH_BUS_BOTH);
+ RealAddr = Address / 2;
+ break;
+ default:
+ /* RealAddr wont be assigned in this case; */
+ break;
+
+ }
+
+ return(RealAddr);
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function setups the interrupt system for a QspiPsu device.
+ *
+ * @param QspiPsuInstancePtr is a pointer to the instance of the
+ * QspiPsu device.
+ * @param QspiPsuIntrId is the interrupt Id for an QSPIPSU device.
+ *
+ * @return XST_SUCCESS if successful, otherwise XST_FAILURE.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+static int QspiPsuSetupIntrSystem(
+ XQspiPsu *QspiPsuInstancePtr,
+ u16 QspiPsuIntrId
+)
+{
+ return rtems_interrupt_handler_install(
+ QspiPsuIntrId,
+ NULL,
+ RTEMS_INTERRUPT_UNIQUE,
+ (rtems_interrupt_handler) XQspiPsu_InterruptHandler,
+ QspiPsuInstancePtr
+ );
+}
+
+/*****************************************************************************/
+/**
+ * @brief
+ * This API enters the flash device into 4 bytes addressing mode.
+ * As per the Micron and ISSI spec, before issuing the command
+ * to enter into 4 byte addr mode, a write enable command is issued.
+ * For Macronix and Winbond flash parts write
+ * enable is not required.
+ *
+ * @param QspiPsuPtr is a pointer to the QSPIPSU driver component to use.
+ * @param Enable is a either 1 or 0 if 1 then enters 4 byte if 0 exits.
+ *
+ * @return
+ * - XST_SUCCESS if successful.
+ * - XST_FAILURE if it fails.
+ *
+ *
+ ******************************************************************************/
+static int FlashEnterExit4BAddMode(
+ XQspiPsu *QspiPsuPtr,
+ unsigned int Enable
+)
+{
+ int Status;
+ u8 WriteEnableCmd;
+ u8 Cmd;
+ u8 WriteDisableCmd;
+ u8 ReadStatusCmd;
+ u8 WriteBuffer[2] = {0};
+ u8 FlashStatus[2] = {0};
+
+ if (Enable) {
+ Cmd = ENTER_4B_ADDR_MODE;
+ } else {
+ if (FlashMake == ISSI_ID_BYTE0)
+ Cmd = EXIT_4B_ADDR_MODE_ISSI;
+ else
+ Cmd = EXIT_4B_ADDR_MODE;
+ }
+
+ switch (FlashMake) {
+ case ISSI_ID_BYTE0:
+ case MICRON_ID_BYTE0:
+ WriteEnableCmd = WRITE_ENABLE_CMD;
+ GetRealAddr(QspiPsuPtr, TEST_ADDRESS);
+ /*
+ * Send the write enable command to the Flash so that it can be
+ * written to, this needs to be sent as a separate transfer
+ * before the write
+ */
+ FlashMsg[0].TxBfrPtr = &WriteEnableCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ break;
+
+ case SPANSION_ID_BYTE0:
+
+ /* Read Extended Addres Register */
+ WriteBuffer[0] = BANK_REG_RD;
+ FlashMsg[0].TxBfrPtr = &WriteBuffer[0];
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = &WriteBuffer[1];
+ FlashMsg[1].ByteCount = 1;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+ if (Enable) {
+ WriteBuffer[0] = BANK_REG_WR;
+ WriteBuffer[1] |= 1 << 7;
+ } else {
+ WriteBuffer[0] = BANK_REG_WR;
+ WriteBuffer[1] &= ~(0x01 << 7);
+ }
+
+ FlashMsg[0].TxBfrPtr = &WriteBuffer[0];
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[1].TxBfrPtr = &WriteBuffer[1];
+ FlashMsg[2].RxBfrPtr = NULL;
+ FlashMsg[2].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[2].Flags = XQSPIPSU_MSG_FLAG_TX;
+ FlashMsg[2].ByteCount = 1;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+ WriteBuffer[0] = BANK_REG_RD;
+ FlashMsg[0].TxBfrPtr = &WriteBuffer[0];
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = &FlashStatus[0];
+ FlashMsg[1].ByteCount = 1;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ return Status;
+
+ default:
+ /*
+ * For Macronix and Winbond flash parts
+ * Write enable command is not required.
+ */
+ break;
+ }
+
+ GetRealAddr(QspiPsuPtr, TEST_ADDRESS);
+
+ FlashMsg[0].TxBfrPtr = &Cmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ while (1) {
+ ReadStatusCmd = StatusCmd;
+
+ FlashMsg[0].TxBfrPtr = &ReadStatusCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = FlashStatus;
+ FlashMsg[1].ByteCount = 2;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
+ }
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ if (FSRFlag) {
+ FlashStatus[1] &= FlashStatus[0];
+ } else {
+ FlashStatus[1] |= FlashStatus[0];
+ }
+ }
+
+ if (FSRFlag) {
+ if ((FlashStatus[1] & 0x80) != 0) {
+ break;
+ }
+ } else {
+ if ((FlashStatus[1] & 0x01) == 0) {
+ break;
+ }
+ }
+ }
+
+ switch (FlashMake) {
+ case ISSI_ID_BYTE0:
+ case MICRON_ID_BYTE0:
+ WriteDisableCmd = WRITE_DISABLE_CMD;
+ GetRealAddr(QspiPsuPtr, TEST_ADDRESS);
+ /*
+ * Send the write enable command to the Flash so that it can be
+ * written to, this needs to be sent as a separate transfer
+ * before the write
+ */
+ FlashMsg[0].TxBfrPtr = &WriteDisableCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ break;
+
+ default:
+ /*
+ * For Macronix and Winbond flash parts
+ * Write disable command is not required.
+ */
+ break;
+ }
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+ * @brief
+ * This API enables Quad mode for the flash parts which require to enable quad
+ * mode before using Quad commands.
+ * For S25FL-L series flash parts this is required as the default configuration
+ * is x1/x2 mode.
+ *
+ * @param QspiPsuPtr is a pointer to the QSPIPSU driver component to use.
+ *
+ * @return
+ * - XST_SUCCESS if successful.
+ * - XST_FAILURE if it fails.
+ *
+ *
+ ******************************************************************************/
+static int FlashEnableQuadMode(XQspiPsu *QspiPsuPtr)
+{
+ int Status;
+ u8 WriteEnableCmd;
+ u8 ReadStatusCmd;
+ u8 FlashStatus[2];
+ u8 StatusRegVal;
+ u8 WriteBuffer[3] = {0};
+
+ switch (FlashMake) {
+ case SPANSION_ID_BYTE0:
+ TxBfrPtr = READ_CONFIG_CMD;
+ FlashMsg[0].TxBfrPtr = &TxBfrPtr;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = &WriteBuffer[2];
+ FlashMsg[1].ByteCount = 1;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr,
+ FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ WriteEnableCmd = WRITE_ENABLE_CMD;
+ /*
+ * Send the write enable command to the Flash
+ * so that it can be written to, this needs
+ * to be sent as a separate transfer before
+ * the write
+ */
+ FlashMsg[0].TxBfrPtr = &WriteEnableCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr,
+ FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ GetRealAddr(QspiPsuPtr, TEST_ADDRESS);
+
+ WriteBuffer[0] = WRITE_CONFIG_CMD;
+ WriteBuffer[1] |= 0x02;
+ WriteBuffer[2] |= 0x01 << 1;
+
+ FlashMsg[0].TxBfrPtr = &WriteBuffer[0];
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[1].TxBfrPtr = &WriteBuffer[1];
+ FlashMsg[1].RxBfrPtr = NULL;
+ FlashMsg[1].ByteCount = 2;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr,
+ FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ while (1) {
+ TxBfrPtr = READ_STATUS_CMD;
+ FlashMsg[0].TxBfrPtr = &TxBfrPtr;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = FlashStatus;
+ FlashMsg[1].ByteCount = 2;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr,
+ FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ if (FSRFlag) {
+ FlashStatus[1] &= FlashStatus[0];
+ }else {
+ FlashStatus[1] |= FlashStatus[0];
+ }
+ }
+
+ if ((FlashStatus[1] & 0x01) == 0x00)
+ break;
+ }
+ TxBfrPtr = READ_CONFIG_CMD;
+ FlashMsg[0].TxBfrPtr = &TxBfrPtr;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = ReadBfrPtr;
+ FlashMsg[1].ByteCount = 1;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+ break;
+ case ISSI_ID_BYTE0:
+ /*
+ * Read Status Register to a buffer
+ */
+ ReadStatusCmd = READ_STATUS_CMD;
+ FlashMsg[0].TxBfrPtr = &ReadStatusCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = FlashStatus;
+ FlashMsg[1].ByteCount = 2;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
+ }
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ if (FSRFlag) {
+ FlashStatus[1] &= FlashStatus[0];
+ } else {
+ FlashStatus[1] |= FlashStatus[0];
+ }
+ }
+ /*
+ * Set Quad Enable Bit in the buffer
+ */
+ StatusRegVal = FlashStatus[1];
+ StatusRegVal |= 0x1 << QUAD_MODE_ENABLE_BIT;
+
+ /*
+ * Write enable
+ */
+ WriteEnableCmd = WRITE_ENABLE_CMD;
+ /*
+ * Send the write enable command to the Flash so that it can be
+ * written to, this needs to be sent as a separate transfer
+ * before the write
+ */
+ FlashMsg[0].TxBfrPtr = &WriteEnableCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ /*
+ * Write Status register
+ */
+ WriteBuffer[COMMAND_OFFSET] = WRITE_STATUS_CMD;
+ FlashMsg[0].TxBfrPtr = WriteBuffer;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = &StatusRegVal;
+ FlashMsg[1].RxBfrPtr = NULL;
+ FlashMsg[1].ByteCount = 1;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_TX;
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ FlashMsg[1].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
+ }
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ /*
+ * Write Disable
+ */
+ WriteEnableCmd = WRITE_DISABLE_CMD;
+ FlashMsg[0].TxBfrPtr = &WriteEnableCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+ break;
+
+ case WINBOND_ID_BYTE0:
+ ReadStatusCmd = READ_STATUS_REG_2_CMD;
+ FlashMsg[0].TxBfrPtr = &ReadStatusCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = FlashStatus;
+ FlashMsg[1].ByteCount = 2;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ if (FSRFlag) {
+ FlashStatus[1] &= FlashStatus[0];
+ } else {
+ FlashStatus[1] |= FlashStatus[0];
+ }
+ }
+ /*
+ * Set Quad Enable Bit in the buffer
+ */
+ StatusRegVal = FlashStatus[1];
+ StatusRegVal |= 0x1 << WB_QUAD_MODE_ENABLE_BIT;
+ /*
+ * Write Enable
+ */
+ WriteEnableCmd = WRITE_ENABLE_CMD;
+ FlashMsg[0].TxBfrPtr = &WriteEnableCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 1);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+ /*
+ * Write Status register
+ */
+ WriteBuffer[COMMAND_OFFSET] = WRITE_STATUS_REG_2_CMD;
+ FlashMsg[0].TxBfrPtr = WriteBuffer;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsg[1].TxBfrPtr = &StatusRegVal;
+ FlashMsg[1].RxBfrPtr = NULL;
+ FlashMsg[1].ByteCount = 1;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_TX;
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ while (1) {
+ ReadStatusCmd = READ_STATUS_CMD;
+ FlashMsg[0].TxBfrPtr = &ReadStatusCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+ FlashMsg[1].TxBfrPtr = NULL;
+ FlashMsg[1].RxBfrPtr = FlashStatus;
+ FlashMsg[1].ByteCount = 2;
+ FlashMsg[1].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[1].Flags = XQSPIPSU_MSG_FLAG_RX;
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ if (FSRFlag) {
+ FlashStatus[1] &= FlashStatus[0];
+ } else {
+ FlashStatus[1] |= FlashStatus[0];
+ }
+ }
+ if ((FlashStatus[1] & 0x01) == 0x00) {
+ break;
+ }
+ }
+ /*
+ * Write Disable
+ */
+ WriteEnableCmd = WRITE_DISABLE_CMD;
+ FlashMsg[0].TxBfrPtr = &WriteEnableCmd;
+ FlashMsg[0].RxBfrPtr = NULL;
+ FlashMsg[0].ByteCount = 1;
+ FlashMsg[0].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[0].Flags = XQSPIPSU_MSG_FLAG_TX;
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg, 2);
+ if (Status != XST_SUCCESS) {
+ return XST_FAILURE;
+ }
+ while (TransferInProgress);
+ break;
+
+ default:
+ /*
+ * Currently only S25FL-L series requires the
+ * Quad enable bit to be set to 1.
+ */
+ Status = XST_SUCCESS;
+ break;
+ }
+
+ return Status;
+}
+
+static int MultiDieReadEcc(
+ XQspiPsu *QspiPsuPtr,
+ u32 Address,
+ u32 ByteCount,
+ u8 *WriteBfrPtr,
+ u8 *ReadBfrPtr
+);
+
+int QspiPsu_NOR_Read_Ecc(
+ XQspiPsu *QspiPsuPtr,
+ u32 Address,
+ u8 *ReadBfrPtr
+)
+{
+ u32 RealAddr;
+ u32 DiscardByteCnt;
+ u32 FlashMsgCnt;
+ u8 EccBuffer[16];
+ int ByteCount = sizeof(EccBuffer);
+ int Status;
+
+ /* Check die boundary conditions if required for any flash */
+ if (Flash_Config_Table[FCTIndex].NumDie > 1) {
+
+ Status = MultiDieReadEcc(QspiPsuPtr, Address, ByteCount,
+ CmdBfr, EccBuffer);
+ if (Status == XST_SUCCESS) {
+ /* All bytes are the same, so copy one return byte into the output buffer */
+ *ReadBfrPtr = EccBuffer[0];
+ }
+ return Status;
+ }
+
+ /* For Dual Stacked, split and read for boundary crossing */
+ /*
+ * Translate address based on type of connection
+ * If stacked assert the slave select based on address
+ */
+ RealAddr = GetRealAddr(QspiPsuPtr, Address);
+
+ CmdBfr[COMMAND_OFFSET] = READ_ECCSR;
+ CmdBfr[ADDRESS_1_OFFSET] =
+ (u8)((RealAddr & 0xFF000000) >> 24);
+ CmdBfr[ADDRESS_2_OFFSET] =
+ (u8)((RealAddr & 0xFF0000) >> 16);
+ CmdBfr[ADDRESS_3_OFFSET] =
+ (u8)((RealAddr & 0xFF00) >> 8);
+ CmdBfr[ADDRESS_4_OFFSET] =
+ (u8)(RealAddr & 0xF0);
+ DiscardByteCnt = 5;
+
+ FlashMsgCnt = 0;
+
+ FlashMsg[FlashMsgCnt].TxBfrPtr = CmdBfr;
+ FlashMsg[FlashMsgCnt].RxBfrPtr = NULL;
+ FlashMsg[FlashMsgCnt].ByteCount = DiscardByteCnt;
+ FlashMsg[FlashMsgCnt].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[FlashMsgCnt].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsgCnt++;
+
+ FlashMsg[FlashMsgCnt].TxBfrPtr = NULL;
+ FlashMsg[FlashMsgCnt].RxBfrPtr = NULL;
+ FlashMsg[FlashMsgCnt].ByteCount = DUMMY_CLOCKS;
+ FlashMsg[FlashMsgCnt].Flags = 0;
+
+ FlashMsgCnt++;
+
+ FlashMsg[FlashMsgCnt].TxBfrPtr = NULL;
+ FlashMsg[FlashMsgCnt].RxBfrPtr = EccBuffer;
+ FlashMsg[FlashMsgCnt].ByteCount = ByteCount;
+ FlashMsg[FlashMsgCnt].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[FlashMsgCnt].Flags = XQSPIPSU_MSG_FLAG_RX;
+
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ FlashMsg[FlashMsgCnt].Flags |= XQSPIPSU_MSG_FLAG_STRIPE;
+ }
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg,
+ FlashMsgCnt + 1);
+ if (Status == XST_SUCCESS) {
+ while (TransferInProgress);
+
+ /* All bytes are the same, so copy one return byte into the output buffer */
+ *ReadBfrPtr = EccBuffer[0];
+ }
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function performs an ECC read operation for multi die flash devices.
+ * Default setting is in DMA mode.
+ *
+ * @param QspiPsuPtr is a pointer to the QSPIPSU driver component to use.
+ * @param Address contains the address of the first sector which needs to
+ * be erased.
+ * @param ByteCount contains the total size to be erased.
+ * @param WriteBfrPtr is pointer to the write buffer which contains data to be
+ * transmitted
+ * @param ReadBfrPtr is pointer to the read buffer to which valid received data
+ * should be written
+ *
+ * @return XST_SUCCESS if successful, else XST_FAILURE.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+static int MultiDieReadEcc(
+ XQspiPsu *QspiPsuPtr,
+ u32 Address,
+ u32 ByteCount,
+ u8 *WriteBfrPtr,
+ u8 *ReadBuffer
+)
+{
+ u32 RealAddr;
+ u32 DiscardByteCnt;
+ u32 FlashMsgCnt;
+ int Status;
+ u32 cur_bank = 0;
+ u32 nxt_bank = 0;
+ u32 bank_size;
+ u32 remain_len = ByteCount;
+ u32 data_len;
+ u32 transfer_len;
+
+ /*
+ * Some flash devices like N25Q512 have multiple dies
+ * in it. Read operation in these devices is bounded
+ * by its die segment. In a continuous read, across
+ * multiple dies, when the last byte of the selected
+ * die segment is read, the next byte read is the
+ * first byte of the same die segment. This is Die
+ * cross over issue. So to handle this issue, split
+ * a read transaction, that spans across multiple
+ * banks, into one read per bank. Bank size is 16MB
+ * for single and dual stacked mode and 32MB for dual
+ * parallel mode.
+ */
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL)
+ bank_size = SIXTEENMB << 1;
+ else
+ bank_size = SIXTEENMB;
+
+ while (remain_len) {
+ cur_bank = Address / bank_size;
+ nxt_bank = (Address + remain_len) / bank_size;
+
+ if (cur_bank != nxt_bank) {
+ transfer_len = (bank_size * (cur_bank + 1)) - Address;
+ if (remain_len < transfer_len)
+ data_len = remain_len;
+ else
+ data_len = transfer_len;
+ } else {
+ data_len = remain_len;
+ }
+ /*
+ * Translate address based on type of connection
+ * If stacked assert the slave select based on address
+ */
+ RealAddr = GetRealAddr(QspiPsuPtr, Address);
+
+ WriteBfrPtr[COMMAND_OFFSET] = READ_ECCSR;
+ WriteBfrPtr[ADDRESS_1_OFFSET] =
+ (u8)((RealAddr & 0xFF000000) >> 24);
+ WriteBfrPtr[ADDRESS_2_OFFSET] =
+ (u8)((RealAddr & 0xFF0000) >> 16);
+ WriteBfrPtr[ADDRESS_3_OFFSET] =
+ (u8)((RealAddr & 0xFF00) >> 8);
+ WriteBfrPtr[ADDRESS_4_OFFSET] =
+ (u8)(RealAddr & 0xF0);
+ DiscardByteCnt = 5;
+
+ FlashMsgCnt = 0;
+
+ FlashMsg[FlashMsgCnt].TxBfrPtr = WriteBfrPtr;
+ FlashMsg[FlashMsgCnt].RxBfrPtr = NULL;
+ FlashMsg[FlashMsgCnt].ByteCount = DiscardByteCnt;
+ FlashMsg[FlashMsgCnt].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[FlashMsgCnt].Flags = XQSPIPSU_MSG_FLAG_TX;
+
+ FlashMsgCnt++;
+
+ FlashMsg[FlashMsgCnt].TxBfrPtr = NULL;
+ FlashMsg[FlashMsgCnt].RxBfrPtr = NULL;
+ FlashMsg[FlashMsgCnt].ByteCount = DUMMY_CLOCKS;
+ FlashMsg[FlashMsgCnt].Flags = 0;
+
+ FlashMsgCnt++;
+
+ FlashMsg[FlashMsgCnt].TxBfrPtr = NULL;
+ FlashMsg[FlashMsgCnt].RxBfrPtr = ReadBuffer;
+ FlashMsg[FlashMsgCnt].ByteCount = data_len;
+ FlashMsg[FlashMsgCnt].BusWidth = XQSPIPSU_SELECT_MODE_SPI;
+ FlashMsg[FlashMsgCnt].Flags = XQSPIPSU_MSG_FLAG_RX;
+
+ if (QspiPsuPtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_PARALLEL)
+ FlashMsg[FlashMsgCnt].Flags |=
+ XQSPIPSU_MSG_FLAG_STRIPE;
+
+ TransferInProgress = TRUE;
+ Status = XQspiPsu_InterruptTransfer(QspiPsuPtr, FlashMsg,
+ FlashMsgCnt + 1);
+ if (Status != XST_SUCCESS)
+ return XST_FAILURE;
+
+ while (TransferInProgress);
+
+ ReadBuffer += data_len;
+ Address += data_len;
+ remain_len -= data_len;
+ }
+ return 0;
+}
+
+u32 QspiPsu_NOR_Get_Sector_Size(XQspiPsu *QspiPsuPtr)
+{
+ if(QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ return Flash_Config_Table[FCTIndex].SectSize * 2;
+ }
+ return Flash_Config_Table[FCTIndex].SectSize;
+}
+
+u32 QspiPsu_NOR_Get_Device_Size(XQspiPsu *QspiPsuPtr)
+{
+ if(QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_STACKED
+ || QspiPsuPtr->Config.ConnectionMode == XQSPIPSU_CONNECTION_MODE_PARALLEL) {
+ return Flash_Config_Table[FCTIndex].FlashDeviceSize * 2;
+ }
+ return Flash_Config_Table[FCTIndex].FlashDeviceSize;
+}
diff --git a/bsps/shared/dev/spi/xqspipsu.c b/bsps/shared/dev/spi/xqspipsu.c
new file mode 100644
index 0000000000..93d3fa4c98
--- /dev/null
+++ b/bsps/shared/dev/spi/xqspipsu.c
@@ -0,0 +1,1086 @@
+/******************************************************************************
+* Copyright (C) 2014 - 2022 Xilinx, Inc. All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+
+/*****************************************************************************/
+/**
+ *
+ * @file xqspipsu.c
+ * @addtogroup Overview
+ * @{
+ *
+ * This file implements the functions required to use the QSPIPSU hardware to
+ * perform a transfer. These are accessible to the user via xqspipsu.h.
+ *
+ * <pre>
+ * MODIFICATION HISTORY:
+ *
+ * Ver Who Date Changes
+ * ----- --- -------- -----------------------------------------------
+ * 1.0 hk 08/21/14 First release
+ * sk 03/13/15 Added IO mode support.
+ * hk 03/18/15 Switch to I/O mode before clearing RX FIFO.
+ * Clear and disable DMA interrupts/status in abort.
+ * Use DMA DONE bit instead of BUSY as recommended.
+ * sk 04/24/15 Modified the code according to MISRAC-2012.
+ * sk 06/17/15 Removed NULL checks for Rx/Tx buffers. As
+ * writing/reading from 0x0 location is permitted.
+ * 1.1 sk 04/12/16 Added debug message prints.
+ * 1.2 nsk 07/01/16 Changed XQspiPsu_Select to support GQSPI and LQSPI
+ * selection.
+ * rk 07/15/16 Added support for TapDelays at different frequencies.
+ * nsk 08/05/16 Added example support PollData and PollTimeout
+ * 1.3 nsk 09/16/16 Update PollData and PollTimeout support for dual
+ * parallel configurations, modified XQspiPsu_PollData()
+ * and XQspiPsu_Create_PollConfigData()
+ * 1,5 nsk 08/14/17 Added CCI support
+ * 1.7 tjs 01/16/18 Removed the check for DMA MSB to be written. (CR#992560)
+ * 1.7 tjs 01/17/18 Added a support to toggle WP pin of the flash.
+ * 1.7 tjs 03/14/18 Added support in EL1 NS mode (CR#974882)
+ * 1.8 tjs 06/26/18 Added an example for accessing 64bit dma within
+ * 32 bit application. CR#1004701
+ * 1.8 tjs 06/26/18 Removed checkpatch warnings.
+ * 1.8 tjs 07/09/18 Fixed cppcheck and doxygen warnings. (CR#1006336)
+ * 1.8 tjs 07/18/18 Setup64BRxDma() should be called only if the RxAddress is
+ * greater than 32 bit address space. (CR#1006862)
+ * 1.8 tjs 09/06/18 Fixed the code in XQspiPsu_GenFifoEntryData() for data
+ * transfer length up to 255 for reducing the extra loop.
+ * 1.8 mus 11/05/18 Support 64 bit DMA addresses for Microblaze-X platform.
+ * 1.9 tjs 11/22/17 Added the check for A72 and R5 processors (CR-987075)
+ * 1.9 tjs 04/17/18 Updated register addresses as per the latest revision
+ * of versal (CR#999610)
+ * 1.9 aru 01/17/19 Fixes violations according to MISRAC-2012
+ * in safety mode and modified the code such as
+ * Added UNITPTR inplace of INTPTR,Declared the pointer param
+ * as Pointer to const .
+ * 1.9 nsk 02/01/19 Clear DMA_DST_ADDR_MSB register on 32bit machine, if the
+ * address is of only 32bit (CR#1020031)
+ * 1.9 nsk 02/01/19 Added QSPI idling support.
+ * 1.9 rama 03/13/19 Fixed MISRA violations related to UR data anamoly,
+ * expression is not a boolean
+ * 1.9 nsk 03/27/19 Update 64bit dma support
+ * 1.10 sk 08/20/19 Fixed issues in poll timeout feature.
+ * 1.11 akm 02/19/20 Added XQspiPsu_StartDmaTransfer() and XQspiPsu_CheckDmaDone()
+ * APIs for non-blocking transfer.
+ * 1.11 sd 01/02/20 Added clocking support
+ * 1.11 akm 03/09/20 Reorganize the source code, enable qspi controller and
+ * interrupts in XQspiPsu_CfgInitialize() API.
+ * 1.11 akm 03/26/20 Fixed issue by updating XQspiPsu_CfgInitialize to return
+ * XST_DEVICE_IS_STARTED instead of asserting, when the
+ * instance is already configured.
+ * 1.13 akm 01/04/21 Fix MISRA-C violations.
+ * 1.14 akm 06/24/21 Allow enough time for the controller to reset the FIFOs.
+ * 1.14 akm 08/12/21 Perform Dcache invalidate at the end of the DMA transfer.
+ * 1.15 akm 10/21/21 Fix MISRA-C violations.
+ *
+ * </pre>
+ *
+ ******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xqspipsu.h"
+#include "xqspipsu_control.h"
+#include "sleep.h"
+#ifdef __rtems__
+#include <rtems/rtems/cache.h>
+#endif
+
+/************************** Constant Definitions *****************************/
+#define MAX_DELAY_CNT 10000000U /**< Max delay count */
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+
+/*****************************************************************************/
+/**
+ *
+ * Initializes a specific XQspiPsu instance as such the driver is ready to use.
+ *
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param ConfigPtr is a reference to a structure containing information
+ * about a specific QSPIPSU device. This function initializes an
+ * InstancePtr object for a specific device specified by the
+ * contents of Config.
+ * @param EffectiveAddr is the device base address in the virtual memory
+ * address space. The caller is responsible for keeping the address
+ * mapping from EffectiveAddr to the device physical base address
+ * unchanged once this function is invoked. Unexpected errors may
+ * occur if the address mapping changes after this function is
+ * called. If address translation is not used, use
+ * ConfigPtr->Config.BaseAddress for this device.
+ *
+ * @return
+ * - XST_SUCCESS if successful.
+ * - XST_DEVICE_IS_STARTED if the device is already started.
+ * It must be stopped to re-initialize.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+s32 XQspiPsu_CfgInitialize(XQspiPsu *InstancePtr,
+ const XQspiPsu_Config *ConfigPtr,
+ UINTPTR EffectiveAddr)
+{
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(ConfigPtr != NULL);
+ s32 Status;
+
+ /*
+ * If the device is busy, disallow the initialize and return a status
+ * indicating it is already started. This allows the user to stop the
+ * device and re-initialize, but prevents a user from inadvertently
+ * initializing. This assumes the busy flag is cleared at startup.
+ */
+ if ((InstancePtr->IsBusy == (u32)TRUE) ||
+ (InstancePtr->IsReady == XIL_COMPONENT_IS_READY)) {
+ Status = (s32)XST_DEVICE_IS_STARTED;
+ } else {
+ /* Set some default values. */
+ InstancePtr->IsBusy = (u32)FALSE;
+ InstancePtr->Config.BaseAddress =
+ EffectiveAddr + XQSPIPSU_OFFSET;
+ InstancePtr->Config.ConnectionMode = ConfigPtr->ConnectionMode;
+ InstancePtr->StatusHandler = StubStatusHandler;
+ InstancePtr->Config.BusWidth = ConfigPtr->BusWidth;
+ InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz;
+#if defined (XCLOCKING)
+ InstancePtr->Config.RefClk = ConfigPtr->RefClk;
+#endif
+ InstancePtr->Config.IsCacheCoherent =
+ ConfigPtr->IsCacheCoherent;
+ /* Other instance variable initializations */
+ InstancePtr->SendBufferPtr = NULL;
+ InstancePtr->RecvBufferPtr = NULL;
+ InstancePtr->GenFifoBufferPtr = NULL;
+ InstancePtr->TxBytes = 0;
+ InstancePtr->RxBytes = 0;
+ InstancePtr->GenFifoEntries = 0;
+ InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
+ InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
+ InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
+ InstancePtr->IsUnaligned = 0;
+ InstancePtr->IsManualstart = (u8)TRUE;
+
+ /* Select QSPIPSU */
+ XQspiPsu_Select(InstancePtr, XQSPIPSU_SEL_GQSPI_MASK);
+ /*
+ * Reset the QSPIPSU device to get it into its initial state.
+ * It is expected that device configuration will take place
+ * after this initialization is done, but before the device
+ * is started.
+ */
+ XQspiPsu_Reset(InstancePtr);
+ /* Enable */
+ XQspiPsu_Enable(InstancePtr);
+
+ InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
+
+ Status = (s32)XST_SUCCESS;
+ }
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * Stops the transfer of data to internal DST FIFO from stream interface and
+ * also stops the issuing of new write commands to memory.
+ *
+ * By calling this API, any ongoing Dma transfers will be paused and DMA will
+ * not issue AXI write commands to memory
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ * @return None.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_Idle(const XQspiPsu *InstancePtr)
+{
+ u32 RegEn;
+ u32 DmaStatus;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ /* Check for QSPI enable */
+ RegEn = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_EN_OFFSET);
+ if ((RegEn & XQSPIPSU_EN_MASK) != 0U) {
+ DmaStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET);
+ DmaStatus |= XQSPIPSU_QSPIDMA_DST_CTRL_PAUSE_STRM_MASK;
+ DmaStatus |= XQSPIPSU_QSPIDMA_DST_CTRL_PAUSE_MEM_MASK;
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET, DmaStatus);
+ }
+#if defined (XCLOCKING)
+ Xil_ClockDisable(InstancePtr->Config.RefClk);
+#endif
+}
+
+/*****************************************************************************/
+/**
+ *
+ * Resets the QSPIPSU device. Reset must only be called after the driver has
+ * been initialized. Any data transfer that is in progress is aborted.
+ *
+ * The upper layer software is responsible for re-configuring (if necessary)
+ * and restarting the QSPIPSU device after the reset.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ * @return None.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_Reset(XQspiPsu *InstancePtr)
+{
+ Xil_AssertVoid(InstancePtr != NULL);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_Reset\r\n");
+#endif
+
+ /* Abort any transfer that is in progress */
+ XQspiPsu_Abort(InstancePtr);
+
+ /* Default value to config register */
+ XQspiPsu_SetDefaultConfig(InstancePtr);
+
+}
+
+/*****************************************************************************/
+/**
+ *
+ * Aborts a transfer in progress.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ * @return None.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_Abort(XQspiPsu *InstancePtr)
+{
+ u32 IntrStatus, ConfigReg, FifoStatus;
+ u32 DelayCount = 0U;
+
+#ifdef __rtems__
+ u32 FifoStatusMask = XQSPIPSU_ISR_RXEMPTY_MASK;
+ FifoStatusMask |= XQSPIPSU_ISR_TXEMPTY_MASK;
+ FifoStatusMask |= XQSPIPSU_ISR_GENFIFOEMPTY_MASK;
+#endif
+
+ Xil_AssertVoid(InstancePtr != NULL);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_Abort\r\n");
+#endif
+ IntrStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_ISR_OFFSET);
+
+ /* Clear and disable interrupts */
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_ISR_OFFSET, IntrStatus | XQSPIPSU_ISR_WR_TO_CLR_MASK);
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET,
+ XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET));
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_STS_OFFSET,
+ XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_STS_OFFSET) |
+ XQSPIPSU_QSPIDMA_DST_STS_WTC);
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_IDR_OFFSET, XQSPIPSU_IDR_ALL_MASK);
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_I_DIS_OFFSET,
+ XQSPIPSU_QSPIDMA_DST_INTR_ALL_MASK);
+
+ /*
+ * Clear GEN FIFO, TX FIFO & RX FIFO. Switch to IO mode to Clear
+ * RX FIFO. This is because of DMA behaviour where it waits on
+ * RX empty and goes busy assuming there is data to be transferred
+ * even if there is no request.
+ */
+ ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET);
+ ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET, ConfigReg);
+
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_FIFO_CTRL_OFFSET,
+ XQSPIPSU_FIFO_CTRL_RST_TX_FIFO_MASK |
+ XQSPIPSU_FIFO_CTRL_RST_GEN_FIFO_MASK |
+ XQSPIPSU_FIFO_CTRL_RST_RX_FIFO_MASK);
+ /*
+ * QSPI Controller takes few clock cycles to update the RX_FIFO_Empty,
+ * TX_FIFO_Empty and GEN_FIFO_Empty status bit. Checking the GQSPI FIFO
+ * Control register bits gives enough time for the QSPI controller to
+ * update the status bit. The opeartion timesout, if the status bit are
+ * not updated after 10secs.
+ */
+
+ FifoStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+#ifdef __rtems__
+ XQSPIPSU_ISR_OFFSET) & FifoStatusMask;
+ while(FifoStatus != FifoStatusMask) {
+#else
+ XQSPIPSU_FIFO_CTRL_OFFSET);
+ while(FifoStatus != 0U) {
+#endif
+ if (DelayCount == MAX_DELAY_CNT) {
+#ifdef DEBUG
+ xil_printf("Timeout error, FIFO reset failed.\r\n");
+#endif
+ } else {
+ /* Wait for 1 usec */
+ usleep(1);
+ DelayCount++;
+ FifoStatus = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+#ifdef __rtems__
+ XQSPIPSU_ISR_OFFSET) & FifoStatusMask;
+#else
+ XQSPIPSU_FIFO_CTRL_OFFSET);
+#endif
+ }
+ }
+
+ if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+ ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET, ConfigReg);
+ }
+
+
+ InstancePtr->TxBytes = 0;
+ InstancePtr->RxBytes = 0;
+ InstancePtr->GenFifoEntries = 0;
+ InstancePtr->IsBusy = (u32)FALSE;
+}
+
+/*****************************************************************************/
+/**
+ * This is the handler for polling functionality of controller. It reads data
+ * from RXFIFO, since when data from the flash device (status data) matched
+ * with configured value in poll_cfg, then controller writes the matched data
+ * into RXFIFO.
+ *
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param StatusReg is the Interrupt status Register value.
+ *
+ * @return None.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_PollDataHandler(XQspiPsu *InstancePtr, u32 StatusReg)
+{
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_PollDataHandler\r\n");
+#endif
+
+ if ((StatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK) != (u32)FALSE) {
+ /*
+ * Read data from RXFIFO, since when data from the
+ * flash device (status data) matched with configured
+ * value in poll_cfg, then controller writes the
+ * matched data into RXFIFO.
+ */
+ (void)XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_RXD_OFFSET);
+
+ InstancePtr->StatusHandler(InstancePtr->StatusRef,
+ XST_SPI_POLL_DONE, 0);
+ }
+ if ((StatusReg & XQSPIPSU_ISR_POLL_TIME_EXPIRE_MASK) != (u32)FALSE) {
+ InstancePtr->StatusHandler(InstancePtr->StatusRef,
+ XST_FLASH_TIMEOUT_ERROR, 0);
+ }
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_IDR_OFFSET,
+ (u32)XQSPIPSU_IER_RXNEMPTY_MASK |
+ (u32)XQSPIPSU_IER_POLL_TIME_EXPIRE_MASK);
+ InstancePtr->IsBusy = (u32)FALSE;
+ if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+ XQspiPsu_SetReadMode(InstancePtr, XQSPIPSU_READMODE_DMA);
+ }
+ /* De-select slave */
+ XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
+ XQspiPsu_ManualStartEnable(InstancePtr);
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function performs a transfer on the bus in polled mode. The messages
+ * passed are all transferred on the bus between one CS assert and de-assert.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ * @param NumMsg is the number of messages to be transferred.
+ *
+ * @return
+ * - XST_SUCCESS if successful.
+ * - XST_FAILURE if transfer fails.
+ * - XST_DEVICE_BUSY if a transfer is already in progress.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+s32 XQspiPsu_PolledTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+ u32 NumMsg)
+{
+ s32 Index;
+ u32 QspiPsuStatusReg;
+ u32 IOPending = (u32)FALSE;
+ u32 DmaIntrSts;
+ s32 Status;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(Msg != NULL);
+ Xil_AssertNonvoid(NumMsg > 0U);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ for (Index = 0; Index < (s32)NumMsg; Index++) {
+ Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
+#ifdef __rtems__
+ if (Msg[Index].TxBfrPtr != NULL) {
+ rtems_cache_flush_multiple_data_lines(Msg[Index].TxBfrPtr, Msg[Index].ByteCount);
+ }
+#endif
+ }
+#ifdef __rtems__
+ rtems_cache_flush_multiple_data_lines(Msg, NumMsg * sizeof(*Msg));
+#endif
+
+ /*
+ * Check whether there is another transfer in progress.
+ * Not thread-safe
+ */
+ if (InstancePtr->IsBusy == (u32)TRUE) {
+ Status = (s32)XST_DEVICE_BUSY;
+ goto END;
+ }
+ /* Check for ByteCount upper limit - 2^28 for DMA */
+ for (Index = 0; Index < (s32)NumMsg; Index++) {
+ if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
+ ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
+ Status = (s32)XST_FAILURE;
+ goto END;
+ }
+ }
+ /*
+ * Set the busy flag, which will be cleared when the transfer is
+ * entirely done.
+ */
+ InstancePtr->IsBusy = (u32)TRUE;
+
+#if defined (XCLOCKING)
+ Xil_ClockEnable(InstancePtr->Config.RefClk);
+#endif
+ /* Select slave */
+ XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
+
+ /* list */
+ Index = 0;
+ while (Index < (s32)NumMsg) {
+ XQspiPsu_GenFifoEntryData(InstancePtr, &Msg[Index]);
+ XQspiPsu_ManualStartEnable(InstancePtr);
+ /* Use thresholds here */
+ /* If there is more data to be transmitted */
+ do {
+ QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_ISR_OFFSET);
+ /* Transmit more data if left */
+ if (((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != (u32)FALSE) &&
+ ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) &&
+ (InstancePtr->TxBytes > 0)) {
+ XQspiPsu_FillTxFifo(InstancePtr, &Msg[Index],
+ (u32)XQSPIPSU_TXD_DEPTH);
+ }
+
+ if ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE) {
+ if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+ /* Check if DMA RX is complete and update RxBytes */
+ DmaIntrSts = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
+ if ((DmaIntrSts &
+ XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != (u32)FALSE) {
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET, DmaIntrSts);
+ /* DMA transfer done, Invalidate Data Cache */
+ if (!((Msg[Index].RxAddr64bit >= XQSPIPSU_RXADDR_OVER_32BIT) ||
+ (Msg[Index].Xfer64bit != (u8)0U)) &&
+ (InstancePtr->Config.IsCacheCoherent == 0U)) {
+ Xil_DCacheInvalidateRange((INTPTR)Msg[Index].RxBfrPtr,
+ (INTPTR)Msg[Index].ByteCount);
+ }
+ IOPending = XQspiPsu_SetIOMode(InstancePtr, &Msg[Index]);
+ InstancePtr->RxBytes = 0;
+ if (IOPending == (u32)TRUE) {
+ break;
+ }
+ }
+ } else {
+ XQspiPsu_IORead(InstancePtr, &Msg[Index], QspiPsuStatusReg);
+ }
+ }
+ } while (((QspiPsuStatusReg &
+ XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == (u32)FALSE) ||
+ (InstancePtr->TxBytes != 0) ||
+ ((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) == (u32)FALSE) ||
+ (InstancePtr->RxBytes != 0));
+
+ if ((InstancePtr->IsUnaligned != 0) && (IOPending == (u32)FALSE)) {
+ InstancePtr->IsUnaligned = 0;
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+ (XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) |
+ XQSPIPSU_CFG_MODE_EN_DMA_MASK));
+ InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
+ }
+ if (IOPending == (u32)TRUE) {
+ IOPending = (u32)FALSE;
+ } else {
+ Index++;
+ }
+ }
+ /* De-select slave */
+ XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
+ XQspiPsu_ManualStartEnable(InstancePtr);
+ do {
+ QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_ISR_OFFSET);
+ } while ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == (u32)FALSE);
+
+ /* Clear the busy flag. */
+ InstancePtr->IsBusy = (u32)FALSE;
+
+ Status = (s32)XST_SUCCESS;
+
+#if defined (XCLOCKING)
+ Xil_ClockDisable(InstancePtr->Config.RefClk);
+#endif
+ END:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function initiates a transfer on the bus and enables interrupts.
+ * The transfer is completed by the interrupt handler. The messages passed are
+ * all transferred on the bus between one CS assert and de-assert.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ * @param NumMsg is the number of messages to be transferred.
+ *
+ * @return
+ * - XST_SUCCESS if successful.
+ * - XST_FAILURE if transfer fails.
+ * - XST_DEVICE_BUSY if a transfer is already in progress.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+s32 XQspiPsu_InterruptTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+ u32 NumMsg)
+{
+ s32 Index;
+ s32 Status;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ for (Index = 0; Index < (s32)NumMsg; Index++)
+#ifdef __rtems__
+ {
+#endif
+ Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
+#ifdef __rtems__
+ if (Msg[Index].TxBfrPtr != NULL) {
+ rtems_cache_flush_multiple_data_lines(Msg[Index].TxBfrPtr, Msg[Index].ByteCount);
+ }
+ }
+ rtems_cache_flush_multiple_data_lines(Msg, NumMsg * sizeof(*Msg));
+#endif
+
+ /*
+ * Check whether there is another transfer in progress.
+ * Not thread-safe
+ */
+ if (InstancePtr->IsBusy == (u32)TRUE) {
+ Status = (s32)XST_DEVICE_BUSY;
+ goto END;
+ }
+#if defined (XCLOCKING)
+ Xil_ClockEnable(InstancePtr->Config.RefClk);
+#endif
+
+ if ((Msg[0].Flags & XQSPIPSU_MSG_FLAG_POLL) != (u32)FALSE) {
+ InstancePtr->IsBusy = (u32)TRUE;
+ XQspiPsu_PollDataConfig(InstancePtr, Msg);
+ } else {
+ /* Check for ByteCount upper limit - 2^28 for DMA */
+ for (Index = 0; Index < (s32)NumMsg; Index++) {
+ if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
+ ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
+ Status = (s32)XST_FAILURE;
+ goto END;
+ }
+ }
+ /*
+ * Set the busy flag, which will be cleared when the transfer is
+ * entirely done.
+ */
+ InstancePtr->IsBusy = (u32)TRUE;
+
+ InstancePtr->Msg = Msg;
+ InstancePtr->NumMsg = (s32)NumMsg;
+ InstancePtr->MsgCnt = 0;
+
+ /* Select slave */
+ XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
+ /* This might not work if not manual start */
+ /* Put first message in FIFO along with the above slave select */
+ XQspiPsu_GenFifoEntryData(InstancePtr, &Msg[0]);
+ XQspiPsu_ManualStartEnable(InstancePtr);
+
+ /* Enable interrupts */
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_IER_OFFSET,
+ (u32)XQSPIPSU_IER_TXNOT_FULL_MASK |
+ (u32)XQSPIPSU_IER_TXEMPTY_MASK |
+ (u32)XQSPIPSU_IER_RXNEMPTY_MASK |
+ (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
+ (u32)XQSPIPSU_IER_RXEMPTY_MASK);
+
+ if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_I_EN_OFFSET,
+ XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
+ }
+ }
+ Status = (s32)XST_SUCCESS;
+
+ END:
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * Handles interrupt based transfers by acting on GENFIFO and DMA interurpts.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ * @return
+ * - XST_SUCCESS if successful.
+ * - XST_FAILURE if transfer fails.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+s32 XQspiPsu_InterruptHandler(XQspiPsu *InstancePtr)
+{
+ u32 QspiPsuStatusReg, DmaIntrStatusReg = 0;
+ XQspiPsu_Msg *Msg;
+ s32 NumMsg;
+ s32 MsgCnt;
+ u8 DeltaMsgCnt = 0;
+ u32 TxRxFlag;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+ Xil_AssertNonvoid(InstancePtr->NumMsg > 0);
+ Xil_AssertNonvoid(InstancePtr->Msg != NULL);
+
+ Msg = InstancePtr->Msg;
+ NumMsg = InstancePtr->NumMsg;
+ MsgCnt = InstancePtr->MsgCnt;
+ TxRxFlag = Msg[MsgCnt].Flags;
+
+ /* QSPIPSU Intr cleared on read */
+ QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_ISR_OFFSET);
+ if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+ /* DMA Intr write to clear */
+ DmaIntrStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET,
+ DmaIntrStatusReg);
+ }
+ if (((DmaIntrStatusReg & XQSPIPSU_QSPIDMA_DST_INTR_ERR_MASK) != (u32)FALSE)) {
+ /* Call status handler to indicate error */
+ InstancePtr->StatusHandler(InstancePtr->StatusRef,
+ XST_SPI_COMMAND_ERROR, 0);
+ }
+ /* Fill more data to be txed if required */
+ if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) &&
+ ((QspiPsuStatusReg & XQSPIPSU_ISR_TXNOT_FULL_MASK) != (u32)FALSE) &&
+ (InstancePtr->TxBytes > 0)) {
+ XQspiPsu_FillTxFifo(InstancePtr, &Msg[MsgCnt], (u32)XQSPIPSU_TXD_DEPTH);
+ }
+ /*
+ * Check if the entry is ONLY TX and increase MsgCnt.
+ * This is to allow TX and RX together in one entry - corner case.
+ */
+ if ((MsgCnt < NumMsg) && ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) &&
+ ((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) != (u32)FALSE) &&
+ ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != (u32)FALSE) &&
+ (InstancePtr->TxBytes == 0) &&
+ ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == (u32)FALSE)) {
+ MsgCnt += 1;
+ DeltaMsgCnt = 1U;
+ }
+
+ if ((MsgCnt < NumMsg) &&
+ ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
+ if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+ if ((DmaIntrStatusReg &
+ XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != (u32)FALSE) {
+ /* DMA transfer done, Invalidate Data Cache */
+ if (!((Msg[MsgCnt].RxAddr64bit >= XQSPIPSU_RXADDR_OVER_32BIT) ||
+ (Msg[MsgCnt].Xfer64bit != (u8)0U)) &&
+ (InstancePtr->Config.IsCacheCoherent == 0U)) {
+ Xil_DCacheInvalidateRange((INTPTR)Msg[MsgCnt].RxBfrPtr, (INTPTR)Msg[MsgCnt].ByteCount);
+ }
+ if (XQspiPsu_SetIOMode(InstancePtr, &Msg[MsgCnt]) == (u32)TRUE) {
+ XQspiPsu_GenFifoEntryData(InstancePtr, &Msg[MsgCnt]);
+ XQspiPsu_ManualStartEnable(InstancePtr);
+ } else {
+ InstancePtr->RxBytes = 0;
+ MsgCnt += 1;
+ DeltaMsgCnt = 1U;
+ }
+ }
+ } else {
+ if (InstancePtr->RxBytes != 0) {
+ XQspiPsu_IORead(InstancePtr, &Msg[MsgCnt], QspiPsuStatusReg);
+ if (InstancePtr->RxBytes == 0) {
+ MsgCnt += 1;
+ DeltaMsgCnt = 1U;
+ }
+ }
+ }
+ }
+
+ /*
+ * Dummy byte transfer
+ * MsgCnt < NumMsg check is to ensure is it a valid dummy cycle message
+ * If one of the above conditions increased MsgCnt, then
+ * the new message is yet to be placed in the FIFO; hence !DeltaMsgCnt.
+ */
+ if ((MsgCnt < NumMsg) && (DeltaMsgCnt == (u8)FALSE) &&
+ ((TxRxFlag & XQSPIPSU_MSG_FLAG_RX) == (u32)FALSE) &&
+ ((TxRxFlag & XQSPIPSU_MSG_FLAG_TX) == (u32)FALSE) &&
+ ((TxRxFlag & XQSPIPSU_MSG_FLAG_POLL) == (u32)FALSE) &&
+ ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != (u32)FALSE)) {
+ MsgCnt += 1;
+ DeltaMsgCnt = 1U;
+ }
+ InstancePtr->MsgCnt = MsgCnt;
+ /*
+ * DeltaMsgCnt is to handle conditions where genfifo empty can be set
+ * while tx is still not empty or rx dma is not yet done.
+ * MsgCnt > NumMsg indicates CS de-assert entry was also executed.
+ */
+ if (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != (u32)FALSE) &&
+ ((DeltaMsgCnt != (u8)FALSE) || (MsgCnt > NumMsg))) {
+ if (MsgCnt < NumMsg) {
+ if (InstancePtr->IsUnaligned != 0) {
+ InstancePtr->IsUnaligned = 0;
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
+ InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) |
+ XQSPIPSU_CFG_MODE_EN_DMA_MASK));
+ InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
+ }
+ /* This might not work if not manual start */
+ XQspiPsu_GenFifoEntryData(InstancePtr, &Msg[MsgCnt]);
+ XQspiPsu_ManualStartEnable(InstancePtr);
+ } else if (MsgCnt == NumMsg) {
+ /* This is just to keep track of the de-assert entry */
+ MsgCnt += 1;
+ InstancePtr->MsgCnt = MsgCnt;
+ /* De-select slave */
+ XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
+ XQspiPsu_ManualStartEnable(InstancePtr);
+ } else {
+ /* Disable interrupts */
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_IDR_OFFSET,
+ (u32)XQSPIPSU_IER_TXNOT_FULL_MASK |
+ (u32)XQSPIPSU_IER_TXEMPTY_MASK |
+ (u32)XQSPIPSU_IER_RXNEMPTY_MASK |
+ (u32)XQSPIPSU_IER_GENFIFOEMPTY_MASK |
+ (u32)XQSPIPSU_IER_RXEMPTY_MASK);
+ if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_I_DIS_OFFSET,
+ XQSPIPSU_QSPIDMA_DST_I_EN_DONE_MASK);
+ }
+ /* Clear the busy flag. */
+ InstancePtr->IsBusy = (u32)FALSE;
+#if defined (XCLOCKING)
+ Xil_ClockDisable(InstancePtr->Config.RefClk);
+#endif
+ /* Call status handler to indicate completion */
+ InstancePtr->StatusHandler(InstancePtr->StatusRef,
+ XST_SPI_TRANSFER_DONE, 0);
+ }
+ }
+ if ((TxRxFlag & XQSPIPSU_MSG_FLAG_POLL) != (u32)FALSE) {
+ XQspiPsu_PollDataHandler(InstancePtr, QspiPsuStatusReg);
+ }
+ return (s32)XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * Sets the status callback function, the status handler, which the driver
+ * calls when it encounters conditions that should be reported to upper
+ * layer software. The handler executes in an interrupt context, so it must
+ * minimize the amount of processing performed. One of the following status
+ * events is passed to the status handler.
+ *
+ * <pre>
+ *
+ * XST_SPI_TRANSFER_DONE The requested data transfer is done
+ *
+ * XST_SPI_TRANSMIT_UNDERRUN As a slave device, the master clocked data
+ * but there were none available in the transmit
+ * register/FIFO. This typically means the slave
+ * application did not issue a transfer request
+ * fast enough, or the processor/driver could not
+ * fill the transmit register/FIFO fast enough.
+ *
+ * XST_SPI_RECEIVE_OVERRUN The QSPIPSU device lost data. Data was received
+ * but the receive data register/FIFO was full.
+ *
+ * </pre>
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param CallBackRef is the upper layer callback reference passed back
+ * when the callback function is invoked.
+ * @param FuncPointer is the pointer to the callback function.
+ *
+ * @return None.
+ *
+ * @note
+ *
+ * The handler is called within interrupt context, so it should do its work
+ * quickly and queue potentially time-consuming work to a task-level thread.
+ *
+ ******************************************************************************/
+void XQspiPsu_SetStatusHandler(XQspiPsu *InstancePtr, void *CallBackRef,
+ XQspiPsu_StatusHandler FuncPointer)
+{
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(FuncPointer != NULL);
+ Xil_AssertVoid(CallBackRef != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ InstancePtr->StatusHandler = FuncPointer;
+ InstancePtr->StatusRef = CallBackRef;
+}
+
+/*****************************************************************************/
+/**
+ * @brief
+ * This API enables/ disables Write Protect pin on the flash parts.
+ *
+ * @param InstancePtr is a pointer to the QSPIPSU driver component to use.
+ *
+ * @param Toggle is a value of the GPIO pin
+ *
+ * @return None
+ *
+ * @note By default WP pin as per the QSPI controller is driven High
+ * which means no write protection. Calling this function once
+ * will enable the protection.
+ *
+ ******************************************************************************/
+void XQspiPsu_WriteProtectToggle(const XQspiPsu *InstancePtr, u32 Toggle)
+{
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+ /* For Single and Stacked flash configuration with x1 or x2 mode*/
+ if (InstancePtr->Config.ConnectionMode ==
+ XQSPIPSU_CONNECTION_MODE_SINGLE) {
+ /* Select slave */
+ XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
+
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_GPIO_OFFSET, Toggle);
+
+ } else {
+#ifdef DEBUG
+ xil_printf("Dual Parallel/Stacked configuration ");
+ xil_printf("is not supported by this API\r\n");
+#endif
+ }
+}
+
+/*****************************************************************************/
+/**
+*
+* This function start a DMA transfer.
+*
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ * @param NumMsg is the number of messages to be transferred.
+ *
+ * @return
+ * - XST_SUCCESS if successful.
+ * - XST_FAILURE if ByteCount is greater than
+ * XQSPIPSU_DMA_BYTES_MAX.
+ * - XST_DEVICE_BUSY if a transfer is already in progress.
+ *
+ * @note None.
+ *
+*
+******************************************************************************/
+s32 XQspiPsu_StartDmaTransfer(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+ u32 NumMsg)
+{
+ s32 Index;
+ u32 QspiPsuStatusReg = 0;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(Msg != NULL);
+ Xil_AssertNonvoid(NumMsg > 0U);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+ for (Index = 0; Index < (s32)NumMsg; Index++) {
+ Xil_AssertNonvoid(Msg[Index].ByteCount > 0U);
+ }
+
+ /*
+ * Check whether there is another transfer in progress.
+ * Not thread-safe
+ */
+ if (InstancePtr->IsBusy == (u32)TRUE) {
+ return (s32)XST_DEVICE_BUSY;
+ }
+
+ /* Check for ByteCount upper limit - 2^28 for DMA */
+ for (Index = 0; Index < (s32)NumMsg; Index++) {
+ if ((Msg[Index].ByteCount > XQSPIPSU_DMA_BYTES_MAX) &&
+ ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
+ return (s32)XST_FAILURE;
+ }
+ }
+
+ /*
+ * Set the busy flag, which will be cleared when the transfer is
+ * entirely done.
+ */
+ InstancePtr->IsBusy = (u32)TRUE;
+
+ /* Select slave */
+ XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
+ /* list */
+ Index = 0;
+ while (Index < (s32)NumMsg) {
+ InstancePtr->Msg = &Msg[Index];
+ XQspiPsu_GenFifoEntryData(InstancePtr, &Msg[Index]);
+ if (InstancePtr->IsManualstart == (u32)TRUE) {
+#ifdef DEBUG
+ xil_printf("\nManual Start\r\n");
+#endif
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+ XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET) |
+ XQSPIPSU_CFG_START_GEN_FIFO_MASK);
+ }
+ do {
+ if((InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) &&
+ ((Msg[Index].Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
+ break;
+ }
+ QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_ISR_OFFSET);
+
+ } while (((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == (u32)FALSE) ||
+ (InstancePtr->TxBytes != 0) ||
+ ((QspiPsuStatusReg & XQSPIPSU_ISR_TXEMPTY_MASK) == (u32)FALSE));
+
+ if(InstancePtr->ReadMode == XQSPIPSU_READMODE_IO) {
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET, (XQspiPsu_ReadReg(
+ InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) |
+ XQSPIPSU_CFG_MODE_EN_DMA_MASK));
+ InstancePtr->ReadMode = XQSPIPSU_READMODE_DMA;
+ }
+ Index++;
+ }
+ return (s32)XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function check for DMA transfer complete.
+*
+* @param InstancePtr is a pointer to the XQspiPsu instance.
+*
+* @return
+* - XST_SUCCESS if DMA transfer complete.
+* - XST_FAILURE if DMA transfer is not completed.
+*
+* @note None.
+*
+******************************************************************************/
+s32 XQspiPsu_CheckDmaDone(XQspiPsu *InstancePtr)
+{
+ u32 QspiPsuStatusReg;
+ u32 DmaIntrSts;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ DmaIntrSts = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET);
+ if ((DmaIntrSts & XQSPIPSU_QSPIDMA_DST_I_STS_DONE_MASK) != (u32)FALSE) {
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_QSPIDMA_DST_I_STS_OFFSET, DmaIntrSts);
+ /* DMA transfer done, Invalidate Data Cache */
+ if (!((InstancePtr->Msg->RxAddr64bit >= XQSPIPSU_RXADDR_OVER_32BIT) ||
+ (InstancePtr->Msg->Xfer64bit != (u8)0U)) &&
+ (InstancePtr->Config.IsCacheCoherent == 0U)) {
+ Xil_DCacheInvalidateRange((INTPTR)InstancePtr->Msg->RxBfrPtr, (INTPTR)InstancePtr->RxBytes);
+ }
+ /* De-select slave */
+ XQspiPsu_GenFifoEntryCSDeAssert(InstancePtr);
+ if (InstancePtr->IsManualstart == (u8)TRUE) {
+#ifdef DEBUG
+ xil_printf("\nManual Start\r\n");
+#endif
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+ XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) |
+ XQSPIPSU_CFG_START_GEN_FIFO_MASK);
+ }
+ do {
+ QspiPsuStatusReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_ISR_OFFSET);
+ } while ((QspiPsuStatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) == (u32)FALSE);
+
+ /* Clear the busy flag. */
+ InstancePtr->IsBusy = (u32)FALSE;
+
+ return (s32)XST_SUCCESS;
+ }
+ else {
+ return (s32)XST_FAILURE;
+ }
+
+}
+/** @} */
diff --git a/bsps/shared/dev/spi/xqspipsu_control.c b/bsps/shared/dev/spi/xqspipsu_control.c
new file mode 100644
index 0000000000..af2400bf4c
--- /dev/null
+++ b/bsps/shared/dev/spi/xqspipsu_control.c
@@ -0,0 +1,282 @@
+/******************************************************************************
+* Copyright (C) 2020 - 2022 Xilinx, Inc. All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+
+/*****************************************************************************/
+/**
+ *
+ * @file xqspipsu_control.c
+ * @addtogroup Overview
+ * @{
+ *
+ * This file contains intermediate control functions used by functions
+ * in xqspipsu.c and xqspipsu_options.c files.
+ *
+ * <pre>
+ * MODIFICATION HISTORY:
+ *
+ * Ver Who Date Changes
+ * ----- --- -------- -----------------------------------------------
+ * 1.11 akm 03/09/20 First release
+ * 1.13 akm 01/04/21 Fix MISRA-C violations.
+ * 1.15 akm 10/21/21 Fix MISRA-C violations.
+ * 1.15 akm 03/03/22 Enable tapdelay settings for applications on
+ * Microblaze platform.
+ * </pre>
+ *
+ ******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xqspipsu_control.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+
+/*****************************************************************************/
+
+/*****************************************************************************/
+/**
+ *
+ * This function writes the GENFIFO entries to transmit the messages requested.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ *
+ * @return
+ * - XST_SUCCESS if successful.
+ * - XST_FAILURE if transfer fails.
+ * - XST_DEVICE_BUSY if a transfer is already in progress.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_GenFifoEntryData(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg)
+{
+ u32 GenFifoEntry;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Msg != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_GenFifoEntryData\r\n");
+#endif
+
+ GenFifoEntry = 0x0U;
+ /* Bus width */
+ GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_MODE_MASK;
+ GenFifoEntry |= XQspiPsu_SelectSpiMode((u8)Msg->BusWidth);
+
+ GenFifoEntry |= InstancePtr->GenFifoCS;
+ GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_BUS_MASK;
+ GenFifoEntry |= InstancePtr->GenFifoBus;
+
+ /* Data */
+ if (((Msg->Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != (u32)FALSE) {
+ GenFifoEntry |= XQSPIPSU_GENFIFO_STRIPE;
+ } else {
+ GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE;
+ }
+ /* If Byte Count is less than 8 bytes do the transfer in IO mode */
+ if ((Msg->ByteCount < 8U) &&
+ (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA)) {
+ InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+ (XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) &
+ ~XQSPIPSU_CFG_MODE_EN_MASK));
+ InstancePtr->IsUnaligned = 1;
+ }
+
+ XQspiPsu_TXRXSetup(InstancePtr, Msg, &GenFifoEntry);
+
+ XQspiPsu_GenFifoEntryDataLen(InstancePtr, Msg, &GenFifoEntry);
+
+ /* One dummy GenFifo entry in case of IO mode */
+ if ((InstancePtr->ReadMode == XQSPIPSU_READMODE_IO) &&
+ ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
+ GenFifoEntry = 0x0U;
+#ifdef DEBUG
+ xil_printf("\nDummy FifoEntry=%08x\r\n", GenFifoEntry);
+#endif
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
+ }
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function enables the polling functionality of controller
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ *
+ * @param FlashMsg is a pointer to the structure containing transfer data
+ *
+ * @return None
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_PollDataConfig(XQspiPsu *InstancePtr, XQspiPsu_Msg *FlashMsg)
+{
+
+ u32 GenFifoEntry;
+ u32 Value;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(FlashMsg != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_PollDataConfig\r\n");
+#endif
+
+ Value = XQspiPsu_CreatePollDataConfig(InstancePtr, FlashMsg);
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_POLL_CFG_OFFSET, Value);
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_P_TO_OFFSET, FlashMsg->PollTimeout);
+
+ XQspiPsu_GenFifoEntryCSAssert(InstancePtr);
+
+ GenFifoEntry = (u32)0;
+ GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_TX;
+ GenFifoEntry |= InstancePtr->GenFifoBus;
+ GenFifoEntry |= InstancePtr->GenFifoCS;
+ GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_MODE_SPI;
+ GenFifoEntry |= (u32)FlashMsg->PollStatusCmd;
+
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_GEN_FIFO_OFFSET, GenFifoEntry);
+
+ GenFifoEntry = (u32)0;
+ GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_POLL;
+ GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_RX;
+ GenFifoEntry |= InstancePtr->GenFifoBus;
+ GenFifoEntry |= InstancePtr->GenFifoCS;
+ GenFifoEntry |= (u32)XQSPIPSU_GENFIFO_MODE_SPI;
+ if (((FlashMsg->Flags) & XQSPIPSU_MSG_FLAG_STRIPE) != (u32)FALSE) {
+ GenFifoEntry |= XQSPIPSU_GENFIFO_STRIPE;
+ } else {
+ GenFifoEntry &= ~XQSPIPSU_GENFIFO_STRIPE;
+ }
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
+ GenFifoEntry);
+
+ /* One Dummy entry required for IO mode */
+ GenFifoEntry = 0x0U;
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
+ GenFifoEntry);
+
+ InstancePtr->Msg = FlashMsg;
+ InstancePtr->NumMsg = (s32)1;
+ InstancePtr->MsgCnt = 0;
+
+ Value = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET);
+ Value &= ~XQSPIPSU_CFG_MODE_EN_MASK;
+ Value |= (XQSPIPSU_CFG_START_GEN_FIFO_MASK |
+ XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK |
+ XQSPIPSU_CFG_EN_POLL_TO_MASK);
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+ Value);
+
+ /* Enable interrupts */
+ Value = ((u32)XQSPIPSU_IER_RXNEMPTY_MASK |
+ (u32)XQSPIPSU_IER_POLL_TIME_EXPIRE_MASK);
+
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_IER_OFFSET,
+ Value);
+
+}
+
+#if defined (ARMR5) || defined (__aarch64__) || defined (__MICROBLAZE__)
+/*****************************************************************************/
+/**
+*
+* Configures the clock according to the prescaler passed.
+*
+*
+* @param InstancePtr is a pointer to the XQspiPsu instance.
+* @param Prescaler - clock prescaler.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_DEVICE_BUSY if the device is currently transferring data.
+* The transfer must complete or be aborted before setting Tapdelay.
+*
+* @note None.
+*
+******************************************************************************/
+s32 XQspipsu_Calculate_Tapdelay(const XQspiPsu *InstancePtr, u8 Prescaler)
+{
+ u32 FreqDiv, Divider;
+ u32 Tapdelay = 0;
+ u32 LBkModeReg = 0;
+ u32 delayReg = 0;
+ s32 Status;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+ Xil_AssertNonvoid(Prescaler <= XQSPIPSU_CR_PRESC_MAXIMUM);
+
+ /*
+ * Do not allow the slave select to change while a transfer is in
+ * progress. Not thread-safe.
+ */
+ if (InstancePtr->IsBusy == (u32)TRUE) {
+ Status = (s32)XST_DEVICE_BUSY;
+ goto END;
+ } else {
+
+ Divider = (u32)1U << (Prescaler+1U);
+
+ FreqDiv = (InstancePtr->Config.InputClockHz)/Divider;
+
+#if defined (versal)
+ if (FreqDiv <= XQSPIPSU_FREQ_37_5MHZ) {
+#else
+ if (FreqDiv <= XQSPIPSU_FREQ_40MHZ) {
+#endif
+ Tapdelay |= (TAPDLY_BYPASS_VALVE_40MHZ <<
+ IOU_TAPDLY_BYPASS_LQSPI_RX_SHIFT);
+ } else if (FreqDiv <= XQSPIPSU_FREQ_100MHZ) {
+ Tapdelay |= (TAPDLY_BYPASS_VALVE_100MHZ <<
+ IOU_TAPDLY_BYPASS_LQSPI_RX_SHIFT);
+ LBkModeReg |= (USE_DLY_LPBK << XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT);
+#if defined (versal)
+ delayReg |= (u32)USE_DATA_DLY_ADJ <<
+ XQSPIPSU_DATA_DLY_ADJ_USE_DATA_DLY_SHIFT;
+#else
+ delayReg |= ((u32)USE_DATA_DLY_ADJ <<
+ XQSPIPSU_DATA_DLY_ADJ_USE_DATA_DLY_SHIFT) |
+ ((u32)DATA_DLY_ADJ_DLY << XQSPIPSU_DATA_DLY_ADJ_DLY_SHIFT);
+#endif
+ } else if (FreqDiv <= XQSPIPSU_FREQ_150MHZ) {
+#if defined (versal)
+ LBkModeReg |= (USE_DLY_LPBK << XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT) |
+ (LPBK_DLY_ADJ_DLY1 << XQSPIPSU_LPBK_DLY_ADJ_DLY1_SHIFT);
+#else
+ LBkModeReg |= USE_DLY_LPBK << XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_SHIFT;
+#endif
+ } else {
+ Status = (s32)XST_FAILURE;
+ goto END;
+ }
+
+ Status = XQspipsu_Set_TapDelay(InstancePtr, Tapdelay, LBkModeReg, delayReg);
+ }
+
+ END:
+ return Status;
+}
+#endif
+/** @} */
diff --git a/bsps/shared/dev/spi/xqspipsu_hw.c b/bsps/shared/dev/spi/xqspipsu_hw.c
new file mode 100644
index 0000000000..6f7708893f
--- /dev/null
+++ b/bsps/shared/dev/spi/xqspipsu_hw.c
@@ -0,0 +1,768 @@
+/******************************************************************************
+* Copyright (C) 2020 - 2022 Xilinx, Inc. All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+
+/*****************************************************************************/
+/**
+ *
+ * @file xqspipsu_hw.c
+ * @addtogroup Overview
+ * @{
+ *
+ * This file contains functions to reads RXFifo, writes TXFifo and setup
+ * RX DMA operation, used by xqspipsu_control.c and xqspipsu_lowlevel.c files.
+ *
+ * <pre>
+ * MODIFICATION HISTORY:
+ *
+ * Ver Who Date Changes
+ * ----- --- -------- -----------------------------------------------
+ * 1.11 akm 03/09/20 First release
+ * mn 03/30/20 Add xil_smc.h include for Xil_Smc calls
+ * 1.13 akm 01/04/21 Fix MISRA-C violations.
+ * 1.15 akm 10/21/21 Fix MISRA-C violations.
+ * 1.15 akm 11/16/21 Typecast function parameter with appropriate
+ * data type.
+ * 1.15 akm 11/30/21 Fix compilation warnings reported with -Wundef flag
+ * 1.15 akm 03/03/22 Enable tapdelay settings for applications on
+ * Microblaze platform.
+ *
+ * </pre>
+ ******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xqspipsu.h"
+#include "xqspipsu_control.h"
+#if defined (__aarch64__)
+#include "xil_smc.h"
+#endif
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+
+/*****************************************************************************/
+
+/*****************************************************************************/
+/**
+ *
+ * Fills the TX FIFO as long as there is room in the FIFO or the bytes required
+ * to be transmitted.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ * @param Size is the number of bytes to be transmitted.
+ *
+ * @return None
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_FillTxFifo(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg, u32 Size)
+{
+ u32 Count = 0;
+ u32 Data = 0U;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Msg != NULL);
+ Xil_AssertVoid(Size != 0U);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_FillTxFifo\r\n");
+#endif
+ while ((InstancePtr->TxBytes > 0) && (Count < Size)) {
+ if (InstancePtr->TxBytes >= 4) {
+ (void)Xil_MemCpy((u8 *)&Data, Msg->TxBfrPtr, 4);
+ Msg->TxBfrPtr += 4;
+ InstancePtr->TxBytes -= 4;
+ Count += 4U;
+ } else {
+ (void)Xil_MemCpy((u8 *)&Data, Msg->TxBfrPtr,
+ (u32)InstancePtr->TxBytes);
+ Msg->TxBfrPtr += InstancePtr->TxBytes;
+ Count += (u32)InstancePtr->TxBytes;
+ InstancePtr->TxBytes = 0;
+ }
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_TXD_OFFSET, Data);
+#ifdef DEBUG
+ xil_printf("\nData is %08x\r\n", Data);
+#endif
+
+ }
+ if (InstancePtr->TxBytes < 0) {
+ InstancePtr->TxBytes = 0;
+ }
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function checks the TX buffer in the message and setup the
+ * TX FIFO as required.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ *
+ * @return None
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_TXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg)
+{
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Msg != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_TXSetup\r\n");
+#endif
+ InstancePtr->TxBytes = (s32)Msg->ByteCount;
+ InstancePtr->SendBufferPtr = Msg->TxBfrPtr;
+
+ XQspiPsu_FillTxFifo(InstancePtr, Msg, (u32)XQSPIPSU_TXD_DEPTH);
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function sets up the RX DMA operation.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ *
+ * @return None
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_SetupRxDma(const XQspiPsu *InstancePtr,
+ XQspiPsu_Msg *Msg)
+{
+ s32 Remainder;
+ s32 DmaRxBytes;
+ UINTPTR AddrTemp;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Msg != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_SetupRxDma\r\n");
+#endif
+
+ AddrTemp = ((UINTPTR)(Msg->RxBfrPtr) & XQSPIPSU_QSPIDMA_DST_ADDR_MASK);
+ /* Check for RXBfrPtr to be word aligned */
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_ADDR_OFFSET, (u32)AddrTemp);
+
+#if defined(__aarch64__) || defined(__arch64__)
+ AddrTemp = ((UINTPTR)(Msg->RxBfrPtr) >> 32U);
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET, (u32)AddrTemp &
+ XQSPIPSU_QSPIDMA_DST_ADDR_MSB_MASK);
+#else
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET, 0U);
+#endif
+
+ Remainder = InstancePtr->RxBytes % 4;
+ DmaRxBytes = InstancePtr->RxBytes;
+ if (Remainder != 0) {
+ /* This is done to make Dma bytes aligned */
+ DmaRxBytes = InstancePtr->RxBytes - Remainder;
+ Msg->ByteCount = (u32)DmaRxBytes;
+ }
+ if (InstancePtr->Config.IsCacheCoherent == 0U) {
+ Xil_DCacheInvalidateRange((INTPTR)Msg->RxBfrPtr, (INTPTR)Msg->ByteCount);
+ }
+ /* Write no. of words to DMA DST SIZE */
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_SIZE_OFFSET, (u32)DmaRxBytes);
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function sets up the RX DMA operation on a 32bit Machine
+ * For 64bit Dma transfers.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ *
+ * @return None
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_Setup64BRxDma(const XQspiPsu *InstancePtr,
+ XQspiPsu_Msg *Msg)
+{
+ s32 Remainder;
+ s32 DmaRxBytes;
+ u64 AddrTemp;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Msg != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_Setup64BRxDma\r\n");
+#endif
+ AddrTemp = Msg->RxAddr64bit & XQSPIPSU_QSPIDMA_DST_ADDR_MASK;
+
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_ADDR_OFFSET, (u32)AddrTemp);
+
+ AddrTemp = (Msg->RxAddr64bit >> 32);
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_ADDR_MSB_OFFSET, (u32)AddrTemp &
+ XQSPIPSU_QSPIDMA_DST_ADDR_MSB_MASK);
+
+ Remainder = InstancePtr->RxBytes % 4;
+ DmaRxBytes = InstancePtr->RxBytes;
+ if (Remainder != 0) {
+ /* This is done to make Dma bytes aligned */
+ DmaRxBytes = InstancePtr->RxBytes - Remainder;
+ Msg->ByteCount = (u32)DmaRxBytes;
+ }
+
+ /* Write no. of words to DMA DST SIZE */
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_SIZE_OFFSET, (u32)DmaRxBytes);
+
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function reads remaining bytes, after the completion of a DMA transfer,
+ * using IO mode
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ *
+ * @return
+ * - XST_SUCCESS if successful.
+ * - XST_FAILURE if transfer fails.
+ * - XST_DEVICE_BUSY if a transfer is already in progress.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+u32 XQspiPsu_SetIOMode(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg)
+{
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(Msg != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_DMARXComplete\r\n");
+#endif
+
+ /* Read remaining bytes using IO mode */
+ if ((InstancePtr->RxBytes % 4) != 0) {
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+ (XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET) &
+ ~XQSPIPSU_CFG_MODE_EN_MASK));
+ InstancePtr->ReadMode = XQSPIPSU_READMODE_IO;
+ Msg->ByteCount = (u32)InstancePtr->RxBytes % 4U;
+ Msg->RxBfrPtr += (InstancePtr->RxBytes - (InstancePtr->RxBytes % 4));
+ InstancePtr->IsUnaligned = 1;
+ return (u32) TRUE;
+ }
+ return (u32) FALSE;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function checks the RX buffers in the message and setup the
+ * RX DMA as required.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ *
+ * @return None
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_RXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg)
+{
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Msg != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_RXSetup\r\n");
+#endif
+ InstancePtr->RxBytes = (s32)Msg->ByteCount;
+
+ if (InstancePtr->ReadMode == XQSPIPSU_READMODE_DMA) {
+ if ((Msg->RxAddr64bit >= XQSPIPSU_RXADDR_OVER_32BIT) ||
+ (Msg->Xfer64bit != (u8)0U)) {
+ XQspiPsu_Setup64BRxDma(InstancePtr, Msg);
+ } else {
+ XQspiPsu_SetupRxDma(InstancePtr, Msg);
+ }
+ }
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function checks the TX/RX buffers in the message and setups up the
+ * GENFIFO entries, TX FIFO or RX DMA as required.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ * @param GenFifoEntry is pointer to the variable in which GENFIFO mask
+ * is returned to calling function
+ *
+ * @return None
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_TXRXSetup(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+ u32 *GenFifoEntry)
+{
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Msg != NULL);
+ Xil_AssertVoid(GenFifoEntry != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_TXRXSetup\r\n");
+#endif
+ /* Transmit */
+ if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) &&
+ ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == (u32)FALSE)) {
+
+ *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
+ *GenFifoEntry |= XQSPIPSU_GENFIFO_TX;
+ /* Discard RX data */
+ *GenFifoEntry &= ~XQSPIPSU_GENFIFO_RX;
+
+ /* Setup data to be TXed */
+ XQspiPsu_TXSetup(InstancePtr, Msg);
+
+ InstancePtr->RecvBufferPtr = NULL;
+ InstancePtr->RxBytes = 0;
+ }
+ /*Receive*/
+ if (((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE) &&
+ ((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == (u32)FALSE)) {
+
+ /* TX auto fill */
+ *GenFifoEntry &= ~XQSPIPSU_GENFIFO_TX;
+ /* Setup RX */
+ *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
+ *GenFifoEntry |= XQSPIPSU_GENFIFO_RX;
+
+ /* Setup DMA for data to be RXed */
+ XQspiPsu_RXSetup(InstancePtr, Msg);
+
+ InstancePtr->SendBufferPtr = NULL;
+ InstancePtr->TxBytes = 0;
+ }
+ /* If only dummy is requested as a separate entry */
+ if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) == (u32)FALSE) &&
+ ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) == (u32)FALSE)) {
+
+ *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
+ *GenFifoEntry &= ~(XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX);
+ InstancePtr->TxBytes = 0;
+ InstancePtr->RxBytes = 0;
+ InstancePtr->SendBufferPtr = NULL;
+ InstancePtr->RecvBufferPtr = NULL;
+ }
+ /* Dummy and cmd sent by upper layer to received data */
+ if (((Msg->Flags & XQSPIPSU_MSG_FLAG_TX) != (u32)FALSE) &&
+ ((Msg->Flags & XQSPIPSU_MSG_FLAG_RX) != (u32)FALSE)) {
+ *GenFifoEntry |= XQSPIPSU_GENFIFO_DATA_XFER;
+ *GenFifoEntry |= (XQSPIPSU_GENFIFO_TX | XQSPIPSU_GENFIFO_RX);
+
+ /* Setup data to be TXed */
+ XQspiPsu_TXSetup(InstancePtr, Msg);
+ /* Setup DMA for data to be RXed */
+ XQspiPsu_RXSetup(InstancePtr, Msg);
+ }
+}
+/*****************************************************************************/
+/**
+ *
+ * This function writes the Data length to GENFIFO entries that need to be
+ * transmitted or received.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ * @param GenFifoEntry is index of the current message to be handled.
+ *
+ * @return
+ * - XST_SUCCESS if successful.
+ * - XST_FAILURE if transfer fails.
+ * - XST_DEVICE_BUSY if a transfer is already in progress.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_GenFifoEntryDataLen(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+ u32 *GenFifoEntry)
+{
+ u32 TempCount;
+ u32 ImmData;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Msg != NULL);
+ Xil_AssertVoid(GenFifoEntry != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_GenFifoEntryDataLen\r\n");
+#endif
+
+ if (Msg->ByteCount <= XQSPIPSU_GENFIFO_IMM_DATA_MASK) {
+ *GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_IMM_DATA_MASK;
+ *GenFifoEntry |= Msg->ByteCount;
+ #ifdef DEBUG
+ xil_printf("\nFifoEntry=%08x\r\n", *GenFifoEntry);
+ #endif
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
+ *GenFifoEntry);
+ } else {
+ TempCount = Msg->ByteCount;
+ u32 Exponent = 8; /* 2^8 = 256 */
+ ImmData = TempCount & 0xFFU;
+ /* Exponent entries */
+ *GenFifoEntry |= XQSPIPSU_GENFIFO_EXP;
+ while (TempCount != 0U) {
+ if ((TempCount & XQSPIPSU_GENFIFO_EXP_START) != (u32)FALSE) {
+ *GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_IMM_DATA_MASK;
+ *GenFifoEntry |= Exponent;
+ #ifdef DEBUG
+ xil_printf("\nFifoEntry=%08x\r\n",
+ *GenFifoEntry);
+ #endif
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
+ *GenFifoEntry);
+ }
+ TempCount = TempCount >> 1;
+ Exponent++;
+ }
+ /* Immediate entry */
+ *GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_EXP;
+ if ((ImmData & 0xFFU) != (u32)FALSE) {
+ *GenFifoEntry &= ~(u32)XQSPIPSU_GENFIFO_IMM_DATA_MASK;
+ *GenFifoEntry |= ImmData & 0xFFU;
+ #ifdef DEBUG
+ xil_printf("\nFifoEntry=%08x\r\n", *GenFifoEntry);
+ #endif
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_GEN_FIFO_OFFSET,
+ *GenFifoEntry);
+ }
+ }
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function creates Poll config register data to write
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ * @param FlashMsg is a pointer to the structure containing transfer data.
+ *
+ * @return None
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+u32 XQspiPsu_CreatePollDataConfig(const XQspiPsu *InstancePtr,
+ const XQspiPsu_Msg *FlashMsg)
+{
+ u32 ConfigData = 0;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(FlashMsg != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_CreatePollDataConfig\r\n");
+#endif
+
+ if ((InstancePtr->GenFifoBus & XQSPIPSU_GENFIFO_BUS_UPPER) != (u32)FALSE) {
+ ConfigData = (u32)XQSPIPSU_SELECT_FLASH_BUS_LOWER <<
+ XQSPIPSU_POLL_CFG_EN_MASK_UPPER_SHIFT;
+ }
+ if ((InstancePtr->GenFifoBus & XQSPIPSU_GENFIFO_BUS_LOWER) != (u32)FALSE) {
+ ConfigData |= (u32)XQSPIPSU_SELECT_FLASH_BUS_LOWER <<
+ XQSPIPSU_POLL_CFG_EN_MASK_LOWER_SHIFT;
+ }
+ ConfigData |= (u32)(((u32)FlashMsg->PollBusMask <<
+ XQSPIPSU_POLL_CFG_MASK_EN_SHIFT) & XQSPIPSU_POLL_CFG_MASK_EN_MASK);
+ ConfigData |= (u32)(((u32)FlashMsg->PollData <<
+ XQSPIPSU_POLL_CFG_DATA_VALUE_SHIFT)
+ & XQSPIPSU_POLL_CFG_DATA_VALUE_MASK);
+ return ConfigData;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * Selects SPI mode - x1 or x2 or x4.
+ *
+ * @param SpiMode - spi or dual or quad.
+ * @return Mask to set desired SPI mode in GENFIFO entry.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+u32 XQspiPsu_SelectSpiMode(u8 SpiMode)
+{
+ u32 Mask;
+
+ Xil_AssertNonvoid(SpiMode > 0U);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_SelectSpiMode\r\n");
+#endif
+
+ switch (SpiMode) {
+ case XQSPIPSU_SELECT_MODE_DUALSPI:
+ Mask = XQSPIPSU_GENFIFO_MODE_DUALSPI;
+ break;
+ case XQSPIPSU_SELECT_MODE_QUADSPI:
+ Mask = XQSPIPSU_GENFIFO_MODE_QUADSPI;
+ break;
+ case XQSPIPSU_SELECT_MODE_SPI:
+ Mask = XQSPIPSU_GENFIFO_MODE_SPI;
+ break;
+ default:
+ Mask = XQSPIPSU_GENFIFO_MODE_SPI;
+ break;
+ }
+#ifdef DEBUG
+ xil_printf("\nSPIMode is %08x\r\n", SpiMode);
+#endif
+ return Mask;
+}
+
+/*****************************************************************************/
+/**
+ *
+ * Enable and initialize DMA Mode, set little endain, disable poll timeout,
+ * clear prescalar bits and reset thresholds
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ *
+ * @return None.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_SetDefaultConfig(XQspiPsu *InstancePtr)
+{
+ u32 ConfigReg;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_SetDefaultConfig\r\n");
+#endif
+
+ /* Default value to config register */
+ ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET);
+
+ /* DMA mode */
+ ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
+ ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
+ /* Manual start */
+ ConfigReg |= XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK;
+ /* Little endain by default */
+ ConfigReg &= ~XQSPIPSU_CFG_ENDIAN_MASK;
+ /* Disable poll timeout */
+ ConfigReg &= ~XQSPIPSU_CFG_EN_POLL_TO_MASK;
+ /* Set hold bit */
+ ConfigReg |= XQSPIPSU_CFG_WP_HOLD_MASK;
+ /* Clear prescalar by default */
+ ConfigReg &= ~(u32)XQSPIPSU_CFG_BAUD_RATE_DIV_MASK;
+ /* CPOL CPHA 00 */
+ ConfigReg &= ~(u32)XQSPIPSU_CFG_CLK_PHA_MASK;
+ ConfigReg &= ~(u32)XQSPIPSU_CFG_CLK_POL_MASK;
+
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET, ConfigReg);
+
+ /* Set by default to allow for high frequencies */
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_LPBK_DLY_ADJ_OFFSET,
+ XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_LPBK_DLY_ADJ_OFFSET) |
+ XQSPIPSU_LPBK_DLY_ADJ_USE_LPBK_MASK);
+
+ /* Reset thresholds */
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_TX_THRESHOLD_OFFSET, XQSPIPSU_TX_FIFO_THRESHOLD_RESET_VAL);
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_RX_THRESHOLD_OFFSET, XQSPIPSU_RX_FIFO_THRESHOLD_RESET_VAL);
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_GF_THRESHOLD_OFFSET, XQSPIPSU_GEN_FIFO_THRESHOLD_RESET_VAL);
+
+ /* DMA init */
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_QSPIDMA_DST_CTRL_OFFSET,
+ XQSPIPSU_QSPIDMA_DST_CTRL_RESET_VAL);
+}
+
+/*****************************************************************************/
+/**
+ *
+ * Read the specified number of bytes from RX FIFO
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ * @param Size is the number of bytes to be read.
+ *
+ * @return None
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_ReadRxFifo(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg, s32 Size)
+{
+ s32 Count = 0;
+ u32 Data;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Msg != NULL);
+ Xil_AssertVoid(Size > 0);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_ReadRxFifo\r\n");
+#endif
+ while ((InstancePtr->RxBytes != 0) && (Count < Size)) {
+ Data = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_RXD_OFFSET);
+#ifdef DEBUG
+ xil_printf("\nData is %08x\r\n", Data);
+#endif
+ if (InstancePtr->RxBytes >= 4) {
+ (void)Xil_MemCpy(Msg->RxBfrPtr, (u8 *)&Data, 4);
+ InstancePtr->RxBytes -= 4;
+ Msg->RxBfrPtr += 4;
+ Count += 4;
+ } else {
+ /* Read unaligned bytes (< 4 bytes) */
+ (void)Xil_MemCpy(Msg->RxBfrPtr, (u8 *)&Data,
+ (u32)InstancePtr->RxBytes);
+ Msg->RxBfrPtr += InstancePtr->RxBytes;
+ Count += InstancePtr->RxBytes;
+ InstancePtr->RxBytes = 0;
+ }
+ }
+}
+
+/*****************************************************************************/
+/**
+ *
+ * This function reads data from RXFifo in IO mode.
+ *
+ * @param InstancePtr is a pointer to the XQspiPsu instance.
+ * @param Msg is a pointer to the structure containing transfer data.
+ * @param StatusReg is the Interrupt status Register value.
+ *
+ * @return None.
+ *
+ * @note None.
+ *
+ ******************************************************************************/
+void XQspiPsu_IORead(XQspiPsu *InstancePtr, XQspiPsu_Msg *Msg,
+ u32 StatusReg)
+{
+ s32 RxThr;
+
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(Msg != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_IORXComplete\r\n");
+#endif
+
+ if ((StatusReg & XQSPIPSU_ISR_RXNEMPTY_MASK) != 0U) {
+ /*
+ * Check if PIO RX is complete and
+ * update RxBytes
+ */
+ RxThr = (s32)XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_RX_THRESHOLD_OFFSET);
+ RxThr = RxThr*4;
+ XQspiPsu_ReadRxFifo(InstancePtr, Msg, RxThr);
+
+ return;
+ }
+
+ if ((StatusReg & XQSPIPSU_ISR_GENFIFOEMPTY_MASK) != 0U) {
+ XQspiPsu_ReadRxFifo(InstancePtr, Msg, InstancePtr->RxBytes);
+ }
+}
+
+#if defined (ARMR5) || defined (__aarch64__) || defined (__MICROBLAZE__)
+/*****************************************************************************/
+/**
+*
+* This function sets the Tapdelay values for the QSPIPSU device driver.The device
+* must be idle rather than busy transferring data before setting Tapdelay.
+*
+* @param InstancePtr is a pointer to the XQspiPsu instance.
+* @param TapdelayBypss contains the IOU_TAPDLY_BYPASS register value.
+* @param LPBKDelay contains the GQSPI_LPBK_DLY_ADJ register value.
+* @param Datadelay contains the QSPI_DATA_DLY_ADJ register value.
+*
+* @return
+* - XST_SUCCESS if options are successfully set.
+* - XST_DEVICE_BUSY if the device is currently transferring data.
+* The transfer must complete or be aborted before setting TapDelay.
+*
+* @note
+* This function is not thread-safe.
+*
+******************************************************************************/
+s32 XQspipsu_Set_TapDelay(const XQspiPsu *InstancePtr, u32 TapdelayBypass,
+ u32 LPBKDelay, u32 Datadelay)
+{
+ s32 Status;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ /*
+ * Do not allow to modify the Control Register while a transfer is in
+ * progress. Not thread-safe.
+ */
+ if (InstancePtr->IsBusy == (u32)TRUE) {
+ Status = (s32)XST_DEVICE_BUSY;
+ } else {
+#if defined (__aarch64__) && (EL1_NONSECURE == 1) && !defined (versal)
+ Xil_Smc(MMIO_WRITE_SMC_FID, (u64)(XPS_SYS_CTRL_BASEADDR +
+ IOU_TAPDLY_BYPASS_OFFSET) | ((u64)(0x4) << 32),
+ (u64)TapdelayBypass, 0, 0, 0, 0, 0);
+#elif defined (versal)
+ XQspiPsu_WriteReg(XQSPIPS_BASEADDR, IOU_TAPDLY_BYPASS_OFFSET,
+ TapdelayBypass);
+#else
+ XQspiPsu_WriteReg(XPS_SYS_CTRL_BASEADDR, IOU_TAPDLY_BYPASS_OFFSET,
+ TapdelayBypass);
+#endif
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_LPBK_DLY_ADJ_OFFSET, LPBKDelay);
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_DATA_DLY_ADJ_OFFSET, Datadelay);
+
+ Status = (s32)XST_SUCCESS;
+ }
+ return Status;
+}
+#endif
+/** @} */
diff --git a/bsps/shared/dev/spi/xqspipsu_options.c b/bsps/shared/dev/spi/xqspipsu_options.c
new file mode 100644
index 0000000000..c889d64abb
--- /dev/null
+++ b/bsps/shared/dev/spi/xqspipsu_options.c
@@ -0,0 +1,532 @@
+/******************************************************************************
+* Copyright (C) 2014 - 2022 Xilinx, Inc. All rights reserved.
+* SPDX-License-Identifier: MIT
+******************************************************************************/
+
+/*****************************************************************************/
+/**
+*
+* @file xqspipsu_options.c
+* @addtogroup Overview
+* @{
+*
+* This file implements functions to configure the QSPIPSU component,
+* specifically some optional settings, clock and flash related information.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- --- -------- -----------------------------------------------
+* 1.0 hk 08/21/14 First release
+* sk 03/13/15 Added IO mode support.
+* sk 04/24/15 Modified the code according to MISRAC-2012.
+* 1.1 sk 04/12/16 Added debug message prints.
+* 1.2 nsk 07/01/16 Modified XQspiPsu_SetOptions() to support
+* LQSPI options and updated OptionsTable
+* rk 07/15/16 Added support for TapDelays at different frequencies.
+* 1.7 tjs 01/17/18 Added support to toggle the WP pin of flash. (PR#2448)
+* 1.7 tjs 03/14/18 Added support in EL1 NS mode. (CR#974882)
+* 1.8 tjs 05/02/18 Added support for IS25LP064 and IS25WP064.
+* 1.8 tjs 07/26/18 Resolved cppcheck errors. (CR#1006336)
+* 1.9 tjs 04/17/18 Updated register addresses as per the latest revision
+* of versal (CR#999610)
+* 1.9 aru 01/17/19 Fixes violations according to MISRAC-2012
+* in safety mode and modified the code such as
+* Added Xil_MemCpy inplace of memcpy,Declared the pointer param
+* as Pointer to const, declared XQspi_Set_TapDelay() as static.
+* 1.9 akm 03/08/19 Set recommended clock and data tap delay values for 40MHZ,
+* 100MHZ and 150MHZ frequencies(CR#1023187)
+* 1.10 akm 08/22/19 Set recommended tap delay values for 37.5MHZ, 100MHZ and
+* 150MHZ frequencies in Versal.
+* 1.11 akm 11/07/19 Removed LQSPI register access in Versal.
+* 1.11 akm 11/15/19 Fixed Coverity deadcode warning in
+* XQspipsu_Calculate_Tapdelay().
+* 1.11 akm 03/09/20 Reorganize the source code, enable qspi controller and
+* interrupts in XQspiPsu_CfgInitialize() API.
+* 1.13 akm 01/04/21 Fix MISRA-C violations.
+* 1.15 akm 03/03/22 Enable tapdelay settings for applications on Microblaze
+* platform.
+*
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xqspipsu_control.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+
+/**
+ * Create the table of options which are processed to get/set the device
+ * options. These options are table driven to allow easy maintenance and
+ * expansion of the options.
+ */
+typedef struct {
+ u32 Option; /**< Get/Set the device option */
+ u32 Mask; /**< Mask */
+} OptionsMap;
+
+static OptionsMap OptionsTable[] = {
+ {XQSPIPSU_CLK_ACTIVE_LOW_OPTION, XQSPIPSU_CFG_CLK_POL_MASK},
+ {XQSPIPSU_CLK_PHASE_1_OPTION, XQSPIPSU_CFG_CLK_PHA_MASK},
+ {XQSPIPSU_MANUAL_START_OPTION, XQSPIPSU_CFG_GEN_FIFO_START_MODE_MASK},
+#if !defined (versal)
+ {XQSPIPSU_LQSPI_MODE_OPTION, XQSPIPSU_CFG_WP_HOLD_MASK},
+#endif
+};
+
+/**
+ * Number of options in option table
+ */
+#define XQSPIPSU_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(OptionsMap))
+
+/*****************************************************************************/
+/**
+*
+* This function sets the options for the QSPIPSU device driver.The options
+* control how the device behaves relative to the QSPIPSU bus. The device must be
+* idle rather than busy transferring data before setting these device options.
+*
+* @param InstancePtr is a pointer to the XQspiPsu instance.
+* @param Options contains the specified options to be set. This is a bit
+* mask where a 1 indicates the option should be turned ON and
+* a 0 indicates no action. One or more bit values may be
+* contained in the mask. See the bit definitions named
+* XQSPIPSU_*_OPTIONS in the file xqspipsu.h.
+*
+* @return
+* - XST_SUCCESS if options are successfully set.
+* - XST_DEVICE_BUSY if the device is currently transferring data.
+* The transfer must complete or be aborted before setting options.
+*
+* @note
+* This function is not thread-safe.
+*
+******************************************************************************/
+s32 XQspiPsu_SetOptions(XQspiPsu *InstancePtr, u32 Options)
+{
+ u32 ConfigReg;
+ u32 Index;
+#if !defined (versal)
+ u32 QspiPsuOptions;
+#endif
+ s32 Status;
+ u32 OptionsVal;
+ OptionsVal = Options;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ /*
+ * Do not allow to modify the Control Register while a transfer is in
+ * progress. Not thread-safe.
+ */
+ if (InstancePtr->IsBusy == (u32)TRUE) {
+ Status = (s32)XST_DEVICE_BUSY;
+ } else {
+ ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET);
+#if !defined (versal)
+ QspiPsuOptions = OptionsVal & XQSPIPSU_LQSPI_MODE_OPTION;
+ OptionsVal &= (~XQSPIPSU_LQSPI_MODE_OPTION);
+#endif
+ /*
+ * Loop through the options table, turning the option on
+ * depending on whether the bit is set in the incoming options flag.
+ */
+ for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
+ if ((OptionsVal & OptionsTable[Index].Option) ==
+ OptionsTable[Index].Option) {
+ /* Turn it on */
+ ConfigReg |= OptionsTable[Index].Mask;
+ } else {
+ /* Turn it off */
+ ConfigReg &= ~(OptionsTable[Index].Mask);
+ }
+ }
+ /*
+ * Now write the control register. Leave it to the upper layers
+ * to restart the device.
+ */
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+ ConfigReg);
+
+ if ((OptionsVal & XQSPIPSU_MANUAL_START_OPTION) != (u32)FALSE) {
+ InstancePtr->IsManualstart = (u8)TRUE;
+ }
+#if !defined (versal)
+ if ((QspiPsuOptions & XQSPIPSU_LQSPI_MODE_OPTION) != (u32)FALSE) {
+ if ((Options & XQSPIPSU_LQSPI_LESS_THEN_SIXTEENMB) != (u32)FALSE) {
+ XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET,XQSPIPS_LQSPI_CR_RST_STATE);
+ } else {
+ XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET,XQSPIPS_LQSPI_CR_4_BYTE_STATE);
+ }
+ XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_CFG_OFFSET,XQSPIPS_LQSPI_CFG_RST_STATE);
+ /* Enable the QSPI controller */
+ XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_EN_OFFSET,XQSPIPSU_EN_MASK);
+ } else {
+ /*
+ * Check for the LQSPI configuration options.
+ */
+ ConfigReg = XQspiPsu_ReadReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET);
+ ConfigReg &= ~(XQSPIPSU_LQSPI_CR_LINEAR_MASK);
+ XQspiPsu_WriteReg(XQSPIPS_BASEADDR,XQSPIPSU_LQSPI_CR_OFFSET, ConfigReg);
+ }
+#endif
+ Status = (s32)XST_SUCCESS;
+ }
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function resets the options for the QSPIPSU device driver.The options
+* control how the device behaves relative to the QSPIPSU bus. The device must be
+* idle rather than busy transferring data before setting these device options.
+*
+* @param InstancePtr is a pointer to the XQspiPsu instance.
+* @param Options contains the specified options to be set. This is a bit
+* mask where a 1 indicates the option should be turned OFF and
+* a 0 indicates no action. One or more bit values may be
+* contained in the mask. See the bit definitions named
+* XQSPIPSU_*_OPTIONS in the file xqspipsu.h.
+*
+* @return
+* - XST_SUCCESS if options are successfully set.
+* - XST_DEVICE_BUSY if the device is currently transferring data.
+* The transfer must complete or be aborted before setting options.
+*
+* @note
+* This function is not thread-safe.
+*
+******************************************************************************/
+s32 XQspiPsu_ClearOptions(XQspiPsu *InstancePtr, u32 Options)
+{
+ u32 ConfigReg;
+ u32 Index;
+ s32 Status;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ /*
+ * Do not allow to modify the Control Register while a transfer is in
+ * progress. Not thread-safe.
+ */
+ if (InstancePtr->IsBusy == (u32)TRUE) {
+ Status = (s32)XST_DEVICE_BUSY;
+ } else {
+
+ ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET);
+
+ /*
+ * Loop through the options table, turning the option on
+ * depending on whether the bit is set in the incoming options flag.
+ */
+ for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
+ if ((Options & OptionsTable[Index].Option) != (u32)FALSE) {
+ /* Turn it off */
+ ConfigReg &= ~OptionsTable[Index].Mask;
+ }
+ }
+ /*
+ * Now write the control register. Leave it to the upper layers
+ * to restart the device.
+ */
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+ ConfigReg);
+
+ if ((Options & XQSPIPSU_MANUAL_START_OPTION) != (u32)FALSE) {
+ InstancePtr->IsManualstart = (u8)FALSE;
+ }
+
+ Status = (s32)XST_SUCCESS;
+ }
+
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function gets the options for the QSPIPSU device. The options control how
+* the device behaves relative to the QSPIPSU bus.
+*
+* @param InstancePtr is a pointer to the XQspiPsu instance.
+*
+* @return
+*
+* Options contains the specified options currently set. This is a bit value
+* where a 1 means the option is on, and a 0 means the option is off.
+* See the bit definitions named XQSPIPSU_*_OPTIONS in file xqspipsu.h.
+*
+* @note None.
+*
+******************************************************************************/
+u32 XQspiPsu_GetOptions(const XQspiPsu *InstancePtr)
+{
+ u32 OptionsFlag = 0;
+ u32 ConfigReg;
+ u32 Index;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+ /* Loop through the options table to grab options */
+ for (Index = 0U; Index < XQSPIPSU_NUM_OPTIONS; Index++) {
+ /*
+ * Get the current options from QSPIPSU configuration register.
+ */
+ ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET);
+ if ((ConfigReg & OptionsTable[Index].Mask) != (u32)FALSE) {
+ OptionsFlag |= OptionsTable[Index].Option;
+ }
+ }
+ return OptionsFlag;
+}
+
+/*****************************************************************************/
+/**
+*
+* Configures the clock according to the prescaler passed.
+*
+*
+* @param InstancePtr is a pointer to the XQspiPsu instance.
+* @param Prescaler - clock prescaler to be set.
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_DEVICE_IS_STARTED if the device is already started.
+* - XST_DEVICE_BUSY if the device is currently transferring data.
+* It must be stopped to re-initialize.
+*
+* @note None.
+*
+******************************************************************************/
+s32 XQspiPsu_SetClkPrescaler(const XQspiPsu *InstancePtr, u8 Prescaler)
+{
+ u32 ConfigReg;
+ s32 Status;
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+ Xil_AssertNonvoid(Prescaler <= XQSPIPSU_CR_PRESC_MAXIMUM);
+
+ /*
+ * Do not allow the slave select to change while a transfer is in
+ * progress. Not thread-safe.
+ */
+ if (InstancePtr->IsBusy == (u32)TRUE) {
+ Status = (s32)XST_DEVICE_BUSY;
+ } else {
+ /*
+ * Read the configuration register, mask out the relevant bits, and set
+ * them with the shifted value passed into the function. Write the
+ * results back to the configuration register.
+ */
+ ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET);
+
+ ConfigReg &= ~(u32)XQSPIPSU_CFG_BAUD_RATE_DIV_MASK;
+ ConfigReg |= (u32) ((u32)Prescaler & (u32)XQSPIPSU_CR_PRESC_MAXIMUM) <<
+ XQSPIPSU_CFG_BAUD_RATE_DIV_SHIFT;
+
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+ ConfigReg);
+
+#if defined (ARMR5) || defined (__aarch64__) || defined (__MICROBLAZE__)
+ Status = XQspipsu_Calculate_Tapdelay(InstancePtr,Prescaler);
+#else
+ Status = (s32)XST_SUCCESS;
+#endif
+ }
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function should be used to tell the QSPIPSU driver the HW flash
+* configuration being used. This API should be called at least once in the
+* application. If desired, it can be called multiple times when switching
+* between communicating to different flahs devices/using different configs.
+*
+* @param InstancePtr is a pointer to the XQspiPsu instance.
+* @param FlashCS - Flash Chip Select.
+* @param FlashBus - Flash Bus (Upper, Lower or Both).
+*
+* @return
+* - XST_SUCCESS if successful.
+* - XST_DEVICE_IS_STARTED if the device is already started.
+* It must be stopped to re-initialize.
+*
+* @note If this function is not called at least once in the application,
+* the driver assumes there is a single flash connected to the
+* lower bus and CS line.
+*
+******************************************************************************/
+void XQspiPsu_SelectFlash(XQspiPsu *InstancePtr, u8 FlashCS, u8 FlashBus)
+{
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(FlashCS > 0U);
+ Xil_AssertVoid(FlashBus > 0U);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_SelectFlash\r\n");
+#endif
+
+ /*
+ * Bus and CS lines selected here will be updated in the instance and
+ * used for subsequent GENFIFO entries during transfer.
+ */
+
+ /* Choose slave select line */
+ switch (FlashCS) {
+ case XQSPIPSU_SELECT_FLASH_CS_BOTH:
+ InstancePtr->GenFifoCS = (u32)XQSPIPSU_GENFIFO_CS_LOWER |
+ (u32)XQSPIPSU_GENFIFO_CS_UPPER;
+ break;
+ case XQSPIPSU_SELECT_FLASH_CS_UPPER:
+ InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_UPPER;
+ break;
+ case XQSPIPSU_SELECT_FLASH_CS_LOWER:
+ InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
+ break;
+ default:
+ InstancePtr->GenFifoCS = XQSPIPSU_GENFIFO_CS_LOWER;
+ break;
+ }
+
+ /* Choose bus */
+ switch (FlashBus) {
+ case XQSPIPSU_SELECT_FLASH_BUS_BOTH:
+ InstancePtr->GenFifoBus = (u32)XQSPIPSU_GENFIFO_BUS_LOWER |
+ (u32)XQSPIPSU_GENFIFO_BUS_UPPER;
+ break;
+ case XQSPIPSU_SELECT_FLASH_BUS_UPPER:
+ InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_UPPER;
+ break;
+ case XQSPIPSU_SELECT_FLASH_BUS_LOWER:
+ InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
+ break;
+ default:
+ InstancePtr->GenFifoBus = XQSPIPSU_GENFIFO_BUS_LOWER;
+ break;
+ }
+#ifdef DEBUG
+ xil_printf("\nGenFifoCS is %08x and GenFifoBus is %08x\r\n",
+ InstancePtr->GenFifoCS, InstancePtr->GenFifoBus);
+#endif
+
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sets the Read mode for the QSPIPSU device driver.The device
+* must be idle rather than busy transferring data before setting Read mode
+* options.
+*
+* @param InstancePtr is a pointer to the XQspiPsu instance.
+* @param Mode contains the specified Mode to be set. See the
+* bit definitions named XQSPIPSU_READMODE_* in the file xqspipsu.h.
+*
+* @return
+* - XST_SUCCESS if options are successfully set.
+* - XST_DEVICE_BUSY if the device is currently transferring data.
+* The transfer must complete or be aborted before setting Mode.
+*
+* @note
+* This function is not thread-safe.
+*
+******************************************************************************/
+s32 XQspiPsu_SetReadMode(XQspiPsu *InstancePtr, u32 Mode)
+{
+ u32 ConfigReg;
+ s32 Status;
+
+#ifdef DEBUG
+ xil_printf("\nXQspiPsu_SetReadMode\r\n");
+#endif
+
+ Xil_AssertNonvoid(InstancePtr != NULL);
+ Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+ Xil_AssertNonvoid((Mode == XQSPIPSU_READMODE_DMA) || (Mode == XQSPIPSU_READMODE_IO));
+
+ /*
+ * Do not allow to modify the Control Register while a transfer is in
+ * progress. Not thread-safe.
+ */
+ if (InstancePtr->IsBusy == (u32)TRUE) {
+ Status = (s32)XST_DEVICE_BUSY;
+ } else {
+
+ InstancePtr->ReadMode = Mode;
+
+ ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET);
+
+ if (Mode == XQSPIPSU_READMODE_DMA) {
+ ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
+ ConfigReg |= XQSPIPSU_CFG_MODE_EN_DMA_MASK;
+ } else {
+ ConfigReg &= ~XQSPIPSU_CFG_MODE_EN_MASK;
+ }
+
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+ ConfigReg);
+
+ Status = (s32)XST_SUCCESS;
+ }
+#ifdef DEBUG
+ xil_printf("\nRead Mode is %08x\r\n", InstancePtr->ReadMode);
+#endif
+ return Status;
+}
+
+/*****************************************************************************/
+/**
+*
+* This function sets the Write Protect and Hold options for the QSPIPSU device
+* driver.The device must be idle rather than busy transferring data before
+* setting Write Protect and Hold options.
+*
+* @param InstancePtr is a pointer to the XQspiPsu instance.
+* @param Value of the WP_HOLD bit in configuration register
+*
+* @return None
+*
+* @note
+* This function is not thread-safe. This function can only be used with single
+* flash configuration and x1/x2 data mode. This function cannot be used with
+* x4 data mode and dual parallel and stacked flash configuration.
+*
+******************************************************************************/
+void XQspiPsu_SetWP(const XQspiPsu *InstancePtr, u8 Value)
+{
+ u32 ConfigReg;
+ Xil_AssertVoid(InstancePtr != NULL);
+ Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
+ Xil_AssertVoid(InstancePtr->IsBusy != TRUE);
+
+ ConfigReg = XQspiPsu_ReadReg(InstancePtr->Config.BaseAddress,
+ XQSPIPSU_CFG_OFFSET);
+ ConfigReg |= (u32)((u32)Value << XQSPIPSU_CFG_WP_HOLD_SHIFT);
+ XQspiPsu_WriteReg(InstancePtr->Config.BaseAddress, XQSPIPSU_CFG_OFFSET,
+ ConfigReg);
+}
+/** @} */