drivers: scugic: deprecated version 3.0 and created a new minor version 3.1

Signed-off-by: Kinjal Pravinbhai Patel <patelki@xilinx.com>
This commit is contained in:
Kinjal Pravinbhai Patel 2015-06-03 14:21:35 +05:30 committed by Nava kishore Manne
parent c7791d8bb0
commit de71767f08
17 changed files with 4508 additions and 0 deletions

View file

@ -0,0 +1,42 @@
###############################################################################
#
# Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
###############################################################################
OPTION psf_version = 2.1;
BEGIN driver scugic
OPTION supported_peripherals = (ps7_scugic psu_scugic psu_acpu_gic psu_rcpu_gic);
OPTION driver_state = ACTIVE;
OPTION copyfiles = all;
OPTION VERSION = 3.1;
OPTION NAME = scugic;
OPTION INTC_TYPE = XScuGic;
END driver

View file

@ -0,0 +1,562 @@
###############################################################################
#
# Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
###############################################################################
##############################################################################
#
# Modification History
#
# Ver Who Date Changes
# ----- ---- -------- -----------------------------------------------
# 1.00a sdm 04/18/11 Created
# 1.05a hk 06/26/13 Modified to export external interrupts correctly
# to xparameters.h. Fix for CR's 690505, 708928 & 719359
# 2.0 adk 12/10/13 Updated as per the New Tcl API's
# 2.1 adk 25/04/14 Added support for corenIRQ/FIQ interrupts.Fix for the
# CR#789373
# 3.0 pkp 12/09/14 Added support for Zynq Ultrascale Mp
##############################################################################
#uses "xillib.tcl"
############################################################
# "generate" procedure
############################################################
proc generate {drv_handle} {
xdefine_gic_params $drv_handle
xdefine_zynq_include_file $drv_handle "xparameters.h" "XScuGic" "NUM_INSTANCES" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" "C_DIST_BASEADDR"
xdefine_zynq_config_file $drv_handle "xscugic_g.c" "XScuGic" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_DIST_BASEADDR"
xdefine_zynq_canonical_xpars $drv_handle "xparameters.h" "ScuGic" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" "C_DIST_BASEADDR"
}
#
# Given a list of arguments, define them all in an include file.
# Similar to proc xdefine_include_file, except that uses regsub
# to replace "S_AXI_" with "".
#
proc xdefine_zynq_include_file {drv_handle file_name drv_string args} {
# Open include file
set file_handle [::hsi::utils::open_include_file $file_name]
# Get all peripherals connected to this driver
set periphs [::hsi::utils::get_common_driver_ips $drv_handle]
#Get the processor instance name
set sw_proc_handle [hsi::get_sw_processor]
set hw_proc_handle [hsi::get_cells [common::get_property HW_INSTANCE $sw_proc_handle] ]
set proctype [common::get_property IP_NAME $hw_proc_handle]
#Get proper gic instance for periphs in case of zynqmp
foreach periph $periphs {
if {([string compare -nocase $proctype "ps7_cortexa9"] == 0)||
(([string compare -nocase $proctype "psu_cortexa53"] == 0)&&([string compare -nocase $periph "psu_acpu_gic"] == 0))||
(([string compare -nocase $proctype "psu_cortexr5"] == 0)&&([string compare -nocase $periph "psu_rcpu_gic"] == 0))} {
lappend newperiphs $periph
}
}
set periphs $newperiphs
# Handle special cases
set arg "NUM_INSTANCES"
set posn [lsearch -exact $args $arg]
if {$posn > -1} {
puts $file_handle "/* Definitions for driver [string toupper [common::get_property NAME $drv_handle]] */"
# Define NUM_INSTANCES
puts $file_handle "#define [::hsi::utils::get_driver_param_name $drv_string $arg] [llength $periphs]"
set args [lreplace $args $posn $posn]
}
# Check if it is a driver parameter
lappend newargs
foreach arg $args {
set value [common::get_property CONFIG.$arg $drv_handle]
if {[llength $value] == 0} {
lappend newargs $arg
} else {
puts $file_handle "#define [::hsi::utils::get_driver_param_name $drv_string $arg] [common::get_property CONFIG.$arg $drv_handle]"
}
}
set args $newargs
# Print all parameters for all peripherals
set device_id 0
foreach periph $periphs {
puts $file_handle ""
puts $file_handle "/* Definitions for peripheral [string toupper [common::get_property NAME $periph]] */"
foreach arg $args {
if {[string compare -nocase "DEVICE_ID" $arg] == 0} {
set value $device_id
incr device_id
} elseif {[string compare -nocase "C_S_AXI_BASEADDR" $arg] == 0} {
if {[string compare -nocase $proctype "psu_cortexr5"] == 0} {
set value 0xF9001000
} elseif {[string compare -nocase $proctype "ps7_cortexa9"] == 0} {
set value [common::get_property CONFIG.$arg $periph]
} else {
set value 0xF9020000
}
} elseif {[string compare -nocase "C_S_AXI_HIGHADDR" $arg] == 0} {
if {[string compare -nocase $proctype "psu_cortexr5"] == 0} {
set value 0xF9001FFF
} elseif {[string compare -nocase $proctype "ps7_cortexa9"] == 0} {
set value [common::get_property CONFIG.$arg $periph]
} else {
set value 0xF9020FFF
}
} elseif {[string compare -nocase "C_DIST_BASEADDR" $arg] == 0} {
if {[string compare -nocase $proctype "psu_cortexr5"] == 0} {
set value 0xF9000000
} elseif {[string compare -nocase $proctype "ps7_cortexa9"] == 0} {
set value 0xf8f01000
} else {
set value 0xF9010000
}
} else {
set value [common::get_property CONFIG.$arg $periph]
}
if {[llength $value] == 0} {
set value 0
}
set value [::hsi::utils::format_addr_string $value $arg]
set arg_name [::hsi::utils::get_ip_param_name $periph $arg]
regsub "S_AXI_" $arg_name "" arg_name
if {[string compare -nocase "HW_VER" $arg] == 0} {
puts $file_handle "#define $arg_name \"$value\""
} else {
puts $file_handle "#define $arg_name $value"
}
}
puts $file_handle ""
}
puts $file_handle "\n/******************************************************************/\n"
close $file_handle
}
#-----------------------------------------------------------------------------
# xdefine_zynq_canonical_xpars - Used to print out canonical defines for a driver.
# Similar to proc xdefine_config_file, except that uses regsub to replace "S_AXI_"
# with "".
#-----------------------------------------------------------------------------
proc xdefine_zynq_canonical_xpars {drv_handle file_name drv_string args} {
# Open include file
set file_handle [::hsi::utils::open_include_file $file_name]
# Get all the peripherals connected to this driver
set periphs [::hsi::utils::get_common_driver_ips $drv_handle]
#Get the processor instance name
set sw_proc_handle [hsi::get_sw_processor]
set hw_proc_handle [hsi::get_cells [common::get_property HW_INSTANCE $sw_proc_handle] ]
set proctype [common::get_property IP_NAME $hw_proc_handle]
#Get proper gic instance for periphs in case of zynqmp
foreach periph $periphs {
if {([string compare -nocase $proctype "ps7_cortexa9"] == 0)||
(([string compare -nocase $proctype "psu_cortexa53"] == 0)&&([string compare -nocase $periph "psu_acpu_gic"] == 0))||
(([string compare -nocase $proctype "psu_cortexr5"] == 0)&&([string compare -nocase $periph "psu_rcpu_gic"] == 0))} {
lappend newperiphs $periph
}
}
set periphs $newperiphs
# Get the names of all the peripherals connected to this driver
foreach periph $periphs {
set peripheral_name [string toupper [common::get_property NAME $periph]]
lappend peripherals $peripheral_name
}
# Get possible canonical names for all the peripherals connected to this
# driver
set device_id 0
foreach periph $periphs {
set canonical_name [string toupper [format "%s_%s" $drv_string $device_id]]
lappend canonicals $canonical_name
# Create a list of IDs of the peripherals whose hardware instance name
# doesn't match the canonical name. These IDs can be used later to
# generate canonical definitions
if { [lsearch $peripherals $canonical_name] < 0 } {
lappend indices $device_id
}
incr device_id
}
set i 0
foreach periph $periphs {
set periph_name [string toupper [common::get_property NAME $periph]]
# Generate canonical definitions only for the peripherals whose
# canonical name is not the same as hardware instance name
if { [lsearch $canonicals $periph_name] < 0 } {
puts $file_handle "/* Canonical definitions for peripheral $periph_name */"
set canonical_name [format "%s_%s" $drv_string [lindex $indices $i]]
foreach arg $args {
set lvalue [::hsi::utils::get_driver_param_name $canonical_name $arg]
# replace S_SXI_ with CPU_. This is a temporary fix. Revist when the
# S_AXI_DIST_BASEADDR is generated by the tools
regsub "S_AXI_" $lvalue "CPU_" lvalue
# The commented out rvalue is the name of the instance-specific constant
# set rvalue [::hsi::utils::get_ip_param_name $periph $arg]
# The rvalue set below is the actual value of the parameter
if {[string compare -nocase "C_S_AXI_BASEADDR" $arg] == 0} {
if {[string compare -nocase $proctype "psu_cortexr5"] == 0} {
set rvalue 0xF9001000
} elseif {[string compare -nocase $proctype "ps7_cortexa9"] == 0} {
set rvalue [common::get_property CONFIG.$arg $periph]
} else {
set rvalue 0xF9020000
}
} elseif {[string compare -nocase "C_S_AXI_HIGHADDR" $arg] == 0} {
if {[string compare -nocase $proctype "psu_cortexr5"] == 0} {
set rvalue 0xF9001FFF
} elseif {[string compare -nocase $proctype "ps7_cortexa9"] == 0} {
set rvalue [common::get_property CONFIG.$arg $periph]
} else {
set rvalue 0xF9020FFF
}
} elseif {[string compare -nocase "C_DIST_BASEADDR" $arg] == 0} {
if {[string compare -nocase $proctype "psu_cortexr5"] == 0} {
set rvalue 0xF9000000
} elseif {[string compare -nocase $proctype "ps7_cortexa9"] == 0} {
set rvalue 0xf8f01000
} else {
set rvalue 0xF9010000
}
} else {
set rvalue [common::get_property CONFIG.$arg $periph]
}
if {[llength $rvalue] == 0} {
set rvalue 0
}
set rvalue [::hsi::utils::format_addr_string $rvalue $arg]
puts $file_handle "#define $lvalue $rvalue"
}
puts $file_handle ""
incr i
}
}
puts $file_handle "\n/******************************************************************/\n"
close $file_handle
}
#
# Create configuration C file as required by Xilinx Zynq drivers
# Similar to proc define_config_file, except that uses regsub
# to replace "S_AXI_" with ""
#
proc xdefine_zynq_config_file {drv_handle file_name drv_string args} {
set args [::hsi::utils::get_exact_arg_list $args]
set filename [file join "src" $file_name]
#file delete $filename
set config_file [open $filename w]
::hsi::utils::write_c_header $config_file "Driver configuration"
puts $config_file "#include \"xparameters.h\""
puts $config_file "#include \"[string tolower $drv_string].h\""
puts $config_file "\n/*"
puts $config_file "* The configuration table for devices"
puts $config_file "*/\n"
puts $config_file [format "%s_Config %s_ConfigTable\[\] =" $drv_string $drv_string]
puts $config_file "\{"
set periphs [::hsi::utils::get_common_driver_ips $drv_handle]
#Get the processor instance name
set sw_proc_handle [hsi::get_sw_processor]
set hw_proc_handle [hsi::get_cells [common::get_property HW_INSTANCE $sw_proc_handle] ]
set proctype [common::get_property IP_NAME $hw_proc_handle]
#Get proper gic instance for periphs in case of zynqmp
foreach periph $periphs {
if {([string compare -nocase $proctype "ps7_cortexa9"] == 0)||
(([string compare -nocase $proctype "psu_cortexa53"] == 0)&&([string compare -nocase $periph "psu_acpu_gic"] == 0))||
(([string compare -nocase $proctype "psu_cortexr5"] == 0)&&([string compare -nocase $periph "psu_rcpu_gic"] == 0))} {
lappend newperiphs $periph
}
}
set periphs $newperiphs
set start_comma ""
foreach periph $periphs {
puts $config_file [format "%s\t\{" $start_comma]
set comma ""
foreach arg $args {
# Check if this is a driver parameter or a peripheral parameter
set value [common::get_property CONFIG.$arg $drv_handle]
if {[llength $value] == 0} {
set local_value [common::get_property CONFIG.$arg $periph ]
# If a parameter isn't found locally (in the current
# peripheral), we will (for some obscure and ancient reason)
# look in peripherals connected via point to point links
if { [string compare -nocase $local_value ""] == 0} {
set p2p_name [::hsi::utils::get_p2p_name $periph $arg]
if { [string compare -nocase $p2p_name ""] == 0} {
set arg_name [::hsi::utils::get_ip_param_name $periph $arg]
regsub "S_AXI_" $arg_name "" arg_name
puts -nonewline $config_file [format "%s\t\t%s" $comma $arg_name]
} else {
regsub "S_AXI_" $p2p_name "" p2p_name
puts -nonewline $config_file [format "%s\t\t%s" $comma $p2p_name]
}
} else {
set arg_name [::hsi::utils::get_ip_param_name $periph $arg]
regsub "S_AXI_" $arg_name "" arg_name
puts -nonewline $config_file [format "%s\t\t%s" $comma $arg_name]
}
} else {
set arg_name [::hsi::utils::get_driver_param_name $drv_string $arg]
regsub "S_AXI_" $arg_name "" arg_name
puts -nonewline $config_file [format "%s\t\t%s" $comma $arg_name]
}
set comma ",\n"
}
puts -nonewline $config_file "\n\t\}"
set start_comma ",\n"
}
puts $config_file "\n\};"
puts $config_file "\n";
close $config_file
}
proc xdefine_gic_params {drvhandle} {
#Get the processor instance name
set sw_proc_handle [hsi::get_sw_processor]
set hw_proc_handle [hsi::get_cells [common::get_property HW_INSTANCE $sw_proc_handle] ]
set proctype [common::get_property IP_NAME $hw_proc_handle]
# Fix me
# Avoid generating fabric interrupts for zynqmp till the issue is fixed
if {([string compare -nocase $proctype "psu_cortexa53"] == 0) || ([string compare -nocase $proctype "psu_cortexr5"] == 0)} {
} else {
set config_inc [::hsi::utils::open_include_file "xparameters.h"]
# Next define interrupt IDs for each connected peripheral
set periphs [::hsi::utils::get_common_driver_ips $drvhandle]
set device_id 0
foreach periph $periphs {
# get the gic mode information
set scugic_mode [common::get_property CONFIG.C_IRQ_F2P_MODE $periph]
# Get the edk based name of peripheral for printing redefines
set edk_periph_name [common::get_property NAME $periph]
# Get ports that are driving the interrupt
set source_ports [::hsi::utils::get_interrupt_sources $periph]
set i 0
lappend source_list
foreach source_port $source_ports {
if {[llength $source_port] ==0 } {
continue
}
set portType [common::get_property TYPE $source_port]
if { [string compare -nocase $portType "INTERRUPT"] } {
continue
}
set external_pin [::hsi::utils::is_external_pin $source_port]
if {$external_pin} {
set source_port_name($i) [common::get_property NAME $source_port]
set source_periph($i) ""
set source_name($i) "system"
} else {
set source_port_name($i) [common::get_property NAME $source_port]
set source_ip [hsi::get_cells -of_objects $source_port]
if { [common::get_property IS_PL $source_ip] == 0 } {
#add only PL IP. Return all PS IPs
continue
}
set source_periph($i) $source_ip
set source_name($i) [common::get_property NAME $source_periph($i)]
}
lappend source_list $source_name($i)
incr i
}
set num_intr_inputs $i
if {$num_intr_inputs == 0} {
close $config_inc
return
}
puts $config_inc "/* Definitions for Fabric interrupts connected to $edk_periph_name */"
for {set i 0} {$i < $num_intr_inputs} {incr i} {
set ip_name $source_name($i)
set port_name $source_port_name($i)
set port_obj [::hsi::get_ports $port_name]
set port_intr_id [::hsi::utils::get_interrupt_id $ip_name $port_name]
if { [string compare -nocase $ip_name "system"] } {
set ip_obj [::hsi::get_cells $ip_name]
if {[llength $ip_obj]} {
set port_obj [::hsi::get_pins -of_objects $ip_obj $port_name]
}
} else {
set port_intr_id [::hsi::utils::get_interrupt_id "" $port_name]
}
if { [llength $port_intr_id] > 1 } {
set j 0
foreach intr_id $port_intr_id {
puts $config_inc [format "#define XPAR_FABRIC_%s_%s_INTR %d" \
[string toupper $ip_name] [string toupper "${port_name}$j"] $intr_id ]
incr j
}
} else {
puts $config_inc [format "#define XPAR_FABRIC_%s_%s_INTR %d" \
[string toupper $ip_name] [string toupper $port_name] $port_intr_id]
}
}
puts $config_inc "\n/******************************************************************/\n"
puts $config_inc "/* Canonical definitions for Fabric interrupts connected to $edk_periph_name */"
for {set i 0} {$i < $num_intr_inputs} {incr i} {
# Skip global (external) ports
if {[string compare -nocase $source_periph($i) ""] != 0} {
set drv [::hsi::get_drivers -filter "HW_INSTANCE==$$source_name($i)"]
if {[llength $source_name($i)] != 0 && [llength $drv] != 0} {
set instance [xfind_instance $drv $source_name($i)]
set drvname [common::get_property NAME $drv]
set drvname [string toupper $drvname]
#
# Treat sources with multiple interrupt ports slightly different
# by including the interrupt port name in the canonical constant
# name
#
if { [lcount $source_list $source_name($i)] > 1} {
set port_name [string toupper $source_port_name($i)]
#
# If there are multiple interrupt ports for axi_ethernet, do not include
# the port name in the canonical name, for the port "INTERRUPT". Other ports
# will have the port name in the canonical name. This is to make sure that
# the canonical name for the port INTERRUPT will remain same irrespective of
# whether the design has a single interrupt port or multiple interrupt ports
#
if {[string compare -nocase $drvname "axiethernet"] == 0} {
if {[string compare -nocase $port_name "INTERRUPT"] == 0} {
set first_part [format "#define XPAR_%s_%s_%s_VEC_ID" "FABRIC" $drvname $instance]
} else {
set first_part [format "#define XPAR_%s_%s_%s_%s_VEC_ID" "FABRIC" $drvname $instance $port_name]
}
} else {
set first_part [format "#define XPAR_%s_%s_%s_%s_VEC_ID" "FABRIC" $drvname $instance $port_name]
}
} else {
set first_part [format "#define XPAR_%s_%s_%s_VEC_ID" "FABRIC" $drvname $instance]
}
set second_part [format "XPAR_%s_%s_%s_INTR" "FABRIC" [string toupper $source_name($i)] [string toupper $source_port_name($i)] ]
if {[string compare -nocase $drvname "generic"] != 0} {
puts $config_inc "$first_part $second_part"
}
}
}
}
incr device_id
}
puts $config_inc "\n/******************************************************************/\n"
close $config_inc
}
}
###################################################################
#
# Get the number of elements in the given list that match the
# given entry. Assume elements are strings.
#
###################################################################
proc lcount {list match_entry} {
set len [llength $list]
set count 0
for {set i 0} {$i < $len} {incr i} {
set entry [lindex $list $i]
if { [string compare -nocase $entry $match_entry] == 0} {
incr count
}
}
return $count
}
###################################################################
#
# Get the HW instance number for a particular device. This will be used to enumerate
# the vector ID defines if more than one interrupt from the core is connected to the
# interrupt controller.
#
###################################################################
proc xfind_instance {drvhandle instname} {
set instlist [::hsi::utils::get_common_driver_ips $drvhandle]
set i 0
foreach inst $instlist {
set name [common::get_property NAME $inst]
if {[string compare -nocase $instname $name] == 0} {
return $i
}
incr i
}
set i 0
return $i
}
###################################################################
#
# Get the type of port, whether it is "local" (from an IP), or
# "global" (from external source).
#
###################################################################
proc xget_port_type {port} {
set periph [hsi::get_cells -of_objects $port]
if {[llength $periph] == 0} {
return "global"
} else {
return "local"
}
}

View file

@ -0,0 +1,43 @@
/* $Id: intc_header.h,v 1.1.4.1 2010/09/17 05:32:46 svemula Exp $ */
/******************************************************************************
*
* Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
#ifndef SCUGIC_HEADER_H /* prevent circular inclusions */
#define SCUGIC_HEADER_H /* by using protection macros */
#include "xil_assert.h"
#include "xil_types.h"
#include "xstatus.h"
int ScuGicSelfTestExample(u16 DeviceId);
int ScuGicInterruptSetup(XScuGic *IntcInstancePtr, u16 DeviceId);
#endif

View file

@ -0,0 +1,152 @@
###############################################################################
#
# Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
###############################################################################
##############################################################################
##
## MODIFICATION HISTORY:
## Ver Who Date Changes
## ----- ---- -------- ----------------------------------------------------
## 1.00a sdm 05/24/11 First release
## 3.0 adk 12/10/13 Updated as per the New Tcl API's
##############################################################################
# Uses $XILINX_EDK/bin/lib/xillib_sw.tcl
# -----------------------------------------------------------------
# Software Project Types (swproj):
# 0 : MemoryTest - Calls basic memorytest routines
# 1 : PeripheralTest - Calls any existing polled_example and/or selftest
# -----------------------------------------------------------------
# -----------------------------------------------------------------
# TCL Procedures:
# -----------------------------------------------------------------
proc gen_include_files {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
if {$swproj == 1} {
set inc_file_lines {xscugic.h xil_exception.h scugic_header.h}
return $inc_file_lines
}
}
proc gen_src_files {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
if {$swproj == 1} {
set inc_file_lines {examples/xscugic_tapp_example.c data/scugic_header.h}
return $inc_file_lines
}
}
proc gen_testfunc_def {swproj mhsinst} {
return ""
}
proc gen_init_code {swproj mhsinst} {
return ""
}
proc gen_testfunc_call {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
set ipname [common::get_property NAME $mhsinst]
set decl " static XScuGic ${ipname};"
set deviceid [::hsi::utils::get_ip_param_name $mhsinst "DEVICE_ID"]
set stdout [common::get_property CONFIG.STDOUT [hsi::get_os]]
if { $stdout == "" || $stdout == "none" } {
set hasStdout 0
} else {
set hasStdout 1
}
set intcvar intc
set testfunc_call ""
if {${hasStdout} == 0} {
append testfunc_call "
{
int Status;
Status = ScuGicSelfTestExample(${deviceid});
Status = ScuGicInterruptSetup(&${intcvar}, ${deviceid});
}"
} else {
append testfunc_call "
{
int Status;
print(\"\\r\\n Running ScuGicSelfTestExample() for ${ipname}...\\r\\n\");
Status = ScuGicSelfTestExample(${deviceid});
if (Status == 0) {
print(\"ScuGicSelfTestExample PASSED\\r\\n\");
}
else {
print(\"ScuGicSelfTestExample FAILED\\r\\n\");
}
}"
append testfunc_call "
{
int Status;
Status = ScuGicInterruptSetup(&${intcvar}, ${deviceid});
if (Status == 0) {
print(\"ScuGic Interrupt Setup PASSED\\r\\n\");
}
else {
print(\"ScuGic Interrupt Setup FAILED\\r\\n\");
}
}"
}
return $testfunc_call
}

View file

@ -0,0 +1,19 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Driver example applications</title>
<link rel="stylesheet" type="text/css" href="../help.css">
</head>
<body bgcolor="#FFFFFF">
<h1> Example Applications for the driver scugic_v2_1 </h1>
<HR>
<ul>
<li>xscugic_low_level_example.c <a href="xscugic_low_level_example.c">(source)</a> </li>
<li>xscugic_example.c <a href="xscugic_example.c">(source)</a> </li>
<li>xscugic_tapp_example.c <a href="xscugic_tapp_example.c">(source)</a> </li>
</ul>
<p><font face="Times New Roman" color="#800000">Copyright <20> 1995-2014 Xilinx, Inc. All rights reserved.</font></p>
</body>
</html>

View file

@ -0,0 +1,313 @@
/* $Id: xscugic_example.c,v 1.1.2.2 2011/03/23 07:46:43 sadanan Exp $ */
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************/
/**
*
* @file xscugic_example.c
*
* This file contains a design example using the Interrupt Controller driver
* (XScuGic) and hardware device. Please reference other device driver examples
* to see more examples of how the intc and interrupts can be used by a software
* application.
*
* @note
*
* None
*
* <pre>
*
* MODIFICATION HISTORY:
* Ver Who Date Changes
* ----- ---- -------- ----------------------------------------------------
* 1.00a drg 01/18/10 First release
* </pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xil_exception.h"
#include "xparameters.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xil_types.h"
#include "xscugic.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID
#define INTC_DEVICE_INT_ID 0x0E
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int ScuGicExample(u16 DeviceId);
int SetUpInterruptSystem(XScuGic *XScuGicInstancePtr);
void DeviceDriverHandler(void *CallbackRef);
/************************** Variable Definitions *****************************/
XScuGic InterruptController; /* Instance of the Interrupt Controller */
static XScuGic_Config *GicConfig; /* The configuration parameters of the
controller */
/*
* Create a shared variable to be used by the main thread of processing and
* the interrupt processing
*/
volatile static int InterruptProcessed = FALSE;
static void AssertPrint(const char8 *FilenamePtr, s32 LineNumber){
xil_printf("ASSERT: File Name: %s ", FilenamePtr);
xil_printf("Line Number: %d\r\n",LineNumber);
}
/*****************************************************************************/
/**
*
* This is the main function for the Interrupt Controller example.
*
* @param None.
*
* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE.
*
* @note None.
*
****************************************************************************/
int main(void)
{
int Status;
/*
* Setup an assert call back to get some info if we assert.
*/
Xil_AssertSetCallback(AssertPrint);
xil_printf("GIC Example Test\r\n");
/*
* Run the Gic example , specify the Device ID generated in xparameters.h
*/
Status = ScuGicExample(INTC_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("GIC Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran GIC Example Test\r\n");
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is an example of how to use the interrupt controller driver
* (XScuGic) and the hardware device. This function is designed to
* work without any hardware devices to cause interrupts. It may not return
* if the interrupt controller is not properly connected to the processor in
* either software or hardware.
*
* This function relies on the fact that the interrupt controller hardware
* has come out of the reset state such that it will allow interrupts to be
* simulated by the software.
*
* @param DeviceId is Device ID of the Interrupt Controller Device,
* typically XPAR_<INTC_instance>_DEVICE_ID value from
* xparameters.h
*
* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE
*
* @note None.
*
******************************************************************************/
int ScuGicExample(u16 DeviceId)
{
int Status;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
GicConfig = XScuGic_LookupConfig(DeviceId);
if (NULL == GicConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(&InterruptController, GicConfig,
GicConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to ensure that the hardware was built
* correctly
*/
Status = XScuGic_SelfTest(&InterruptController);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the Interrupt System
*/
Status = SetUpInterruptSystem(&InterruptController);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect a device driver handler that will be called when an
* interrupt for the device occurs, the device driver handler performs
* the specific interrupt processing for the device
*/
Status = XScuGic_Connect(&InterruptController, INTC_DEVICE_INT_ID,
(Xil_ExceptionHandler)DeviceDriverHandler,
(void *)&InterruptController);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Enable the interrupt for the device and then cause (simulate) an
* interrupt so the handlers will be called
*/
XScuGic_Enable(&InterruptController, INTC_DEVICE_INT_ID);
/*
* Simulate the Interrupt
*/
Status = XScuGic_SoftwareIntr(&InterruptController,
INTC_DEVICE_INT_ID,
XSCUGIC_SPI_CPU0_MASK);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait for the interrupt to be processed, if the interrupt does not
* occur this loop will wait forever
*/
while (1) {
/*
* If the interrupt occurred which is indicated by the global
* variable which is set in the device driver handler, then
* stop waiting
*/
if (InterruptProcessed) {
break;
}
}
return XST_SUCCESS;
}
/******************************************************************************/
/**
*
* This function connects the interrupt handler of the interrupt controller to
* the processor. This function is seperate to allow it to be customized for
* each application. Each processor or RTOS may require unique processing to
* connect the interrupt handler.
*
* @param XScuGicInstancePtr is the instance of the interrupt controller
* that needs to be worked on.
*
* @return None.
*
* @note None.
*
****************************************************************************/
int SetUpInterruptSystem(XScuGic *XScuGicInstancePtr)
{
/*
* Connect the interrupt controller interrupt handler to the hardware
* interrupt handling logic in the ARM processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler) XScuGic_InterruptHandler,
XScuGicInstancePtr);
/*
* Enable interrupts in the ARM
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}
/******************************************************************************/
/**
*
* This function is designed to look like an interrupt handler in a device
* driver. This is typically a 2nd level handler that is called from the
* interrupt controller interrupt handler. This handler would typically
* perform device specific processing such as reading and writing the registers
* of the device to clear the interrupt condition and pass any data to an
* application using the device driver. Many drivers already provide this
* handler and the user is not required to create it.
*
* @param CallbackRef is passed back to the device driver's interrupt
* handler by the XScuGic driver. It was given to the XScuGic
* driver in the XScuGic_Connect() function call. It is typically
* a pointer to the device driver instance variable.
* In this example, we do not care about the callback
* reference, so we passed it a 0 when connecting the handler to
* the XScuGic driver and we make no use of it here.
*
* @return None.
*
* @note None.
*
****************************************************************************/
void DeviceDriverHandler(void *CallbackRef)
{
/*
* Indicate the interrupt has been processed using a shared variable
*/
InterruptProcessed = TRUE;
}

View file

@ -0,0 +1,389 @@
/* $Id: xscugic_low_level_example.c,v 1.1.2.2 2011/03/23 07:46:42 sadanan Exp $ */
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************/
/**
*
* @file xscugic_low_level_example.c
*
* This file contains a design example using the low level driver, interface
* of the Interrupt Controller driver.
*
* This example shows the use of the Interrupt Controller with the ARM
* processor.
*
* @note
*
* none
*
* <pre>
*
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ---------------------------------------------------------
* 1.00a drg 01/30/10 First release
* </pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include <stdio.h>
#include "xparameters.h"
#include "xil_exception.h"
#include "xscugic_hw.h"
#include "xil_printf.h"
#include "xstatus.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define CPU_BASEADDR XPAR_SCUGIC_0_CPU_BASEADDR
#define DIST_BASEADDR XPAR_SCUGIC_0_DIST_BASEADDR
#define GIC_DEVICE_INT_MASK 0x02010003 /* Bit [25:24] Target list filter
Bit [23:16] 16 = Target CPU iface 0
Bit [3:0] identifies the SFI */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int ScuGicLowLevelExample(u32 CpuBaseAddress, u32 DistBaseAddress);
void SetupInterruptSystem();
void LowInterruptHandler(void *CallbackRef);
static void GicDistInit(u32 BaseAddress);
static void GicCPUInit(u32 BaseAddress);
/************************** Variable Definitions *****************************/
/*
* Create a shared variable to be used by the main thread of processing and
* the interrupt processing
*/
volatile static u32 InterruptProcessed = FALSE;
/*****************************************************************************/
/**
*
* This is the main function for the Interrupt Controller Low Level example.
*
* @param None.
*
* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int main(void)
{
int Status;
/*
* Run the low level example of Interrupt Controller, specify the Base
* Address generated in xparameters.h
*/
xil_printf("Low Level GIC Example Test\r\n");
Status = ScuGicLowLevelExample(CPU_BASEADDR, DIST_BASEADDR);
if (Status != XST_SUCCESS) {
xil_printf("Low Level GIC Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran Low Level GIC Example Test\r\n");
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is an example of how to use the interrupt controller driver
* (XScuGic) and the hardware device. This function is designed to
* work without any hardware devices to cause interrupts. It may not return
* if the interrupt controller is not properly connected to the processor in
* either software or hardware.
*
* This function relies on the fact that the interrupt controller hardware
* has come out of the reset state such that it will allow interrupts to be
* simulated by the software.
*
* @param CpuBaseAddress is Base Address of the Interrupt Controller
* Device
*
* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE
*
* @note None.
*
******************************************************************************/
static int ScuGicLowLevelExample(u32 CpuBaseAddress, u32 DistBaseAddress)
{
GicDistInit(DistBaseAddress);
GicCPUInit(CpuBaseAddress);
/*
* This step is processor specific, connect the handler for the
* interrupt controller to the interrupt source for the processor
*/
SetupInterruptSystem();
/*
* Enable the software interrupts only.
*/
XScuGic_WriteReg(DistBaseAddress, XSCUGIC_ENABLE_SET_OFFSET, 0x0000FFFF);
/*
* Cause (simulate) an interrupt so the handler will be called.
* This is done by changing the interrupt source to be software driven,
* then set a bit which simulates an interrupt.
*/
XScuGic_WriteReg(DistBaseAddress, XSCUGIC_SFI_TRIG_OFFSET, GIC_DEVICE_INT_MASK);
/*
* Wait for the interrupt to be processed, if the interrupt does not
* occur this loop will wait forever
*/
while (1)
{
/*
* If the interrupt occurred which is indicated by the global
* variable which is set in the device driver handler, then
* stop waiting
*/
if (InterruptProcessed != 0) {
break;
}
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function connects the interrupt handler of the interrupt controller to
* the processor. This function is separate to allow it to be customized for
* each application. Each processor or RTOS may require unique processing to
* connect the interrupt handler.
*
* @param None.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SetupInterruptSystem(void)
{
/*
* Connect the interrupt controller interrupt handler to the hardware
* interrupt handling logic in the ARM processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
(Xil_ExceptionHandler) LowInterruptHandler,
(void *)CPU_BASEADDR);
/*
* Enable interrupts in the ARM
*/
Xil_ExceptionEnable();
}
/*****************************************************************************/
/**
*
* This function is designed to look like an interrupt handler in a device
* driver. This is typically a 2nd level handler that is called from the
* interrupt controller interrupt handler. This handler would typically
* perform device specific processing such as reading and writing the registers
* of the device to clear the interrupt condition and pass any data to an
* application using the device driver.
*
* @param CallbackRef is passed back to the device driver's interrupt handler
* by the XScuGic driver. It was given to the XScuGic driver in the
* XScuGic_Connect() function call. It is typically a pointer to the
* device driver instance variable if using the Xilinx Level 1 device
* drivers. In this example, we do not care about the callback
* reference, so we passed it a 0 when connecting the handler to the
* XScuGic driver and we make no use of it here.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void LowInterruptHandler(void *CallbackRef)
{
u32 BaseAddress;
u32 IntID;
if (NULL == CallbackRef) {
return;
}
BaseAddress = (u32)CallbackRef;
/*
* Read the int_ack register to identify the interrupt and
* make sure it is valid.
*/
IntID = XScuGic_ReadReg(BaseAddress, XSCUGIC_INT_ACK_OFFSET) &
XSCUGIC_ACK_INTID_MASK;
if(XSCUGIC_MAX_NUM_INTR_INPUTS < IntID){
return;
}
/*
* If the interrupt is shared, do some locking here if there are
* multiple processors.
*/
/*
* Execute the ISR. For this example set the global to 1.
* The software trigger is cleared by the ACK.
*/
InterruptProcessed = 1;
/*
* Write to the EOI register, we are all done here.
* Let this function return, the boot code will restore the stack.
*/
XScuGic_WriteReg(BaseAddress, XSCUGIC_EOI_OFFSET, IntID);
}
static void GicDistInit(u32 BaseAddress)
{
u32 Int_Id;
XScuGic_WriteReg(BaseAddress, XSCUGIC_DIST_EN_OFFSET, 0UL);
/*
* Set the security domains in the int_security registers for non-secure interrupts
* All are secure, so leave at the default. Set to 1 for non-secure interrupts.
*/
/*
* For the Shared Peripheral Interrupts INT_ID[MAX..32], set:
*/
/*
* 1. The trigger mode in the int_config register
*/
for(Int_Id = 32; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id+=16) {
/*
* Each INT_ID uses two bits, or 16 INT_ID per register
* Set them all to be level sensitive, active HIGH.
*/
XScuGic_WriteReg(BaseAddress,
XSCUGIC_INT_CFG_OFFSET + (Int_Id * 4)/16, 0UL);
}
#define DEFAULT_PRIORITY 0xa0a0a0a0UL
#define DEFAULT_TARGET 0x01010101UL
for(Int_Id = 0; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; Int_Id+=4){
/*
* 2. The priority using int the priority_level register
* The priority_level and spi_target registers use one byte
* per INT_ID.
* Write a default value that can be changed elsewhere.
*/
XScuGic_WriteReg(BaseAddress,
XSCUGIC_PRIORITY_OFFSET +((Int_Id *4)/4),
DEFAULT_PRIORITY);
}
for(Int_Id = 32; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id+=4){
/*
* 3. The CPU interface in the spi_target register
*/
XScuGic_WriteReg(BaseAddress,
XSCUGIC_SPI_TARGET_OFFSET +((Int_Id *4)/4),
DEFAULT_TARGET);
}
for(Int_Id = 0; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id+=32){
/*
* 4. Enable the SPI using the enable_set register.
* Leave all disabled for now.
*/
XScuGic_WriteReg(BaseAddress,
XSCUGIC_DISABLE_OFFSET +((Int_Id *4)/32), 0xFFFFFFFFUL);
}
XScuGic_WriteReg(BaseAddress, XSCUGIC_DIST_EN_OFFSET, 0x01UL);
}
static void GicCPUInit(u32 BaseAddress)
{
/*
* Program the priority mask of the CPU using the Priority mask register
*/
XScuGic_WriteReg(BaseAddress, XSCUGIC_CPU_PRIOR_OFFSET, 0xF0);
/*
* If the CPU operates in both security domains, set parameters in the control_s register.
* 1. Set FIQen=1 to use FIQ for secure interrupts,
* 2. Program the AckCtl bit
* 3. Program the SBPR bit to select the binary pointer behavior
* 4. Set EnableS = 1 to enable secure interrupts
* 5. Set EnbleNS = 1 to enable non secure interrupts
*/
/*
* If the CPU operates only in the secure domain, setup the control_s register.
* 1. Set FIQen=1,
* 2. Set EnableS=1, to enable the CPU interface to signal secure interrupts.
*/
XScuGic_WriteReg(BaseAddress, XSCUGIC_CONTROL_OFFSET, 0x01);
}

View file

@ -0,0 +1,242 @@
/* $Id: xintc_tapp_example.c,v 1.1.4.1 2010/09/17 05:32:46 svemula Exp $ */
/******************************************************************************
*
* Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************/
/**
*
* @file xscugic_tapp_example.c
*
* This file contains a self test example using the Interrupt Controller driver
* (XScuGic) and hardware device. Please reference other device driver examples to
* see more examples of how the Intc and interrupts can be used by a software
* application.
*
* The TestApp Gen utility uses this file to perform the self test and setup
* of Intc for interrupts.
*
* @note
*
* None
*
* <pre>
*
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- --------------------------------------------------------
* 1.00a sdm 05/29/11 Created for Test App Integration
* </pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h"
#include "xstatus.h"
#include "xscugic.h"
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place. This definition is not
* included if the example is generated from the TestAppGen test tool.
*/
#ifndef TESTAPP_GEN
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#endif
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int ScuGicSelfTestExample(u16 DeviceId);
int ScuGicInterruptSetup(XScuGic *IntcInstancePtr, u16 DeviceId);
/************************** Variable Definitions *****************************/
static XScuGic IntcInstance; /* Instance of the Interrupt Controller */
/*****************************************************************************/
/**
*
* This is the main function for the Interrupt Controller example. This
* function is not included if the example is generated from the TestAppGen
* test tool.
*
* @param None.
*
* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE.
*
* @note None.
*
******************************************************************************/
#ifndef TESTAPP_GEN
int main(void)
{
int Status;
/*
* Run the Scu Gic Intc example, specify the Device ID generated in
* xparameters.h.
*/
Status = ScuGicSelfTestExample(INTC_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
#endif
/*****************************************************************************/
/**
*
* This function runs a self-test on the driver/device. This is a destructive
* test. This function is an example of how to use the interrupt controller
* driver component (XScuGic) and the hardware device. This function is designed
* to work without any hardware devices to cause interrupts. It may not return
* if the interrupt controller is not properly connected to the processor in
* either software or hardware.
*
* This function relies on the fact that the interrupt controller hardware
* has come out of the reset state such that it will allow interrupts to be
* simulated by the software.
*
* @param DeviceId is device ID of the Interrupt Controller Device,
* typically XPAR_<INTC_instance>_DEVICE_ID value from
* xparameters.h.
*
* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int ScuGicSelfTestExample(u16 DeviceId)
{
int Status;
static XScuGic_Config *GicConfig;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
GicConfig = XScuGic_LookupConfig(DeviceId);
if (NULL == GicConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(&IntcInstance, GicConfig,
GicConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function is used by the TestAppGen generated application to setup
* the interrupt controller.
*
* @param IntcInstancePtr is the reference to the Interrupt Controller
* instance.
* @param DeviceId is device ID of the Interrupt Controller Device,
* typically XPAR_<INTC_instance>_DEVICE_ID value from
* xparameters.h.
*
* @return XST_SUCCESS to indicate success, otherwise XST_FAILURE.
*
* @note None.
*
******************************************************************************/
int ScuGicInterruptSetup(XScuGic *IntcInstancePtr, u16 DeviceId)
{
int Status;
static XScuGic_Config *GicConfig;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
GicConfig = XScuGic_LookupConfig(DeviceId);
if (NULL == GicConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstancePtr, GicConfig,
GicConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
/*
* Connect the interrupt controller interrupt handler to the hardware
* interrupt handling logic in the processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
IntcInstancePtr);
/*
* Enable exceptions.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}

View file

@ -0,0 +1,40 @@
COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a
CC_FLAGS = $(COMPILER_FLAGS)
ECC_FLAGS = $(EXTRA_COMPILER_FLAGS)
RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I./. -I${INCLUDEDIR}
OUTS = *.o
LIBSOURCES:=*.c
INCLUDEFILES:=*.h
OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c)))
libs: banner scugic_libs clean
%.o: %.c
${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $<
banner:
echo "Compiling scugic"
scugic_libs: ${OBJECTS}
$(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS}
.PHONY: include
include: scugic_includes
scugic_includes:
${CP} ${INCLUDEFILES} ${INCLUDEDIR}
clean:
rm -rf ${OBJECTS}

View file

@ -0,0 +1,712 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xscugic.c
*
* Contains required functions for the XScuGic driver for the Interrupt
* Controller. See xscugic.h for a detailed description of the driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- --------------------------------------------------------
* 1.00a drg 01/19/10 First release
* 1.01a sdm 11/09/11 Changes are made in function XScuGic_CfgInitialize. Since
* "Config" entry is now made as pointer in the XScuGic
* structure, necessary changes are made.
* The HandlerTable can now be populated through the low
* level routine XScuGic_RegisterHandler added in this
* release. Hence necessary checks are added not to
* overwrite the HandlerTable entriesin function
* XScuGic_CfgInitialize.
* 1.03a srt 02/27/13 Added APIs
* - XScuGic_SetPriTrigTypeByDistAddr()
* - XScuGic_GetPriTrigTypeByDistAddr()
* Removed Offset calculation macros, defined in _hw.h
* (CR 702687)
* Added support to direct interrupts to the appropriate CPU. Earlier
* interrupts were directed to CPU1 (hard coded). Now depending
* upon the CPU selected by the user (xparameters.h), interrupts
* will be directed to the relevant CPU. This fixes CR 699688.
*
* 1.04a hk 05/04/13 Assigned EffectiveAddr to CpuBaseAddress in
* XScuGic_CfgInitialize. Fix for CR#704400 to remove warnings.
* Moved functions XScuGic_SetPriTrigTypeByDistAddr and
* XScuGic_GetPriTrigTypeByDistAddr to xscugic_hw.c.
* This is fix for CR#705621.
* 1.06a asa 16/11/13 Fix for CR#749178. Assignment for EffectiveAddr
* in function XScuGic_CfgInitialize is removed as it was
* a bug.
* 3.00 kvn 02/13/14 Modified code for MISRA-C:2012 compliance.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
#include "xscugic.h"
#include "xparameters.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Variable Definitions *****************************/
/************************** Function Prototypes ******************************/
static void StubHandler(void *CallBackRef);
/*****************************************************************************/
/**
*
* DistributorInit initializes the distributor of the GIC. The
* initialization entails:
*
* - Write the trigger mode, priority and target CPU
* - All interrupt sources are disabled
* - Enable the distributor
*
* @param InstancePtr is a pointer to the XScuGic instance.
* @param CpuID is the Cpu ID to be initialized.
*
* @return None
*
* @note None.
*
******************************************************************************/
static void DistributorInit(XScuGic *InstancePtr, u32 CpuID)
{
u32 Int_Id;
u32 LocalCpuID = CpuID;
#if USE_AMP==1
#warning "Building GIC for AMP"
/*
* The distrubutor should not be initialized by FreeRTOS in the case of
* AMP -- it is assumed that Linux is the master of this device in that
* case.
*/
return;
#endif
Xil_AssertVoid(InstancePtr != NULL);
XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET, 0U);
/*
* Set the security domains in the int_security registers for
* non-secure interrupts
* All are secure, so leave at the default. Set to 1 for non-secure
* interrupts.
*/
/*
* For the Shared Peripheral Interrupts INT_ID[MAX..32], set:
*/
/*
* 1. The trigger mode in the int_config register
* Only write to the SPI interrupts, so start at 32
*/
for (Int_Id = 32U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; Int_Id=Int_Id+16U) {
/*
* Each INT_ID uses two bits, or 16 INT_ID per register
* Set them all to be level sensitive, active HIGH.
*/
XScuGic_DistWriteReg(InstancePtr,
XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id),
0U);
}
#define DEFAULT_PRIORITY 0xa0a0a0a0U
for (Int_Id = 0U; Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS; Int_Id=Int_Id+4U) {
/*
* 2. The priority using int the priority_level register
* The priority_level and spi_target registers use one byte per
* INT_ID.
* Write a default value that can be changed elsewhere.
*/
XScuGic_DistWriteReg(InstancePtr,
XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id),
DEFAULT_PRIORITY);
}
for (Int_Id = 32U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+4U) {
/*
* 3. The CPU interface in the spi_target register
* Only write to the SPI interrupts, so start at 32
*/
LocalCpuID |= LocalCpuID << 8U;
LocalCpuID |= LocalCpuID << 16U;
XScuGic_DistWriteReg(InstancePtr,
XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id),
LocalCpuID);
}
for (Int_Id = 0U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+32U) {
/*
* 4. Enable the SPI using the enable_set register. Leave all
* disabled for now.
*/
XScuGic_DistWriteReg(InstancePtr,
XSCUGIC_EN_DIS_OFFSET_CALC(XSCUGIC_DISABLE_OFFSET, Int_Id),
0xFFFFFFFFU);
}
XScuGic_DistWriteReg(InstancePtr, XSCUGIC_DIST_EN_OFFSET,
XSCUGIC_EN_INT_MASK);
}
/*****************************************************************************/
/**
*
* CPUInitialize initializes the CPU Interface of the GIC. The initialization entails:
*
* - Set the priority of the CPU
* - Enable the CPU interface
*
* @param InstancePtr is a pointer to the XScuGic instance.
*
* @return None
*
* @note None.
*
******************************************************************************/
static void CPUInitialize(XScuGic *InstancePtr)
{
/*
* Program the priority mask of the CPU using the Priority mask register
*/
XScuGic_CPUWriteReg(InstancePtr, XSCUGIC_CPU_PRIOR_OFFSET, 0xF0U);
/*
* If the CPU operates in both security domains, set parameters in the
* control_s register.
* 1. Set FIQen=1 to use FIQ for secure interrupts,
* 2. Program the AckCtl bit
* 3. Program the SBPR bit to select the binary pointer behavior
* 4. Set EnableS = 1 to enable secure interrupts
* 5. Set EnbleNS = 1 to enable non secure interrupts
*/
/*
* If the CPU operates only in the secure domain, setup the
* control_s register.
* 1. Set FIQen=1,
* 2. Set EnableS=1, to enable the CPU interface to signal secure interrupts.
* Only enable the IRQ output unless secure interrupts are needed.
*/
XScuGic_CPUWriteReg(InstancePtr, XSCUGIC_CONTROL_OFFSET, 0x07U);
}
/*****************************************************************************/
/**
*
* CfgInitialize a specific interrupt controller instance/driver. The
* initialization entails:
*
* - Initialize fields of the XScuGic structure
* - Initial vector table with stub function calls
* - All interrupt sources are disabled
*
* @param InstancePtr is a pointer to the XScuGic instance.
* @param ConfigPtr is a pointer to a config table for the particular
* device this driver is associated with.
* @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
* Config->BaseAddress for this parameters, passing the physical
* address instead.
*
* @return
* - XST_SUCCESS if initialization was successful
*
* @note None.
*
******************************************************************************/
s32 XScuGic_CfgInitialize(XScuGic *InstancePtr,
XScuGic_Config *ConfigPtr,
u32 EffectiveAddr)
{
u32 Int_Id;
u32 Cpu_Id = (u32)XPAR_CPU_ID + (u32)1;
(void) EffectiveAddr;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(ConfigPtr != NULL);
if(InstancePtr->IsReady != XIL_COMPONENT_IS_READY) {
InstancePtr->IsReady = 0;
InstancePtr->Config = ConfigPtr;
for (Int_Id = 0U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id++) {
/*
* Initalize the handler to point to a stub to handle an
* interrupt which has not been connected to a handler. Only
* initialize it if the handler is 0 which means it was not
* initialized statically by the tools/user. Set the callback
* reference to this instance so that unhandled interrupts
* can be tracked.
*/
if ((InstancePtr->Config->HandlerTable[Int_Id].Handler == NULL)) {
InstancePtr->Config->HandlerTable[Int_Id].Handler =
StubHandler;
}
InstancePtr->Config->HandlerTable[Int_Id].CallBackRef =
InstancePtr;
}
DistributorInit(InstancePtr, Cpu_Id);
CPUInitialize(InstancePtr);
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* Makes the connection between the Int_Id of the interrupt source and the
* associated handler that is to run when the interrupt is recognized. The
* argument provided in this call as the Callbackref is used as the argument
* for the handler when it is called.
*
* @param InstancePtr is a pointer to the XScuGic instance.
* @param Int_Id contains the ID of the interrupt source and should be
* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1
* @param Handler to the handler for that interrupt.
* @param CallBackRef is the callback reference, usually the instance
* pointer of the connecting driver.
*
* @return
*
* - XST_SUCCESS if the handler was connected correctly.
*
* @note
*
* WARNING: The handler provided as an argument will overwrite any handler
* that was previously connected.
*
****************************************************************************/
s32 XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id,
Xil_InterruptHandler Handler, void *CallBackRef)
{
/*
* Assert the arguments
*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
Xil_AssertNonvoid(Handler != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* The Int_Id is used as an index into the table to select the proper
* handler
*/
InstancePtr->Config->HandlerTable[Int_Id].Handler = Handler;
InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = CallBackRef;
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* Updates the interrupt table with the Null Handler and NULL arguments at the
* location pointed at by the Int_Id. This effectively disconnects that interrupt
* source from any handler. The interrupt is disabled also.
*
* @param InstancePtr is a pointer to the XScuGic instance to be worked on.
* @param Int_Id contains the ID of the interrupt source and should
* be in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1
*
* @return None.
*
* @note None.
*
****************************************************************************/
void XScuGic_Disconnect(XScuGic *InstancePtr, u32 Int_Id)
{
u32 Mask;
/*
* Assert the arguments
*/
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* The Int_Id is used to create the appropriate mask for the
* desired bit position. Int_Id currently limited to 0 - 31
*/
Mask = 0x00000001U << (Int_Id % 32U);
/*
* Disable the interrupt such that it won't occur while disconnecting
* the handler, only disable the specified interrupt id without modifying
* the other interrupt ids
*/
XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_DISABLE_OFFSET +
((Int_Id / 32U) * 4U), Mask);
/*
* Disconnect the handler and connect a stub, the callback reference
* must be set to this instance to allow unhandled interrupts to be
* tracked
*/
InstancePtr->Config->HandlerTable[Int_Id].Handler = StubHandler;
InstancePtr->Config->HandlerTable[Int_Id].CallBackRef = InstancePtr;
}
/*****************************************************************************/
/**
*
* Enables the interrupt source provided as the argument Int_Id. Any pending
* interrupt condition for the specified Int_Id will occur after this function is
* called.
*
* @param InstancePtr is a pointer to the XScuGic instance.
* @param Int_Id contains the ID of the interrupt source and should be
* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1
*
* @return None.
*
* @note None.
*
****************************************************************************/
void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id)
{
u32 Mask;
/*
* Assert the arguments
*/
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* The Int_Id is used to create the appropriate mask for the
* desired bit position. Int_Id currently limited to 0 - 31
*/
Mask = 0x00000001U << (Int_Id % 32U);
/*
* Enable the selected interrupt source by setting the
* corresponding bit in the Enable Set register.
*/
XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_ENABLE_SET_OFFSET +
((Int_Id / 32U) * 4U), Mask);
}
/*****************************************************************************/
/**
*
* Disables the interrupt source provided as the argument Int_Id such that the
* interrupt controller will not cause interrupts for the specified Int_Id. The
* interrupt controller will continue to hold an interrupt condition for the
* Int_Id, but will not cause an interrupt.
*
* @param InstancePtr is a pointer to the XScuGic instance.
* @param Int_Id contains the ID of the interrupt source and should be
* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1
*
* @return None.
*
* @note None.
*
****************************************************************************/
void XScuGic_Disable(XScuGic *InstancePtr, u32 Int_Id)
{
u32 Mask;
/*
* Assert the arguments
*/
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* The Int_Id is used to create the appropriate mask for the
* desired bit position. Int_Id currently limited to 0 - 31
*/
Mask = 0x00000001U << (Int_Id % 32U);
/*
* Disable the selected interrupt source by setting the
* corresponding bit in the IDR.
*/
XScuGic_DistWriteReg(InstancePtr, (u32)XSCUGIC_DISABLE_OFFSET +
((Int_Id / 32U) * 4U), Mask);
}
/*****************************************************************************/
/**
*
* Allows software to simulate an interrupt in the interrupt controller. This
* function will only be successful when the interrupt controller has been
* started in simulation mode. A simulated interrupt allows the interrupt
* controller to be tested without any device to drive an interrupt input
* signal into it.
*
* @param InstancePtr is a pointer to the XScuGic instance.
* @param Int_Id is the software interrupt ID to simulate an interrupt.
* @param Cpu_Id is the list of CPUs to send the interrupt.
*
* @return
*
* XST_SUCCESS if successful, or XST_FAILURE if the interrupt could not be
* simulated
*
* @note None.
*
******************************************************************************/
s32 XScuGic_SoftwareIntr(XScuGic *InstancePtr, u32 Int_Id, u32 Cpu_Id)
{
u32 Mask;
/*
* Assert the arguments
*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid(Int_Id <= 15U) ;
Xil_AssertNonvoid(Cpu_Id <= 255U) ;
/*
* The Int_Id is used to create the appropriate mask for the
* desired interrupt. Int_Id currently limited to 0 - 15
* Use the target list for the Cpu ID.
*/
Mask = ((Cpu_Id << 16U) | Int_Id) &
(XSCUGIC_SFI_TRIG_CPU_MASK | XSCUGIC_SFI_TRIG_INTID_MASK);
/*
* Write to the Software interrupt trigger register. Use the appropriate
* CPU Int_Id.
*/
XScuGic_DistWriteReg(InstancePtr, XSCUGIC_SFI_TRIG_OFFSET, Mask);
/* Indicate the interrupt was successfully simulated */
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* A stub for the asynchronous callback. The stub is here in case the upper
* layers forget to set the handler.
*
* @param CallBackRef is a pointer to the upper layer callback reference
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void StubHandler(void *CallBackRef) {
/*
* verify that the inputs are valid
*/
Xil_AssertVoid(CallBackRef != NULL);
/*
* Indicate another unhandled interrupt for stats
*/
((XScuGic *)((void *)CallBackRef))->UnhandledInterrupts++;
}
/****************************************************************************/
/**
* Sets the interrupt priority and trigger type for the specificd IRQ source.
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @param Int_Id is the IRQ source number to modify
* @param Priority is the new priority for the IRQ source. 0 is highest
* priority, 0xF8 (248) is lowest. There are 32 priority levels
* supported with a step of 8. Hence the supported priorities are
* 0, 8, 16, 32, 40 ..., 248.
* @param Trigger is the new trigger type for the IRQ source.
* Each bit pair describes the configuration for an INT_ID.
* SFI Read Only b10 always
* PPI Read Only depending on how the PPIs are configured.
* b01 Active HIGH level sensitive
* b11 Rising edge sensitive
* SPI LSB is read only.
* b01 Active HIGH level sensitive
* b11 Rising edge sensitive/
*
* @return None.
*
* @note None.
*
*****************************************************************************/
void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id,
u8 Priority, u8 Trigger)
{
u32 RegValue;
u8 LocalPriority;
LocalPriority = Priority;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
Xil_AssertVoid(Trigger <= (u8)XSCUGIC_INT_CFG_MASK);
Xil_AssertVoid(LocalPriority <= (u8)XSCUGIC_MAX_INTR_PRIO_VAL);
/*
* Determine the register to write to using the Int_Id.
*/
RegValue = XScuGic_DistReadReg(InstancePtr,
XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id));
/*
* The priority bits are Bits 7 to 3 in GIC Priority Register. This
* means the number of priority levels supported are 32 and they are
* in steps of 8. The priorities can be 0, 8, 16, 32, 48, ... etc.
* The lower order 3 bits are masked before putting it in the register.
*/
LocalPriority = LocalPriority & (u8)XSCUGIC_INTR_PRIO_MASK;
/*
* Shift and Mask the correct bits for the priority and trigger in the
* register
*/
RegValue &= ~(XSCUGIC_PRIORITY_MASK << ((Int_Id%4U)*8U));
RegValue |= (u32)LocalPriority << ((Int_Id%4U)*8U);
/*
* Write the value back to the register.
*/
XScuGic_DistWriteReg(InstancePtr, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id),
RegValue);
/*
* Determine the register to write to using the Int_Id.
*/
RegValue = XScuGic_DistReadReg(InstancePtr,
XSCUGIC_INT_CFG_OFFSET_CALC (Int_Id));
/*
* Shift and Mask the correct bits for the priority and trigger in the
* register
*/
RegValue &= ~(XSCUGIC_INT_CFG_MASK << ((Int_Id%16U)*2U));
RegValue |= (u32)Trigger << ((Int_Id%16U)*2U);
/*
* Write the value back to the register.
*/
XScuGic_DistWriteReg(InstancePtr, XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id),
RegValue);
}
/****************************************************************************/
/**
* Gets the interrupt priority and trigger type for the specificd IRQ source.
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @param Int_Id is the IRQ source number to modify
* @param Priority is a pointer to the value of the priority of the IRQ
* source. This is a return value.
* @param Trigger is pointer to the value of the trigger of the IRQ
* source. This is a return value.
*
* @return None.
*
* @note None
*
*****************************************************************************/
void XScuGic_GetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id,
u8 *Priority, u8 *Trigger)
{
u32 RegValue;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
Xil_AssertVoid(Priority != NULL);
Xil_AssertVoid(Trigger != NULL);
/*
* Determine the register to read to using the Int_Id.
*/
RegValue = XScuGic_DistReadReg(InstancePtr,
XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id));
/*
* Shift and Mask the correct bits for the priority and trigger in the
* register
*/
RegValue = RegValue >> ((Int_Id%4U)*8U);
*Priority = (u8)(RegValue & XSCUGIC_PRIORITY_MASK);
/*
* Determine the register to read to using the Int_Id.
*/
RegValue = XScuGic_DistReadReg(InstancePtr,
XSCUGIC_INT_CFG_OFFSET_CALC (Int_Id));
/*
* Shift and Mask the correct bits for the priority and trigger in the
* register
*/
RegValue = RegValue >> ((Int_Id%16U)*2U);
*Trigger = (u8)(RegValue & XSCUGIC_INT_CFG_MASK);
}

View file

@ -0,0 +1,315 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xscugic.h
*
* The generic interrupt controller driver component.
*
* The interrupt controller driver uses the idea of priority for the various
* handlers. Priority is an integer within the range of 1 and 31 inclusive with
* default of 1 being the highest priority interrupt source. The priorities
* of the various sources can be dynamically altered as needed through
* hardware configuration.
*
* The generic interrupt controller supports the following
* features:
*
* - specific individual interrupt enabling/disabling
* - specific individual interrupt acknowledging
* - attaching specific callback function to handle interrupt source
* - assigning desired priority to interrupt source if default is not
* acceptable.
*
* Details about connecting the interrupt handler of the driver are contained
* in the source file specific to interrupt processing, xscugic_intr.c.
*
* This driver is intended to be RTOS and processor independent. It works with
* physical addresses only. Any needs for dynamic memory management, threads
* or thread mutual exclusion, virtual memory, or cache control must be
* satisfied by the layer above this driver.
*
* <b>Interrupt Vector Tables</b>
*
* The device ID of the interrupt controller device is used by the driver as a
* direct index into the configuration data table. The user should populate the
* vector table with handlers and callbacks at run-time using the
* XScuGic_Connect() and XScuGic_Disconnect() functions.
*
* Each vector table entry corresponds to a device that can generate an
* interrupt. Each entry contains an interrupt handler function and an
* argument to be passed to the handler when an interrupt occurs. The
* user must use XScuGic_Connect() when the interrupt handler takes an
* argument other than the base address.
*
* <b>Nested Interrupts Processing</b>
*
* Nested interrupts are not supported by this driver.
*
* NOTE:
* The generic interrupt controller is not a part of the snoop control unit
* as indicated by the prefix "scu" in the name of the driver.
* It is an independent module in APU.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ---------------------------------------------------------
* 1.00a drg 01/19/00 First release
* 1.01a sdm 11/09/11 The XScuGic and XScuGic_Config structures have changed.
* The HandlerTable (of type XScuGic_VectorTableEntry) is
* moved to XScuGic_Config structure from XScuGic structure.
*
* The "Config" entry in XScuGic structure is made as
* pointer for better efficiency.
*
* A new file named as xscugic_hw.c is now added. It is
* to implement low level driver routines without using
* any xscugic instance pointer. They are useful when the
* user wants to use xscugic through device id or
* base address. The driver routines provided are explained
* below.
* XScuGic_DeviceInitialize that takes device id as
* argument and initializes the device (without calling
* XScuGic_CfgInitialize).
* XScuGic_DeviceInterruptHandler that takes device id
* as argument and calls appropriate handlers from the
* HandlerTable.
* XScuGic_RegisterHandler that registers a new handler
* by taking xscugic hardware base address as argument.
* LookupConfigByBaseAddress is used to return the
* corresponding config structure from XScuGic_ConfigTable
* based on the scugic base address passed.
* 1.02a sdm 12/20/11 Removed AckBeforeService from the XScuGic_Config
* structure.
* 1.03a srt 02/27/13 Moved Offset calculation macros from *.c and *_hw.c to
* *_hw.h
* Added APIs
* - XScuGic_SetPriTrigTypeByDistAddr()
* - XScuGic_GetPriTrigTypeByDistAddr()
* (CR 702687)
* Added support to direct interrupts to the appropriate CPU. Earlier
* interrupts were directed to CPU1 (hard coded). Now depending
* upon the CPU selected by the user (xparameters.h), interrupts
* will be directed to the relevant CPU. This fixes CR 699688.
* 1.04a hk 05/04/13 Assigned EffectiveAddr to CpuBaseAddress in
* XScuGic_CfgInitialize. Fix for CR#704400 to remove warnings.
* Moved functions XScuGic_SetPriTrigTypeByDistAddr and
* XScuGic_GetPriTrigTypeByDistAddr to xscugic_hw.c.
* This is fix for CR#705621.
* 1.05a hk 06/26/13 Modified tcl to export external interrupts correctly to
* xparameters.h. Fix for CR's 690505, 708928 & 719359.
* 2.0 adk 12/10/13 Updated as per the New Tcl API's
* 2.1 adk 25/04/14 Fixed the CR:789373 changes are made in the driver tcl file.
* 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
*
* </pre>
*
******************************************************************************/
#ifndef XSCUGIC_H /* prevent circular inclusions */
#define XSCUGIC_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xstatus.h"
#include "xil_io.h"
#include "xscugic_hw.h"
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/* The following data type defines each entry in an interrupt vector table.
* The callback reference is the base address of the interrupting device
* for the low level driver and an instance pointer for the high level driver.
*/
typedef struct
{
Xil_InterruptHandler Handler;
void *CallBackRef;
} XScuGic_VectorTableEntry;
/**
* This typedef contains configuration information for the device.
*/
typedef struct
{
u16 DeviceId; /**< Unique ID of device */
u32 CpuBaseAddress; /**< CPU Interface Register base address */
u32 DistBaseAddress; /**< Distributor Register base address */
XScuGic_VectorTableEntry HandlerTable[XSCUGIC_MAX_NUM_INTR_INPUTS];/**<
Vector table of interrupt handlers */
} XScuGic_Config;
/**
* The XScuGic driver instance data. The user is required to allocate a
* variable of this type for every intc device in the system. A pointer
* to a variable of this type is then passed to the driver API functions.
*/
typedef struct
{
XScuGic_Config *Config; /**< Configuration table entry */
u32 IsReady; /**< Device is initialized and ready */
u32 UnhandledInterrupts; /**< Intc Statistics */
} XScuGic;
/***************** Macros (Inline Functions) Definitions *********************/
/****************************************************************************/
/**
*
* Write the given CPU Interface register
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @param RegOffset is the register offset to be written
* @param Data is the 32-bit value to write to the register
*
* @return None.
*
* @note
* C-style signature:
* void XScuGic_CPUWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data)
*
*****************************************************************************/
#define XScuGic_CPUWriteReg(InstancePtr, RegOffset, Data) \
(XScuGic_WriteReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset), \
((u32)(Data))))
/****************************************************************************/
/**
*
* Read the given CPU Interface register
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @param RegOffset is the register offset to be read
*
* @return The 32-bit value of the register
*
* @note
* C-style signature:
* u32 XScuGic_CPUReadReg(XScuGic *InstancePtr, u32 RegOffset)
*
*****************************************************************************/
#define XScuGic_CPUReadReg(InstancePtr, RegOffset) \
(XScuGic_ReadReg(((InstancePtr)->Config->CpuBaseAddress), (RegOffset)))
/****************************************************************************/
/**
*
* Write the given Distributor Interface register
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @param RegOffset is the register offset to be written
* @param Data is the 32-bit value to write to the register
*
* @return None.
*
* @note
* C-style signature:
* void XScuGic_DistWriteReg(XScuGic *InstancePtr, u32 RegOffset, u32 Data)
*
*****************************************************************************/
#define XScuGic_DistWriteReg(InstancePtr, RegOffset, Data) \
(XScuGic_WriteReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset), \
((u32)(Data))))
/****************************************************************************/
/**
*
* Read the given Distributor Interface register
*
* @param InstancePtr is a pointer to the instance to be worked on.
* @param RegOffset is the register offset to be read
*
* @return The 32-bit value of the register
*
* @note
* C-style signature:
* u32 XScuGic_DistReadReg(XScuGic *InstancePtr, u32 RegOffset)
*
*****************************************************************************/
#define XScuGic_DistReadReg(InstancePtr, RegOffset) \
(XScuGic_ReadReg(((InstancePtr)->Config->DistBaseAddress), (RegOffset)))
/************************** Function Prototypes ******************************/
/*
* Required functions in xscugic.c
*/
s32 XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id,
Xil_InterruptHandler Handler, void *CallBackRef);
void XScuGic_Disconnect(XScuGic *InstancePtr, u32 Int_Id);
void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id);
void XScuGic_Disable(XScuGic *InstancePtr, u32 Int_Id);
s32 XScuGic_CfgInitialize(XScuGic *InstancePtr, XScuGic_Config *ConfigPtr,
u32 EffectiveAddr);
s32 XScuGic_SoftwareIntr(XScuGic *InstancePtr, u32 Int_Id, u32 Cpu_Id);
void XScuGic_GetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id,
u8 *Priority, u8 *Trigger);
void XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id,
u8 Priority, u8 Trigger);
/*
* Initialization functions in xscugic_sinit.c
*/
XScuGic_Config *XScuGic_LookupConfig(u16 DeviceId);
/*
* Interrupt functions in xscugic_intr.c
*/
void XScuGic_InterruptHandler(XScuGic *InstancePtr);
/*
* Self-test functions in xscugic_selftest.c
*/
s32 XScuGic_SelfTest(XScuGic *InstancePtr);
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,93 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xscugic_g.c
*
* This file contains a configuration table that specifies the configuration of
* interrupt controller devices in the system.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a drg 01/19/10 First release
* 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
*
* </pre>
*
* @internal
*
* This configuration table contains entries that are modified at runtime by the
* driver. This table reflects only the hardware configuration of the device.
* This Intc configuration table contains software information in addition to
* hardware configuration.
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xscugic.h"
#include "xparameters.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Prototypes ******************************/
/**
* This table contains configuration information for each GIC device
* in the system. The XScuGic driver must know when to acknowledge the
* interrupt. The entry which specifies this as a bit mask where each bit
* corresponds to a specific interrupt. A bit set indicates to ACK it
* before servicing it. Generally, acknowledge before service is used when
* the interrupt signal is edge-sensitive, and after when the signal is
* level-sensitive.
*
* Refer to the XScuGic_Config data structure in xscugic.h for details on how
* this table should be initialized.
*/
XScuGic_Config XScuGic_ConfigTable[XPAR_XSCUGIC_NUM_INSTANCES] =
{
{
(u16)XPAR_SCUGIC_0_DEVICE_ID, /* Unique ID of device */
(u32)XPAR_SCUGIC_0_CPU_BASEADDR, /* CPU Interface base address */
(u32)XPAR_SCUGIC_0_DIST_BASEADDR /* Distributor base address */
}
};

View file

@ -0,0 +1,567 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xscugic_hw.c
*
* This file contains low-level driver functions that can be used to access the
* device. The user should refer to the hardware device specification for more
* details of the device operation.
* These routines are used when the user does not want to create an instance of
* XScuGic structure but still wants to use the ScuGic device. Hence the
* routines provided here take device id or scugic base address as arguments.
* Separate static versions of DistInit and CPUInit are provided to implement
* the low level driver routines.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -------------------------------------------------------
* 1.01a sdm 07/18/11 First release
* 1.03a srt 02/27/13 Moved Offset calculation macros from *_hw.c (CR
* 702687).
* Added support to direct interrupts to the appropriate CPU.
* Earlier interrupts were directed to CPU1 (hard coded). Now
* depending upon the CPU selected by the user (xparameters.h),
* interrupts will be directed to the relevant CPU.
* This fixes CR 699688.
* 1.04a hk 05/04/13 Fix for CR#705621. Moved functions
* XScuGic_SetPriTrigTypeByDistAddr and
* XScuGic_GetPriTrigTypeByDistAddr here from xscugic.c
* 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
#include "xscugic.h"
#include "xparameters.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static void DistInit(XScuGic_Config *Config, u32 CpuID);
static void CPUInit(XScuGic_Config *Config);
static XScuGic_Config *LookupConfigByBaseAddress(u32 CpuBaseAddress);
/************************** Variable Definitions *****************************/
extern XScuGic_Config XScuGic_ConfigTable[XPAR_XSCUGIC_NUM_INSTANCES];
/*****************************************************************************/
/**
*
* DistInit initializes the distributor of the GIC. The
* initialization entails:
*
* - Write the trigger mode, priority and target CPU
* - All interrupt sources are disabled
* - Enable the distributor
*
* @param InstancePtr is a pointer to the XScuGic instance.
* @param CpuID is the Cpu ID to be initialized.
*
* @return None
*
* @note None.
*
******************************************************************************/
static void DistInit(XScuGic_Config *Config, u32 CpuID)
{
u32 Int_Id;
u32 LocalCpuID = CpuID;
#if USE_AMP==1
#warning "Building GIC for AMP"
/*
* The distrubutor should not be initialized by FreeRTOS in the case of
* AMP -- it is assumed that Linux is the master of this device in that
* case.
*/
return;
#endif
XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET, 0U);
/*
* Set the security domains in the int_security registers for non-secure
* interrupts. All are secure, so leave at the default. Set to 1 for
* non-secure interrupts.
*/
/*
* For the Shared Peripheral Interrupts INT_ID[MAX..32], set:
*/
/*
* 1. The trigger mode in the int_config register
* Only write to the SPI interrupts, so start at 32
*/
for (Int_Id = 32U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+16U) {
/*
* Each INT_ID uses two bits, or 16 INT_ID per register
* Set them all to be level sensitive, active HIGH.
*/
XScuGic_WriteReg(Config->DistBaseAddress,
XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id), 0U);
}
#define DEFAULT_PRIORITY 0xa0a0a0a0U
for (Int_Id = 0U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+4U) {
/*
* 2. The priority using int the priority_level register
* The priority_level and spi_target registers use one byte per
* INT_ID.
* Write a default value that can be changed elsewhere.
*/
XScuGic_WriteReg(Config->DistBaseAddress,
XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id),
DEFAULT_PRIORITY);
}
for (Int_Id = 32U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+4U) {
/*
* 3. The CPU interface in the spi_target register
* Only write to the SPI interrupts, so start at 32
*/
LocalCpuID |= LocalCpuID << 8U;
LocalCpuID |= LocalCpuID << 16U;
XScuGic_WriteReg(Config->DistBaseAddress,
XSCUGIC_SPI_TARGET_OFFSET_CALC(Int_Id), LocalCpuID);
}
for (Int_Id = 0U; Int_Id<XSCUGIC_MAX_NUM_INTR_INPUTS;Int_Id=Int_Id+32U) {
/*
* 4. Enable the SPI using the enable_set register. Leave all disabled
* for now.
*/
XScuGic_WriteReg(Config->DistBaseAddress,
XSCUGIC_EN_DIS_OFFSET_CALC(XSCUGIC_DISABLE_OFFSET,
Int_Id),
0xFFFFFFFFU);
}
XScuGic_WriteReg(Config->DistBaseAddress, XSCUGIC_DIST_EN_OFFSET,
XSCUGIC_EN_INT_MASK);
}
/*****************************************************************************/
/**
*
* CPUInit initializes the CPU Interface of the GIC. The initialization entails:
*
* - Set the priority of the CPU.
* - Enable the CPU interface
*
* @param ConfigPtr is a pointer to a config table for the particular
* device this driver is associated with.
*
* @return None
*
* @note None.
*
******************************************************************************/
static void CPUInit(XScuGic_Config *Config)
{
/*
* Program the priority mask of the CPU using the Priority mask
* register
*/
XScuGic_WriteReg(Config->CpuBaseAddress, XSCUGIC_CPU_PRIOR_OFFSET,
0xF0U);
/*
* If the CPU operates in both security domains, set parameters in the
* control_s register.
* 1. Set FIQen=1 to use FIQ for secure interrupts,
* 2. Program the AckCtl bit
* 3. Program the SBPR bit to select the binary pointer behavior
* 4. Set EnableS = 1 to enable secure interrupts
* 5. Set EnbleNS = 1 to enable non secure interrupts
*/
/*
* If the CPU operates only in the secure domain, setup the
* control_s register.
* 1. Set FIQen=1,
* 2. Set EnableS=1, to enable the CPU interface to signal secure .
* interrupts Only enable the IRQ output unless secure interrupts
* are needed.
*/
XScuGic_WriteReg(Config->CpuBaseAddress, XSCUGIC_CONTROL_OFFSET, 0x07U);
}
/*****************************************************************************/
/**
*
* CfgInitialize a specific interrupt controller instance/driver. The
* initialization entails:
*
* - Initialize fields of the XScuGic structure
* - Initial vector table with stub function calls
* - All interrupt sources are disabled
*
* @param InstancePtr is a pointer to the XScuGic instance to be worked on.
* @param ConfigPtr is a pointer to a config table for the particular device
* this driver is associated with.
* @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 Config->BaseAddress for this parameters,
* passing the physical address instead.
*
* @return
*
* - XST_SUCCESS if initialization was successful
*
* @note
*
* None.
*
******************************************************************************/
s32 XScuGic_DeviceInitialize(u32 DeviceId)
{
XScuGic_Config *Config;
u32 Cpu_Id = (u32)XPAR_CPU_ID + (u32)1;
Config = &XScuGic_ConfigTable[(u32 )DeviceId];
DistInit(Config, Cpu_Id);
CPUInit(Config);
return XST_SUCCESS;
}
/*****************************************************************************/
/**
* This function is the primary interrupt handler for the driver. It must be
* connected to the interrupt source such that it is called when an interrupt of
* the interrupt controller is active. It will resolve which interrupts are
* active and enabled and call the appropriate interrupt handler. It uses
* the Interrupt Type information to determine when to acknowledge the
* interrupt.Highest priority interrupts are serviced first.
*
* This function assumes that an interrupt vector table has been previously
* initialized. It does not verify that entries in the table are valid before
* calling an interrupt handler.
*
* @param DeviceId is the unique identifier for the ScuGic device.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XScuGic_DeviceInterruptHandler(void *DeviceId)
{
u32 InterruptID;
u32 IntIDFull;
XScuGic_VectorTableEntry *TablePtr;
XScuGic_Config *CfgPtr;
CfgPtr = &XScuGic_ConfigTable[(INTPTR )DeviceId];
/*
* Read the int_ack register to identify the highest priority
* interrupt ID and make sure it is valid. Reading Int_Ack will
* clear the interrupt in the GIC.
*/
IntIDFull = XScuGic_ReadReg(CfgPtr->CpuBaseAddress, XSCUGIC_INT_ACK_OFFSET);
InterruptID = IntIDFull & XSCUGIC_ACK_INTID_MASK;
if(XSCUGIC_MAX_NUM_INTR_INPUTS < InterruptID){
goto IntrExit;
}
/*
* If the interrupt is shared, do some locking here if there are
* multiple processors.
*/
/*
* If pre-eption is required:
* Re-enable pre-emption by setting the CPSR I bit for non-secure ,
* interrupts or the F bit for secure interrupts
*/
/*
* If we need to change security domains, issue a SMC instruction here.
*/
/*
* Execute the ISR. Jump into the Interrupt service routine based on
* the IRQSource. A software trigger is cleared by the ACK.
*/
TablePtr = &(CfgPtr->HandlerTable[InterruptID]);
if(TablePtr != NULL) {
TablePtr->Handler(TablePtr->CallBackRef);
}
IntrExit:
/*
* Write to the EOI register, we are all done here.
* Let this function return, the boot code will restore the stack.
*/
XScuGic_WriteReg(CfgPtr->CpuBaseAddress, XSCUGIC_EOI_OFFSET, IntIDFull);
/*
* Return from the interrupt. Change security domains could happen
* here.
*/
}
/*****************************************************************************/
/**
*
* Register a handler function for a specific interrupt ID. The vector table
* of the interrupt controller is updated, overwriting any previous handler.
* The handler function will be called when an interrupt occurs for the given
* interrupt ID.
*
* @param BaseAddress is the CPU Interface Register base address of the
* interrupt controller whose vector table will be modified.
* @param InterruptId is the interrupt ID to be associated with the input
* handler.
* @param Handler is the function pointer that will be added to
* the vector table for the given interrupt ID.
* @param CallBackRef is the argument that will be passed to the new
* handler function when it is called. This is user-specific.
*
* @return None.
*
* @note
*
* Note that this function has no effect if the input base address is invalid.
*
******************************************************************************/
void XScuGic_RegisterHandler(u32 BaseAddress, s32 InterruptID,
Xil_InterruptHandler IntrHandler, void *CallBackRef)
{
XScuGic_Config *CfgPtr;
CfgPtr = LookupConfigByBaseAddress(BaseAddress);
if(CfgPtr != NULL) {
if( IntrHandler != NULL) {
CfgPtr->HandlerTable[InterruptID].Handler = IntrHandler;
}
if( CallBackRef != NULL) {
CfgPtr->HandlerTable[InterruptID].CallBackRef = CallBackRef;
}
}
}
/*****************************************************************************/
/**
*
* Looks up the device configuration based on the CPU interface base address of
* the device. A table contains the configuration info for each device in the
* system.
*
* @param CpuBaseAddress is the CPU Interface Register base address.
*
* @return A pointer to the configuration structure for the specified
* device, or NULL if the device was not found.
*
* @note None.
*
******************************************************************************/
static XScuGic_Config *LookupConfigByBaseAddress(u32 CpuBaseAddress)
{
XScuGic_Config *CfgPtr = NULL;
u32 Index;
for (Index = 0U; Index < XPAR_SCUGIC_NUM_INSTANCES; Index++) {
if (XScuGic_ConfigTable[Index].CpuBaseAddress ==
CpuBaseAddress) {
CfgPtr = &XScuGic_ConfigTable[Index];
break;
}
}
return (XScuGic_Config *)CfgPtr;
}
/****************************************************************************/
/**
* Sets the interrupt priority and trigger type for the specificd IRQ source.
*
* @param BaseAddr is the device base address
* @param Int_Id is the IRQ source number to modify
* @param Priority is the new priority for the IRQ source. 0 is highest
* priority, 0xF8 (248) is lowest. There are 32 priority levels
* supported with a step of 8. Hence the supported priorities are
* 0, 8, 16, 32, 40 ..., 248.
* @param Trigger is the new trigger type for the IRQ source.
* Each bit pair describes the configuration for an INT_ID.
* SFI Read Only b10 always
* PPI Read Only depending on how the PPIs are configured.
* b01 Active HIGH level sensitive
* b11 Rising edge sensitive
* SPI LSB is read only.
* b01 Active HIGH level sensitive
* b11 Rising edge sensitive/
*
* @return None.
*
* @note This API has the similar functionality of XScuGic_SetPriority
* TriggerType() and should be used when there is no InstancePtr.
*
*****************************************************************************/
void XScuGic_SetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id,
u8 Priority, u8 Trigger)
{
u32 RegValue;
u8 LocalPriority = Priority;
Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
Xil_AssertVoid(Trigger <= XSCUGIC_INT_CFG_MASK);
Xil_AssertVoid(LocalPriority <= XSCUGIC_MAX_INTR_PRIO_VAL);
/*
* Determine the register to write to using the Int_Id.
*/
RegValue = XScuGic_ReadReg(DistBaseAddress,
XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id));
/*
* The priority bits are Bits 7 to 3 in GIC Priority Register. This
* means the number of priority levels supported are 32 and they are
* in steps of 8. The priorities can be 0, 8, 16, 32, 48, ... etc.
* The lower order 3 bits are masked before putting it in the register.
*/
LocalPriority = LocalPriority & XSCUGIC_INTR_PRIO_MASK;
/*
* Shift and Mask the correct bits for the priority and trigger in the
* register
*/
RegValue &= ~(XSCUGIC_PRIORITY_MASK << ((Int_Id%4U)*8U));
RegValue |= (u32)LocalPriority << ((Int_Id%4U)*8U);
/*
* Write the value back to the register.
*/
XScuGic_WriteReg(DistBaseAddress, XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id),
RegValue);
/*
* Determine the register to write to using the Int_Id.
*/
RegValue = XScuGic_ReadReg(DistBaseAddress,
XSCUGIC_INT_CFG_OFFSET_CALC (Int_Id));
/*
* Shift and Mask the correct bits for the priority and trigger in the
* register
*/
RegValue &= ~(XSCUGIC_INT_CFG_MASK << ((Int_Id%16U)*2U));
RegValue |= (u32)Trigger << ((Int_Id%16U)*2U);
/*
* Write the value back to the register.
*/
XScuGic_WriteReg(DistBaseAddress, XSCUGIC_INT_CFG_OFFSET_CALC(Int_Id),
RegValue);
}
/****************************************************************************/
/**
* Gets the interrupt priority and trigger type for the specificd IRQ source.
*
* @param BaseAddr is the device base address
* @param Int_Id is the IRQ source number to modify
* @param Priority is a pointer to the value of the priority of the IRQ
* source. This is a return value.
* @param Trigger is pointer to the value of the trigger of the IRQ
* source. This is a return value.
*
* @return None.
*
* @note This API has the similar functionality of XScuGic_GetPriority
* TriggerType() and should be used when there is no InstancePtr.
*
*****************************************************************************/
void XScuGic_GetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id,
u8 *Priority, u8 *Trigger)
{
u32 RegValue;
Xil_AssertVoid(Int_Id < XSCUGIC_MAX_NUM_INTR_INPUTS);
Xil_AssertVoid(Priority != NULL);
Xil_AssertVoid(Trigger != NULL);
/*
* Determine the register to read to using the Int_Id.
*/
RegValue = XScuGic_ReadReg(DistBaseAddress,
XSCUGIC_PRIORITY_OFFSET_CALC(Int_Id));
/*
* Shift and Mask the correct bits for the priority and trigger in the
* register
*/
RegValue = RegValue >> ((Int_Id%4U)*8U);
*Priority = (u8)(RegValue & XSCUGIC_PRIORITY_MASK);
/*
* Determine the register to read to using the Int_Id.
*/
RegValue = XScuGic_ReadReg(DistBaseAddress,
XSCUGIC_INT_CFG_OFFSET_CALC (Int_Id));
/*
* Shift and Mask the correct bits for the priority and trigger in the
* register
*/
RegValue = RegValue >> ((Int_Id%16U)*2U);
*Trigger = (u8)(RegValue & XSCUGIC_INT_CFG_MASK);
}

View file

@ -0,0 +1,637 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xscugic_hw.h
*
* This header file contains identifiers and HW access functions (or
* macros) that can be used to access the device. The user should refer to the
* hardware device specification for more details of the device operation.
* The driver functions/APIs are defined in xscugic.h.
*
* This GIC device has two parts, a distributor and CPU interface(s). Each part
* has separate register definition sections.
*
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------------
* 1.00a drg 01/19/10 First release
* 1.01a sdm 11/09/11 "xil_exception.h" added as include.
* Macros XScuGic_EnableIntr and XScuGic_DisableIntr are
* added to enable or disable interrupts based on
* Distributor Register base address. Normally users use
* XScuGic instance and call XScuGic_Enable or
* XScuGic_Disable to enable/disable interrupts. These
* new macros are provided when user does not want to
* use an instance pointer but still wants to enable or
* disable interrupts.
* Function prototypes for functions (present in newly
* added file xscugic_hw.c) are added.
* 1.03a srt 02/27/13 Moved Offset calculation macros from *_hw.c (CR
* 702687).
* 1.04a hk 05/04/13 Fix for CR#705621. Moved function prototypes
* XScuGic_SetPriTrigTypeByDistAddr and
* XScuGic_GetPriTrigTypeByDistAddr here from xscugic.h
* 3.0 pkp 12/09/14 changed XSCUGIC_MAX_NUM_INTR_INPUTS for
* Zynq Ultrascale Mp
* 3.0 kvn 02/13/14 Modified code for MISRA-C:2012 compliance.
* </pre>
*
******************************************************************************/
#ifndef XSCUGIC_HW_H /* prevent circular inclusions */
#define XSCUGIC_HW_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
#include "xil_io.h"
#include "xil_exception.h"
/************************** Constant Definitions *****************************/
/*
* The maximum number of interrupts supported by the hardware.
*/
#ifdef __ARM_NEON__
#define XSCUGIC_MAX_NUM_INTR_INPUTS 95U /* Maximum number of interrupt defined by Zynq */
#else
#define XSCUGIC_MAX_NUM_INTR_INPUTS 195U /* Maximum number of interrupt defined by Zynq Ultrascale Mp */
#endif
/*
* The maximum priority value that can be used in the GIC.
*/
#define XSCUGIC_MAX_INTR_PRIO_VAL 248U
#define XSCUGIC_INTR_PRIO_MASK 0x000000F8U
/** @name Distributor Interface Register Map
*
* Define the offsets from the base address for all Distributor registers of
* the interrupt controller, some registers may be reserved in the hardware
* device.
* @{
*/
#define XSCUGIC_DIST_EN_OFFSET 0x00000000U /**< Distributor Enable
Register */
#define XSCUGIC_IC_TYPE_OFFSET 0x00000004U /**< Interrupt Controller
Type Register */
#define XSCUGIC_DIST_IDENT_OFFSET 0x00000008U /**< Implementor ID
Register */
#define XSCUGIC_SECURITY_OFFSET 0x00000080U /**< Interrupt Security
Register */
#define XSCUGIC_ENABLE_SET_OFFSET 0x00000100U /**< Enable Set
Register */
#define XSCUGIC_DISABLE_OFFSET 0x00000180U /**< Enable Clear Register */
#define XSCUGIC_PENDING_SET_OFFSET 0x00000200U /**< Pending Set
Register */
#define XSCUGIC_PENDING_CLR_OFFSET 0x00000280U /**< Pending Clear
Register */
#define XSCUGIC_ACTIVE_OFFSET 0x00000300U /**< Active Status Register */
#define XSCUGIC_PRIORITY_OFFSET 0x00000400U /**< Priority Level Register */
#define XSCUGIC_SPI_TARGET_OFFSET 0x00000800U /**< SPI Target
Register 0x800-0x8FB */
#define XSCUGIC_INT_CFG_OFFSET 0x00000C00U /**< Interrupt Configuration
Register 0xC00-0xCFC */
#define XSCUGIC_PPI_STAT_OFFSET 0x00000D00U /**< PPI Status Register */
#define XSCUGIC_SPI_STAT_OFFSET 0x00000D04U /**< SPI Status Register
0xd04-0xd7C */
#define XSCUGIC_AHB_CONFIG_OFFSET 0x00000D80U /**< AHB Configuration
Register */
#define XSCUGIC_SFI_TRIG_OFFSET 0x00000F00U /**< Software Triggered
Interrupt Register */
#define XSCUGIC_PERPHID_OFFSET 0x00000FD0U /**< Peripheral ID Reg */
#define XSCUGIC_PCELLID_OFFSET 0x00000FF0U /**< Pcell ID Register */
/* @} */
/** @name Distributor Enable Register
* Controls if the distributor response to external interrupt inputs.
* @{
*/
#define XSCUGIC_EN_INT_MASK 0x00000001U /**< Interrupt In Enable */
/* @} */
/** @name Interrupt Controller Type Register
* @{
*/
#define XSCUGIC_LSPI_MASK 0x0000F800U /**< Number of Lockable
Shared Peripheral
Interrupts*/
#define XSCUGIC_DOMAIN_MASK 0x00000400U /**< Number os Security domains*/
#define XSCUGIC_CPU_NUM_MASK 0x000000E0U /**< Number of CPU Interfaces */
#define XSCUGIC_NUM_INT_MASK 0x0000001FU /**< Number of Interrupt IDs */
/* @} */
/** @name Implementor ID Register
* Implementor and revision information.
* @{
*/
#define XSCUGIC_REV_MASK 0x00FFF000U /**< Revision Number */
#define XSCUGIC_IMPL_MASK 0x00000FFFU /**< Implementor */
/* @} */
/** @name Interrupt Security Registers
* Each bit controls the security level of an interrupt, either secure or non
* secure. These registers can only be accessed using secure read and write.
* There are registers for each of the CPU interfaces at offset 0x080. A
* register set for the SPI interrupts is available to all CPU interfaces.
* There are up to 32 of these registers staring at location 0x084.
* @{
*/
#define XSCUGIC_INT_NS_MASK 0x00000001U /**< Each bit corresponds to an
INT_ID */
/* @} */
/** @name Enable Set Register
* Each bit controls the enabling of an interrupt, a 0 is disabled, a 1 is
* enabled. Writing a 0 has no effect. Use the ENABLE_CLR register to set a
* bit to 0.
* There are registers for each of the CPU interfaces at offset 0x100. With up
* to 8 registers aliased to the same address. A register set for the SPI
* interrupts is available to all CPU interfaces.
* There are up to 32 of these registers staring at location 0x104.
* @{
*/
#define XSCUGIC_INT_EN_MASK 0x00000001U /**< Each bit corresponds to an
INT_ID */
/* @} */
/** @name Enable Clear Register
* Each bit controls the disabling of an interrupt, a 0 is disabled, a 1 is
* enabled. Writing a 0 has no effect. Writing a 1 disables an interrupt and
* sets the corresponding bit to 0.
* There are registers for each of the CPU interfaces at offset 0x180. With up
* to 8 registers aliased to the same address.
* A register set for the SPI interrupts is available to all CPU interfaces.
* There are up to 32 of these registers staring at location 0x184.
* @{
*/
#define XSCUGIC_INT_CLR_MASK 0x00000001U /**< Each bit corresponds to an
INT_ID */
/* @} */
/** @name Pending Set Register
* Each bit controls the Pending or Active and Pending state of an interrupt, a
* 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1 sets
* an interrupt to the pending state.
* There are registers for each of the CPU interfaces at offset 0x200. With up
* to 8 registers aliased to the same address.
* A register set for the SPI interrupts is available to all CPU interfaces.
* There are up to 32 of these registers staring at location 0x204.
* @{
*/
#define XSCUGIC_PEND_SET_MASK 0x00000001U /**< Each bit corresponds to an
INT_ID */
/* @} */
/** @name Pending Clear Register
* Each bit can clear the Pending or Active and Pending state of an interrupt, a
* 0 is not pending, a 1 is pending. Writing a 0 has no effect. Writing a 1
* clears the pending state of an interrupt.
* There are registers for each of the CPU interfaces at offset 0x280. With up
* to 8 registers aliased to the same address.
* A register set for the SPI interrupts is available to all CPU interfaces.
* There are up to 32 of these registers staring at location 0x284.
* @{
*/
#define XSCUGIC_PEND_CLR_MASK 0x00000001U /**< Each bit corresponds to an
INT_ID */
/* @} */
/** @name Active Status Register
* Each bit provides the Active status of an interrupt, a
* 0 is not Active, a 1 is Active. This is a read only register.
* There are registers for each of the CPU interfaces at offset 0x300. With up
* to 8 registers aliased to each address.
* A register set for the SPI interrupts is available to all CPU interfaces.
* There are up to 32 of these registers staring at location 0x380.
* @{
*/
#define XSCUGIC_ACTIVE_MASK 0x00000001U /**< Each bit corresponds to an
INT_ID */
/* @} */
/** @name Priority Level Register
* Each byte in a Priority Level Register sets the priority level of an
* interrupt. Reading the register provides the priority level of an interrupt.
* There are registers for each of the CPU interfaces at offset 0x400 through
* 0x41C. With up to 8 registers aliased to each address.
* 0 is highest priority, 0xFF is lowest.
* A register set for the SPI interrupts is available to all CPU interfaces.
* There are up to 255 of these registers staring at location 0x420.
* @{
*/
#define XSCUGIC_PRIORITY_MASK 0x000000FFU /**< Each Byte corresponds to an
INT_ID */
#define XSCUGIC_PRIORITY_MAX 0x000000FFU /**< Highest value of a priority
actually the lowest priority*/
/* @} */
/** @name SPI Target Register 0x800-0x8FB
* Each byte references a separate SPI and programs which of the up to 8 CPU
* interfaces are sent a Pending interrupt.
* There are registers for each of the CPU interfaces at offset 0x800 through
* 0x81C. With up to 8 registers aliased to each address.
* A register set for the SPI interrupts is available to all CPU interfaces.
* There are up to 255 of these registers staring at location 0x820.
*
* This driver does not support multiple CPU interfaces. These are included
* for complete documentation.
* @{
*/
#define XSCUGIC_SPI_CPU7_MASK 0x00000080U /**< CPU 7 Mask*/
#define XSCUGIC_SPI_CPU6_MASK 0x00000040U /**< CPU 6 Mask*/
#define XSCUGIC_SPI_CPU5_MASK 0x00000020U /**< CPU 5 Mask*/
#define XSCUGIC_SPI_CPU4_MASK 0x00000010U /**< CPU 4 Mask*/
#define XSCUGIC_SPI_CPU3_MASK 0x00000008U /**< CPU 3 Mask*/
#define XSCUGIC_SPI_CPU2_MASK 0x00000003U /**< CPU 2 Mask*/
#define XSCUGIC_SPI_CPU1_MASK 0x00000002U /**< CPU 1 Mask*/
#define XSCUGIC_SPI_CPU0_MASK 0x00000001U /**< CPU 0 Mask*/
/* @} */
/** @name Interrupt Configuration Register 0xC00-0xCFC
* The interrupt configuration registers program an SFI to be active HIGH level
* sensitive or rising edge sensitive.
* Each bit pair describes the configuration for an INT_ID.
* SFI Read Only b10 always
* PPI Read Only depending on how the PPIs are configured.
* b01 Active HIGH level sensitive
* b11 Rising edge sensitive
* SPI LSB is read only.
* b01 Active HIGH level sensitive
* b11 Rising edge sensitive/
* There are registers for each of the CPU interfaces at offset 0xC00 through
* 0xC04. With up to 8 registers aliased to each address.
* A register set for the SPI interrupts is available to all CPU interfaces.
* There are up to 255 of these registers staring at location 0xC08.
* @{
*/
#define XSCUGIC_INT_CFG_MASK 0x00000003U /**< */
/* @} */
/** @name PPI Status Register
* Enables an external AMBA master to access the status of the PPI inputs.
* A CPU can only read the status of its local PPI signals and cannot read the
* status for other CPUs.
* This register is aliased for each CPU interface.
* @{
*/
#define XSCUGIC_PPI_C15_MASK 0x00008000U /**< PPI Status */
#define XSCUGIC_PPI_C14_MASK 0x00004000U /**< PPI Status */
#define XSCUGIC_PPI_C13_MASK 0x00002000U /**< PPI Status */
#define XSCUGIC_PPI_C12_MASK 0x00001000U /**< PPI Status */
#define XSCUGIC_PPI_C11_MASK 0x00000800U /**< PPI Status */
#define XSCUGIC_PPI_C10_MASK 0x00000400U /**< PPI Status */
#define XSCUGIC_PPI_C09_MASK 0x00000200U /**< PPI Status */
#define XSCUGIC_PPI_C08_MASK 0x00000100U /**< PPI Status */
#define XSCUGIC_PPI_C07_MASK 0x00000080U /**< PPI Status */
#define XSCUGIC_PPI_C06_MASK 0x00000040U /**< PPI Status */
#define XSCUGIC_PPI_C05_MASK 0x00000020U /**< PPI Status */
#define XSCUGIC_PPI_C04_MASK 0x00000010U /**< PPI Status */
#define XSCUGIC_PPI_C03_MASK 0x00000008U /**< PPI Status */
#define XSCUGIC_PPI_C02_MASK 0x00000004U /**< PPI Status */
#define XSCUGIC_PPI_C01_MASK 0x00000002U /**< PPI Status */
#define XSCUGIC_PPI_C00_MASK 0x00000001U /**< PPI Status */
/* @} */
/** @name SPI Status Register 0xd04-0xd7C
* Enables an external AMBA master to access the status of the SPI inputs.
* There are up to 63 registers if the maximum number of SPI inputs are
* configured.
* @{
*/
#define XSCUGIC_SPI_N_MASK 0x00000001U /**< Each bit corresponds to an SPI
input */
/* @} */
/** @name AHB Configuration Register
* Provides the status of the CFGBIGEND input signal and allows the endianess
* of the GIC to be set.
* @{
*/
#define XSCUGIC_AHB_END_MASK 0x00000004U /**< 0-GIC uses little Endian,
1-GIC uses Big Endian */
#define XSCUGIC_AHB_ENDOVR_MASK 0x00000002U /**< 0-Uses CFGBIGEND control,
1-use the AHB_END bit */
#define XSCUGIC_AHB_TIE_OFF_MASK 0x00000001U /**< State of CFGBIGEND */
/* @} */
/** @name Software Triggered Interrupt Register
* Controls issueing of software interrupts.
* @{
*/
#define XSCUGIC_SFI_SELFTRIG_MASK 0x02010000U
#define XSCUGIC_SFI_TRIG_TRGFILT_MASK 0x03000000U /**< Target List filter
b00-Use the target List
b01-All CPUs except requester
b10-To Requester
b11-reserved */
#define XSCUGIC_SFI_TRIG_CPU_MASK 0x00FF0000U /**< CPU Target list */
#define XSCUGIC_SFI_TRIG_SATT_MASK 0x00008000U /**< 0= Use a secure interrupt */
#define XSCUGIC_SFI_TRIG_INTID_MASK 0x0000000FU /**< Set to the INTID
signaled to the CPU*/
/* @} */
/** @name CPU Interface Register Map
*
* Define the offsets from the base address for all CPU registers of the
* interrupt controller, some registers may be reserved in the hardware device.
* @{
*/
#define XSCUGIC_CONTROL_OFFSET 0x00000000U /**< CPU Interface Control
Register */
#define XSCUGIC_CPU_PRIOR_OFFSET 0x00000004U /**< Priority Mask Reg */
#define XSCUGIC_BIN_PT_OFFSET 0x00000008U /**< Binary Point Register */
#define XSCUGIC_INT_ACK_OFFSET 0x0000000CU /**< Interrupt ACK Reg */
#define XSCUGIC_EOI_OFFSET 0x00000010U /**< End of Interrupt Reg */
#define XSCUGIC_RUN_PRIOR_OFFSET 0x00000014U /**< Running Priority Reg */
#define XSCUGIC_HI_PEND_OFFSET 0x00000018U /**< Highest Pending Interrupt
Register */
#define XSCUGIC_ALIAS_BIN_PT_OFFSET 0x0000001CU /**< Aliased non-Secure
Binary Point Register */
/**< 0x00000020 to 0x00000FBC are reserved and should not be read or written
* to. */
/* @} */
/** @name Control Register
* CPU Interface Control register definitions
* All bits are defined here although some are not available in the non-secure
* mode.
* @{
*/
#define XSCUGIC_CNTR_SBPR_MASK 0x00000010U /**< Secure Binary Pointer,
0=separate registers,
1=both use bin_pt_s */
#define XSCUGIC_CNTR_FIQEN_MASK 0x00000008U /**< Use nFIQ_C for secure
interrupts,
0= use IRQ for both,
1=Use FIQ for secure, IRQ for non*/
#define XSCUGIC_CNTR_ACKCTL_MASK 0x00000004U /**< Ack control for secure or non secure */
#define XSCUGIC_CNTR_EN_NS_MASK 0x00000002U /**< Non Secure enable */
#define XSCUGIC_CNTR_EN_S_MASK 0x00000001U /**< Secure enable, 0=Disabled, 1=Enabled */
/* @} */
/** @name Priority Mask Register
* Priority Mask register definitions
* The CPU interface does not send interrupt if the level of the interrupt is
* lower than the level of the register.
* @{
*/
/*#define XSCUGIC_PRIORITY_MASK 0x000000FFU*/ /**< All interrupts */
/* @} */
/** @name Binary Point Register
* Binary Point register definitions
* @{
*/
#define XSCUGIC_BIN_PT_MASK 0x00000007U /**< Binary point mask value
Value Secure Non-secure
b000 0xFE 0xFF
b001 0xFC 0xFE
b010 0xF8 0xFC
b011 0xF0 0xF8
b100 0xE0 0xF0
b101 0xC0 0xE0
b110 0x80 0xC0
b111 0x00 0x80
*/
/*@}*/
/** @name Interrupt Acknowledge Register
* Interrupt Acknowledge register definitions
* Identifies the current Pending interrupt, and the CPU ID for software
* interrupts.
*/
#define XSCUGIC_ACK_INTID_MASK 0x000003FFU /**< Interrupt ID */
#define XSCUGIC_CPUID_MASK 0x00000C00U /**< CPU ID */
/* @} */
/** @name End of Interrupt Register
* End of Interrupt register definitions
* Allows the CPU to signal the GIC when it completes an interrupt service
* routine.
*/
#define XSCUGIC_EOI_INTID_MASK 0x000003FFU /**< Interrupt ID */
/* @} */
/** @name Running Priority Register
* Running Priority register definitions
* Identifies the interrupt priority level of the highest priority active
* interrupt.
*/
#define XSCUGIC_RUN_PRIORITY_MASK 0x000000FFU /**< Interrupt Priority */
/* @} */
/*
* Highest Pending Interrupt register definitions
* Identifies the interrupt priority of the highest priority pending interupt
*/
#define XSCUGIC_PEND_INTID_MASK 0x000003FFU /**< Pending Interrupt ID */
/*#define XSCUGIC_CPUID_MASK 0x00000C00U */ /**< CPU ID */
/* @} */
/***************** Macros (Inline Functions) Definitions *********************/
/****************************************************************************/
/**
*
* Read the Interrupt Configuration Register offset for an interrupt id.
*
* @param InterruptID is the interrupt number.
*
* @return The 32-bit value of the offset
*
* @note
*
*****************************************************************************/
#define XSCUGIC_INT_CFG_OFFSET_CALC(InterruptID) \
((u32)XSCUGIC_INT_CFG_OFFSET + (((InterruptID)/16U) * 4U))
/****************************************************************************/
/**
*
* Read the Interrupt Priority Register offset for an interrupt id.
*
* @param InterruptID is the interrupt number.
*
* @return The 32-bit value of the offset
*
* @note
*
*****************************************************************************/
#define XSCUGIC_PRIORITY_OFFSET_CALC(InterruptID) \
((u32)XSCUGIC_PRIORITY_OFFSET + (((InterruptID)/4U) * 4U))
/****************************************************************************/
/**
*
* Read the SPI Target Register offset for an interrupt id.
*
* @param InterruptID is the interrupt number.
*
* @return The 32-bit value of the offset
*
* @note
*
*****************************************************************************/
#define XSCUGIC_SPI_TARGET_OFFSET_CALC(InterruptID) \
((u32)XSCUGIC_SPI_TARGET_OFFSET + (((InterruptID)/4U) * 4U))
/****************************************************************************/
/**
*
* Read the Interrupt Clear-Enable Register offset for an interrupt ID
*
* @param Register is the register offset for the clear/enable bank.
* @param InterruptID is the interrupt number.
*
* @return The 32-bit value of the offset
*
* @note
*
*****************************************************************************/
#define XSCUGIC_EN_DIS_OFFSET_CALC(Register, InterruptID) \
((Register) + (((InterruptID)/32U) * 4U))
/****************************************************************************/
/**
*
* Read the given Intc register.
*
* @param BaseAddress is the base address of the device.
* @param RegOffset is the register offset to be read
*
* @return The 32-bit value of the register
*
* @note
* C-style signature:
* u32 XScuGic_ReadReg(u32 BaseAddress, u32 RegOffset)
*
*****************************************************************************/
#define XScuGic_ReadReg(BaseAddress, RegOffset) \
(Xil_In32((BaseAddress) + (RegOffset)))
/****************************************************************************/
/**
*
* Write the given Intc register.
*
* @param BaseAddress is the base address of the device.
* @param RegOffset is the register offset to be written
* @param Data is the 32-bit value to write to the register
*
* @return None.
*
* @note
* C-style signature:
* void XScuGic_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data)
*
*****************************************************************************/
#define XScuGic_WriteReg(BaseAddress, RegOffset, Data) \
(Xil_Out32(((BaseAddress) + (RegOffset)), ((u32)(Data))))
/****************************************************************************/
/**
*
* Enable specific interrupt(s) in the interrupt controller.
*
* @param DistBaseAddress is the Distributor Register base address of the
* device
* @param Int_Id is the ID of the interrupt source and should be in the
* range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1
*
* @return None.
*
* @note C-style signature:
* void XScuGic_EnableIntr(u32 DistBaseAddress, u32 Int_Id)
*
*****************************************************************************/
#define XScuGic_EnableIntr(DistBaseAddress, Int_Id) \
XScuGic_WriteReg((DistBaseAddress), \
XSCUGIC_ENABLE_SET_OFFSET + (((Int_Id) / 32U) * 4U), \
(0x00000001U << ((Int_Id) % 32U)))
/****************************************************************************/
/**
*
* Disable specific interrupt(s) in the interrupt controller.
*
* @param DistBaseAddress is the Distributor Register base address of the
* device
* @param Int_Id is the ID of the interrupt source and should be in the
* range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1
*
*
* @return None.
*
* @note C-style signature:
* void XScuGic_DisableIntr(u32 DistBaseAddress, u32 Int_Id)
*
*****************************************************************************/
#define XScuGic_DisableIntr(DistBaseAddress, Int_Id) \
XScuGic_WriteReg((DistBaseAddress), \
XSCUGIC_DISABLE_OFFSET + (((Int_Id) / 32U) * 4U), \
(0x00000001U << ((Int_Id) % 32U)))
/************************** Function Prototypes ******************************/
void XScuGic_DeviceInterruptHandler(void *DeviceId);
s32 XScuGic_DeviceInitialize(u32 DeviceId);
void XScuGic_RegisterHandler(u32 BaseAddress, s32 InterruptID,
Xil_InterruptHandler Handler, void *CallBackRef);
void XScuGic_SetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id,
u8 Priority, u8 Trigger);
void XScuGic_GetPriTrigTypeByDistAddr(u32 DistBaseAddress, u32 Int_Id,
u8 *Priority, u8 *Trigger);
/************************** Variable Definitions *****************************/
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,170 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xscugic_intr.c
*
* This file contains the interrupt processing for the driver for the Xilinx
* Interrupt Controller. The interrupt processing is partitioned separately such
* that users are not required to use the provided interrupt processing. This
* file requires other files of the driver to be linked in also.
*
* The interrupt handler, XScuGic_InterruptHandler, uses an input argument which
* is an instance pointer to an interrupt controller driver such that multiple
* interrupt controllers can be supported. This handler requires the calling
* function to pass it the appropriate argument, so another level of indirection
* may be required.
*
* The interrupt processing may be used by connecting the interrupt handler to
* the interrupt system. The handler does not save and restore the processor
* context but only handles the processing of the Interrupt Controller. The user
* is encouraged to supply their own interrupt handler when performance tuning is
* deemed necessary.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ---------------------------------------------------------
* 1.00a drg 01/19/10 First release
* 1.01a sdm 11/09/11 XScuGic_InterruptHandler has changed correspondingly
* since the HandlerTable has now moved to XScuGic_Config.
* 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
*
* </pre>
*
* @internal
*
* This driver assumes that the context of the processor has been saved prior to
* the calling of the Interrupt Controller interrupt handler and then restored
* after the handler returns. This requires either the running RTOS to save the
* state of the machine or that a wrapper be used as the destination of the
* interrupt vector to save the state of the processor and restore the state
* after the interrupt handler returns.
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
#include "xscugic.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
/*****************************************************************************/
/**
* This function is the primary interrupt handler for the driver. It must be
* connected to the interrupt source such that it is called when an interrupt of
* the interrupt controller is active. It will resolve which interrupts are
* active and enabled and call the appropriate interrupt handler. It uses
* the Interrupt Type information to determine when to acknowledge the interrupt.
* Highest priority interrupts are serviced first.
*
* This function assumes that an interrupt vector table has been previously
* initialized. It does not verify that entries in the table are valid before
* calling an interrupt handler.
*
*
* @param InstancePtr is a pointer to the XScuGic instance.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XScuGic_InterruptHandler(XScuGic *InstancePtr)
{
u32 InterruptID;
u32 IntIDFull;
XScuGic_VectorTableEntry *TablePtr;
/* Assert that the pointer to the instance is valid
*/
Xil_AssertVoid(InstancePtr != NULL);
/*
* Read the int_ack register to identify the highest priority interrupt ID
* and make sure it is valid. Reading Int_Ack will clear the interrupt
* in the GIC.
*/
IntIDFull = XScuGic_CPUReadReg(InstancePtr, XSCUGIC_INT_ACK_OFFSET);
InterruptID = IntIDFull & XSCUGIC_ACK_INTID_MASK;
if(XSCUGIC_MAX_NUM_INTR_INPUTS < InterruptID){
goto IntrExit;
}
/*
* If the interrupt is shared, do some locking here if there are multiple
* processors.
*/
/*
* If pre-eption is required:
* Re-enable pre-emption by setting the CPSR I bit for non-secure ,
* interrupts or the F bit for secure interrupts
*/
/*
* If we need to change security domains, issue a SMC instruction here.
*/
/*
* Execute the ISR. Jump into the Interrupt service routine based on the
* IRQSource. A software trigger is cleared by the ACK.
*/
TablePtr = &(InstancePtr->Config->HandlerTable[InterruptID]);
if(TablePtr != NULL) {
TablePtr->Handler(TablePtr->CallBackRef);
}
IntrExit:
/*
* Write to the EOI register, we are all done here.
* Let this function return, the boot code will restore the stack.
*/
XScuGic_CPUWriteReg(InstancePtr, XSCUGIC_EOI_OFFSET, IntIDFull);
/*
* Return from the interrupt. Change security domains could happen here.
*/
}

View file

@ -0,0 +1,112 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xscugic_selftest.c
*
* Contains diagnostic self-test functions for the XScuGic driver.
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00a drg 01/19/10 First release
* 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
#include "xscugic.h"
/************************** Constant Definitions *****************************/
#define XSCUGIC_PCELL_ID 0xB105F00DU
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
/*****************************************************************************/
/**
*
* Run a self-test on the driver/device. This test reads the ID registers and
* compares them.
*
* @param InstancePtr is a pointer to the XScuGic instance.
*
* @return
*
* - XST_SUCCESS if self-test is successful.
* - XST_FAILURE if the self-test is not successful.
*
* @note None.
*
******************************************************************************/
s32 XScuGic_SelfTest(XScuGic *InstancePtr)
{
u32 RegValue1 = 0U;
u32 Index;
s32 Status;
/*
* Assert the arguments
*/
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Read the ID registers.
*/
for(Index=0U; Index<=3U; Index++) {
RegValue1 |= XScuGic_DistReadReg(InstancePtr,
((u32)XSCUGIC_PCELLID_OFFSET + (Index * 4U))) << (Index * 8U);
}
if(XSCUGIC_PCELL_ID != RegValue1){
Status = XST_FAILURE;
} else {
Status = XST_SUCCESS;
}
return Status;
}

View file

@ -0,0 +1,100 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xscugic_sinit.c
*
* Contains static init functions for the XScuGic driver for the Interrupt
* Controller. See xscugic.h for a detailed description of the driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- --------------------------------------------------------
* 1.00a drg 01/19/10 First release
* 3.00 kvn 02/13/15 Modified code for MISRA-C:2012 compliance.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
#include "xparameters.h"
#include "xscugic.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Variable Definitions *****************************/
extern XScuGic_Config XScuGic_ConfigTable[XPAR_SCUGIC_NUM_INSTANCES];
/************************** Function Prototypes ******************************/
/*****************************************************************************/
/**
*
* Looks up the device configuration based on the unique device ID. A table
* contains the configuration info for each device in the system.
*
* @param DeviceId is the unique identifier for a device.
*
* @return A pointer to the XScuGic configuration structure for the
* specified device, or NULL if the device was not found.
*
* @note None.
*
******************************************************************************/
XScuGic_Config *XScuGic_LookupConfig(u16 DeviceId)
{
XScuGic_Config *CfgPtr = NULL;
u32 Index;
for (Index=0U; Index < (u32)XPAR_SCUGIC_NUM_INSTANCES; Index++) {
if (XScuGic_ConfigTable[Index].DeviceId == DeviceId) {
CfgPtr = &XScuGic_ConfigTable[Index];
break;
}
}
return (XScuGic_Config *)CfgPtr;
}