mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge remote-tracking branch 'upstream/main' into fetch_buffer
This commit is contained in:
commit
dfe7c11af4
@ -414,6 +414,7 @@ if (args.ccov): # only run RV64GC tests on Questa in code coverage mode
|
|||||||
elif (args.fcov): # only run RV64GC tests on Questa in lockstep in functional coverage mode
|
elif (args.fcov): # only run RV64GC tests on Questa in lockstep in functional coverage mode
|
||||||
addLockstepTestsByDir(WALLY+"/addins/cvw-arch-verif/tests/rv32/", "rv32gc", coveragesim, 1)
|
addLockstepTestsByDir(WALLY+"/addins/cvw-arch-verif/tests/rv32/", "rv32gc", coveragesim, 1)
|
||||||
addLockstepTestsByDir(WALLY+"/addins/cvw-arch-verif/tests/rv64/", "rv64gc", coveragesim, 1)
|
addLockstepTestsByDir(WALLY+"/addins/cvw-arch-verif/tests/rv64/", "rv64gc", coveragesim, 1)
|
||||||
|
# addLockstepTestsByDir(WALLY+"/tests/riscof/work/wally-riscv-arch-test/rv64i_m/privilege/src/", "rv64gc", coveragesim, 0)
|
||||||
elif (args.fcovrvvi): # only run RV64GC tests on Questa in rvvi coverage mode
|
elif (args.fcovrvvi): # only run RV64GC tests on Questa in rvvi coverage mode
|
||||||
addTests(tests64gc_nofp, coveragesim)
|
addTests(tests64gc_nofp, coveragesim)
|
||||||
if (args.fp):
|
if (args.fp):
|
||||||
|
@ -3,7 +3,7 @@ lief>=0.14.1
|
|||||||
Markdown>=3.6
|
Markdown>=3.6
|
||||||
matplotlib>=3.9.0
|
matplotlib>=3.9.0
|
||||||
PyYAML>=5.2
|
PyYAML>=5.2
|
||||||
riscv-isac @ git+https://github.com/riscv-software-src/riscv-isac@dev
|
riscv-isac @ git+https://github.com/riscv-non-isa/riscv-arch-test/#subdirectory=riscv-isac
|
||||||
riscof @ git+https://github.com/riscv/riscof.git
|
riscof @ git+https://github.com/riscv/riscof.git
|
||||||
riscv-config>=3.18.3
|
riscv-config>=3.18.3
|
||||||
riscv-isac>=0.18.0
|
riscv-isac>=0.18.0
|
||||||
|
5
bin/wsim
5
bin/wsim
@ -142,6 +142,11 @@ for d in ["logs", "wkdir", "cov", "ucdb", "fcov", "fcov_ucdb", "fcovrvvi", "fcov
|
|||||||
|
|
||||||
cd = "cd $WALLY/sim/" +args.sim
|
cd = "cd $WALLY/sim/" +args.sim
|
||||||
|
|
||||||
|
# check for unsupported sims
|
||||||
|
if (args.tb == "testbench_fp" and args.sim != "questa"):
|
||||||
|
print("Error: testbench_fp presently only supported by Questa, not VCS or Verilator, because of a touchy testbench")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
# per-simulator launch
|
# per-simulator launch
|
||||||
if (args.sim == "questa"):
|
if (args.sim == "questa"):
|
||||||
if (args.gui) and (args.tb == "testbench"):
|
if (args.gui) and (args.tb == "testbench"):
|
||||||
|
@ -8,5 +8,6 @@
|
|||||||
`include "RV32I_coverage.svh"
|
`include "RV32I_coverage.svh"
|
||||||
`include "RV32M_coverage.svh"
|
`include "RV32M_coverage.svh"
|
||||||
`include "RV32F_coverage.svh"
|
`include "RV32F_coverage.svh"
|
||||||
|
`include "RV32Zfh_coverage.svh"
|
||||||
`include "RV32Zicond_coverage.svh"
|
`include "RV32Zicond_coverage.svh"
|
||||||
`include "RV32Zca_coverage.svh"
|
`include "RV32Zca_coverage.svh"
|
||||||
|
@ -8,5 +8,11 @@
|
|||||||
`include "RV64I_coverage.svh"
|
`include "RV64I_coverage.svh"
|
||||||
`include "RV64M_coverage.svh"
|
`include "RV64M_coverage.svh"
|
||||||
`include "RV64F_coverage.svh"
|
`include "RV64F_coverage.svh"
|
||||||
|
`include "RV64Zfh_coverage.svh"
|
||||||
|
// `include "RV64VM_coverage.svh"
|
||||||
|
// `include "RV64VM_PMP_coverage.svh"
|
||||||
|
// `include "RV64CBO_VM_coverage.svh"
|
||||||
|
// `include "RV64CBO_PMP_coverage.svh"
|
||||||
|
// `include "RV64Zicbom_coverage.svh"
|
||||||
`include "RV64Zicond_coverage.svh"
|
`include "RV64Zicond_coverage.svh"
|
||||||
`include "RV64Zca_coverage.svh"
|
`include "RV64Zca_coverage.svh"
|
||||||
|
@ -17,31 +17,3 @@ CORE-V Wally is functionally tested in the following ways. Each test is run in
|
|||||||
| Code Coverage | 5.11.10 | | rv64gc | TBD | TBD | TBD |
|
| Code Coverage | 5.11.10 | | rv64gc | TBD | TBD | TBD |
|
||||||
| Functional Coverage | 5.11.11 | | rv64gc | TBD | TBD | TBD |
|
| Functional Coverage | 5.11.11 | | rv64gc | TBD | TBD | TBD |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
* Run [RISC-V Architecture Compatibility Tests](https://github.com/riscv-non-isa/riscv-arch-test) in lock-step against the ImperasDV reference model.
|
|
||||||
* Run custom tests to cover virtual memory, PMP, privileged unit, and peripherals in lock step against ImperasDV.
|
|
||||||
* ***pending: Run random tests generated by risc-dv
|
|
||||||
* Run CoreMark and Embench benchmarks.
|
|
||||||
* Run performance validation against reference models for the branch predictor and caches.
|
|
||||||
* Run the TestFloat suite against all precisions of all operations for the FPU unit.
|
|
||||||
* *** 83.5% coverage of statements, branches, expressions, and FSM states and transitions
|
|
||||||
* Boot Buildroot Linux in lock-step against ImperasDV.
|
|
||||||
* Boot Buildroot Linux on an FPGA and run programs.
|
|
||||||
|
|
||||||
# Running Tests
|
|
||||||
|
|
||||||
#
|
|
||||||
|
|
||||||
# Detailed Test Plans
|
|
||||||
|
|
||||||
The test plans for specific units are lined below:
|
|
||||||
|
|
||||||
* Privileged Unit
|
|
||||||
* Memory Management Unit
|
|
||||||
* Peripherals
|
|
||||||
* Branch Predictor Performance Validation
|
|
||||||
* Cache Performance Validation
|
|
||||||
|
|
||||||
Wally is described in an upcoming textbook, *RISC-V System-on-Chip Design*, by Harris, Stine, Thompson, and Harris.
|
|
@ -1,30 +0,0 @@
|
|||||||
# core-v-wally Design Verification Test Plan
|
|
||||||
|
|
||||||
This document outlines the test plan for the Wally rv64gc configuration to reach Technology Readiness Level 5.
|
|
||||||
|
|
||||||
1. Pass riscv-arch-test
|
|
||||||
2. Boot Linux
|
|
||||||
3. FPU pass all TestFloat vectors
|
|
||||||
4. Performance verification: Caches and branch predictor miss rates match independent simulation
|
|
||||||
5. Directed tests
|
|
||||||
- Privileged unit: Chapter 5 test plan
|
|
||||||
- MMU: PMA, PMP, virtual memory: Chapter 8 test plan
|
|
||||||
- Peripherals: Chapter 16 test plan
|
|
||||||
6. Random tests
|
|
||||||
- riscdv tests
|
|
||||||
7. Coverage tests
|
|
||||||
- Directed tests to bring coverage up to 100%.
|
|
||||||
- Statement, experssion, branch, condition, FSM coverage in Questa
|
|
||||||
- Do not measure toggle coverage
|
|
||||||
|
|
||||||
All tests operate correctly in lock-step with ImperasDV
|
|
||||||
|
|
||||||
Open questions:
|
|
||||||
1. How to define extent of riscdv random tests needed?
|
|
||||||
2. What other directed tests?
|
|
||||||
PMP Tests
|
|
||||||
Virtual Memory Tests
|
|
||||||
How to define pipeline tests?
|
|
||||||
Simple ones like use after load stall are not important.
|
|
||||||
Hard ones such as page table walker fault during data access while I$ access is pending are hard to articulate and code
|
|
||||||
Is there an example of a good directed pipeline test plan & implementation
|
|
102
fpga/zsbl/bios.S
102
fpga/zsbl/bios.S
@ -1,102 +0,0 @@
|
|||||||
#include "system.h"
|
|
||||||
|
|
||||||
PERIOD = (SYSTEMCLOCK / 2)
|
|
||||||
|
|
||||||
.section .init
|
|
||||||
.global _start
|
|
||||||
.type _start, @function
|
|
||||||
|
|
||||||
|
|
||||||
_start:
|
|
||||||
# Initialize global pointer
|
|
||||||
.option push
|
|
||||||
.option norelax
|
|
||||||
1:auipc gp, %pcrel_hi(__global_pointer$)
|
|
||||||
addi gp, gp, %pcrel_lo(1b)
|
|
||||||
.option pop
|
|
||||||
|
|
||||||
li x1, 0
|
|
||||||
li x2, 0
|
|
||||||
li x4, 0
|
|
||||||
li x5, 0
|
|
||||||
li x6, 0
|
|
||||||
li x7, 0
|
|
||||||
li x8, 0
|
|
||||||
li x9, 0
|
|
||||||
li x10, 0
|
|
||||||
li x11, 0
|
|
||||||
li x12, 0
|
|
||||||
li x13, 0
|
|
||||||
li x14, 0
|
|
||||||
li x15, 0
|
|
||||||
li x16, 0
|
|
||||||
li x17, 0
|
|
||||||
li x18, 0
|
|
||||||
li x19, 0
|
|
||||||
li x20, 0
|
|
||||||
li x21, 0
|
|
||||||
li x22, 0
|
|
||||||
li x23, 0
|
|
||||||
li x24, 0
|
|
||||||
li x25, 0
|
|
||||||
li x26, 0
|
|
||||||
li x27, 0
|
|
||||||
li x28, 0
|
|
||||||
li x29, 0
|
|
||||||
li x30, 0
|
|
||||||
li x31, 0
|
|
||||||
|
|
||||||
|
|
||||||
# set the stack pointer to the top of memory - 8 bytes (pointer size)
|
|
||||||
li sp, (EXT_MEM_END - 8)
|
|
||||||
|
|
||||||
li a0, 0x00000000
|
|
||||||
li a1, EXT_MEM_BASE
|
|
||||||
#li a2, 128*1024*1024/512 # copy 128MB
|
|
||||||
li a2, 127*1024*1024/512 # copy 127MB upper 1MB contains the return address (ra)
|
|
||||||
#li a2, 800 # copy 400KB
|
|
||||||
jal ra, copyFlash
|
|
||||||
|
|
||||||
fence.i
|
|
||||||
# now toggle led so we know the copy completed.
|
|
||||||
|
|
||||||
# write to gpio
|
|
||||||
li t2, 0xFF
|
|
||||||
la t3, 0x1006000C
|
|
||||||
li t4, 5
|
|
||||||
|
|
||||||
loop:
|
|
||||||
|
|
||||||
# delay
|
|
||||||
li t0, PERIOD/2
|
|
||||||
delay1:
|
|
||||||
addi t0, t0, -1
|
|
||||||
bge t0, x0, delay1
|
|
||||||
sw t2, 0x0(t3)
|
|
||||||
|
|
||||||
li t0, PERIOD/2
|
|
||||||
delay2:
|
|
||||||
addi t0, t0, -1
|
|
||||||
bge t0, x0, delay2
|
|
||||||
sw x0, 0x0(t3)
|
|
||||||
|
|
||||||
addi t4, t4, -1
|
|
||||||
bgt t4, x0, loop
|
|
||||||
|
|
||||||
|
|
||||||
# now that the card is copied and the led toggled we
|
|
||||||
# jump to the copied contents of the sd card.
|
|
||||||
|
|
||||||
jumpToLinux:
|
|
||||||
csrrs a0, 0xF14, x0 # copy hart ID to a0
|
|
||||||
li a1, FDT_ADDRESS # This is the device tree address
|
|
||||||
la a2, end_of_bios
|
|
||||||
li t0, EXT_MEM_BASE # start of code
|
|
||||||
|
|
||||||
jalr x0, t0, 0
|
|
||||||
|
|
||||||
end_of_bios:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
54
gitflow.txt
54
gitflow.txt
@ -1,54 +0,0 @@
|
|||||||
###########################################
|
|
||||||
## A component of the CORE-V-WALLY configurable RISC-V project.
|
|
||||||
## https://github.com/openhwgroup/cvw
|
|
||||||
##
|
|
||||||
## Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
|
|
||||||
##
|
|
||||||
## SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
|
||||||
##
|
|
||||||
## Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
|
|
||||||
## except in compliance with the License, or, at your option, the Apache License version 2.0. You
|
|
||||||
## may obtain a copy of the License at
|
|
||||||
##
|
|
||||||
## https://solderpad.org/licenses/SHL-2.1/
|
|
||||||
##
|
|
||||||
## Unless required by applicable law or agreed to in writing, any work distributed under the
|
|
||||||
## License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
|
||||||
## either express or implied. See the License for the specific language governing permissions
|
|
||||||
## and limitations under the License.
|
|
||||||
################################################################################################
|
|
||||||
|
|
||||||
Setup
|
|
||||||
1. goto github and fork openhwgroup/cvw.git
|
|
||||||
2. clone: git clone --recurse-submodules git@ross144/cvw.git
|
|
||||||
3. git remote add upstream https://github.com/openhwgroup/cvw.git
|
|
||||||
4. install gh (github command line interface)
|
|
||||||
type -p curl >/dev/null || sudo apt install curl -y
|
|
||||||
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
|
|
||||||
&& sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
|
|
||||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
|
|
||||||
&& sudo apt update \
|
|
||||||
&& sudo apt install gh -y
|
|
||||||
|
|
||||||
Once per session (This authorizes gh to use your github account)
|
|
||||||
1. gh auth login
|
|
||||||
2. Use ssh and point to your public key
|
|
||||||
3. Copy one-time code from terminal to browser
|
|
||||||
|
|
||||||
Fetch upstream and sync fork
|
|
||||||
1. git pull upstream main # fetch and merge the upstream openhwgroup/cvw into your local clone
|
|
||||||
2. git push # pushes changes back to your fork. Now all three should be in sync
|
|
||||||
|
|
||||||
Create pull request
|
|
||||||
1. git pull upstream main # fetch and merge the upstream openhwgroup/cvw into your local clone
|
|
||||||
3. git push # pushes changes back to your fork. Now all three should be in sync
|
|
||||||
4. gh pr create # Create a pull request.
|
|
||||||
5. Must include a title and strongly encourage a body message explaining your changes.
|
|
||||||
6. Wait for pull request to be approved, rejected, or needs changes.
|
|
||||||
7. Finish by fetching the upstream and pushing back to your fork.
|
|
||||||
1. git pull upstream main # fetch and merge the upstream openhwgroup/cvw into your local clone
|
|
||||||
3. git push # sync your fork with the upstream and clone
|
|
||||||
|
|
||||||
|
|
||||||
If the pull request need changes, modify accordingly, commit, and push changes back to the fork.
|
|
||||||
The pull request will automatically update.
|
|
@ -17,12 +17,6 @@ endif
|
|||||||
WALLYBOARDSRC := $(WALLYLINUX)/buildroot-config-src/wally
|
WALLYBOARDSRC := $(WALLYLINUX)/buildroot-config-src/wally
|
||||||
WALLYBOARD := $(BUILDROOT)/board/wally
|
WALLYBOARD := $(BUILDROOT)/board/wally
|
||||||
|
|
||||||
# Buildroot Package Stuff
|
|
||||||
PACKAGE_SOURCE := ${WALLYLINUX}/buildroot-packages/package-source
|
|
||||||
FPGA_AXI_SDC := ${WALLYLINUX}/buildroot-packages/fpga-axi-sdc
|
|
||||||
DRIVER := ${PACKAGE_SOURCE}/fpga-axi-sdc.c
|
|
||||||
PATCHFILE := $(BRPACKAGES)/package-2023.05.1.patch
|
|
||||||
|
|
||||||
# Device tree files
|
# Device tree files
|
||||||
DTS ?= $(shell find devicetree -type f -regex ".*\.dts" | sort)
|
DTS ?= $(shell find devicetree -type f -regex ".*\.dts" | sort)
|
||||||
DTB := $(DTS:%.dts=%.dtb)
|
DTB := $(DTS:%.dts=%.dtb)
|
||||||
@ -114,15 +108,6 @@ $(WALLYBOARD): $(BUILDROOT)
|
|||||||
cp $(BR2023)/main.config $(WALLYBOARD)/main.config
|
cp $(BR2023)/main.config $(WALLYBOARD)/main.config
|
||||||
cp $(BR2023)/linux.config $(WALLYBOARD)/linux.config
|
cp $(BR2023)/linux.config $(WALLYBOARD)/linux.config
|
||||||
|
|
||||||
# Buildroot Package ---------------------------------------------------
|
|
||||||
$(BUILDROOT)/package/fpga-axi-sdc: $(BUILDROOT) $(PATCHFILE) $(BRPACKAGES)/fpga-axi-sdc
|
|
||||||
cp -r $(BRPACKAGES)/fpga-axi-sdc $(BUILDROOT)/package
|
|
||||||
sed -i 's|FPGA_AXI_SDC_SITE =|FPGA_AXI_SDC_SITE = $(PACKAGE_SOURCE)|1' $(BUILDROOT)/package/fpga-axi-sdc/fpga-axi-sdc.mk
|
|
||||||
cd $(BUILDROOT); if git apply --check $(PATCHFILE) > /dev/null ; then git apply $(PATCHFILE); fi
|
|
||||||
|
|
||||||
$(PATCHFILE):
|
|
||||||
cd $(BUILDROOT); git apply $(PATCHFILE)
|
|
||||||
|
|
||||||
$(BUILDROOT):
|
$(BUILDROOT):
|
||||||
git clone https://github.com/buildroot/buildroot.git $@
|
git clone https://github.com/buildroot/buildroot.git $@
|
||||||
cd $@; git checkout 2023.05.x
|
cd $@; git checkout 2023.05.x
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Automatically generated file; DO NOT EDIT.
|
# Automatically generated file; DO NOT EDIT.
|
||||||
# Buildroot 2023.05.3-dirty Configuration
|
# Buildroot 2023.05.3 Configuration
|
||||||
#
|
#
|
||||||
BR2_HAVE_DOT_CONFIG=y
|
BR2_HAVE_DOT_CONFIG=y
|
||||||
BR2_HOST_GCC_AT_LEAST_4_9=y
|
BR2_HOST_GCC_AT_LEAST_4_9=y
|
||||||
@ -949,7 +949,6 @@ BR2_PACKAGE_SDL_FBCON=y
|
|||||||
BR2_PACKAGE_FLASHROM_ARCH_SUPPORTS=y
|
BR2_PACKAGE_FLASHROM_ARCH_SUPPORTS=y
|
||||||
# BR2_PACKAGE_FLASHROM is not set
|
# BR2_PACKAGE_FLASHROM is not set
|
||||||
# BR2_PACKAGE_FMTOOLS is not set
|
# BR2_PACKAGE_FMTOOLS is not set
|
||||||
BR2_PACKAGE_FPGA_AXI_SDC=y
|
|
||||||
# BR2_PACKAGE_FREEIPMI is not set
|
# BR2_PACKAGE_FREEIPMI is not set
|
||||||
# BR2_PACKAGE_FXLOAD is not set
|
# BR2_PACKAGE_FXLOAD is not set
|
||||||
# BR2_PACKAGE_GPM is not set
|
# BR2_PACKAGE_GPM is not set
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
config BR2_PACKAGE_FPGA_AXI_SDC
|
|
||||||
bool "FPGA AXI SDC"
|
|
||||||
help
|
|
||||||
The Vivado-RISC-V SDC Drivers.
|
|
||||||
|
|
||||||
https://www.github.com/eugene-tarassov/vivado-risc-v
|
|
@ -1,10 +0,0 @@
|
|||||||
FPGA_AXI_SDC_MODULE_VERSION = 1.0
|
|
||||||
# TODO This variable needs to change based on where the package
|
|
||||||
# contents are stored on each individual computer. Might parameterize
|
|
||||||
# this somehow.
|
|
||||||
FPGA_AXI_SDC_SITE =
|
|
||||||
FPGA_AXI_SDC_SITE_METHOD = local
|
|
||||||
FPGA_AXI_SDC_LICENSE = GPLv2
|
|
||||||
|
|
||||||
$(eval $(kernel-module))
|
|
||||||
$(eval $(generic-package))
|
|
File diff suppressed because it is too large
Load Diff
@ -1,12 +0,0 @@
|
|||||||
diff --git a/package/Config.in b/package/Config.in
|
|
||||||
index ad438667d2..810bf0897e 100644
|
|
||||||
--- a/package/Config.in
|
|
||||||
+++ b/package/Config.in
|
|
||||||
@@ -503,6 +503,7 @@ endmenu
|
|
||||||
source "package/fconfig/Config.in"
|
|
||||||
source "package/flashrom/Config.in"
|
|
||||||
source "package/fmtools/Config.in"
|
|
||||||
+ source "package/fpga-axi-sdc/Config.in"
|
|
||||||
source "package/freeipmi/Config.in"
|
|
||||||
source "package/freescale-imx/Config.in"
|
|
||||||
source "package/fxload/Config.in"
|
|
@ -1,9 +0,0 @@
|
|||||||
.PHONY: all clean
|
|
||||||
obj-m += fpga-axi-sdc.o
|
|
||||||
|
|
||||||
all:
|
|
||||||
$(MAKE) -C '$(LINUX-DIR)' M='$(PWD)' modules
|
|
||||||
$(MAKE) -C '$(LINUX-DIR)' M='$(PWD)' modules_install
|
|
||||||
|
|
||||||
clean:
|
|
||||||
$(MAKE) -C '$(LINUX-DIR)' M='$(PWD)' clean
|
|
@ -1,496 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
|
|
||||||
#include <linux/delay.h>
|
|
||||||
#include <linux/dma-mapping.h>
|
|
||||||
#include <linux/err.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/iopoll.h>
|
|
||||||
#include <linux/platform_device.h>
|
|
||||||
#include <linux/clk.h>
|
|
||||||
#include <linux/io.h>
|
|
||||||
#include <linux/of.h>
|
|
||||||
#include <linux/of_device.h>
|
|
||||||
#include <linux/pinctrl/consumer.h>
|
|
||||||
#include <linux/regulator/consumer.h>
|
|
||||||
#include <linux/reset.h>
|
|
||||||
#include <linux/mmc/card.h>
|
|
||||||
#include <linux/mmc/host.h>
|
|
||||||
#include <linux/mmc/mmc.h>
|
|
||||||
#include <linux/mmc/slot-gpio.h>
|
|
||||||
#include <linux/ktime.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* AXI SD Card driver.
|
|
||||||
*
|
|
||||||
* AXI SD Card is open source Verilog implementation of high speed SD card controller.
|
|
||||||
* It is mainly used in FPGA designs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_INFO
|
|
||||||
#pragma GCC optimize("O0")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Capability bits
|
|
||||||
#define SDC_CAPABILITY_SD_4BIT 0x0001
|
|
||||||
#define SDC_CAPABILITY_SD_RESET 0x0002
|
|
||||||
#define SDC_CAPABILITY_ADDR 0xff00
|
|
||||||
|
|
||||||
// Control bits
|
|
||||||
#define SDC_CONTROL_SD_4BIT 0x0001
|
|
||||||
#define SDC_CONTROL_SD_RESET 0x0002
|
|
||||||
|
|
||||||
// Card detect bits
|
|
||||||
#define SDC_CARD_INSERT_INT_EN 0x0001
|
|
||||||
#define SDC_CARD_INSERT_INT_REQ 0x0002
|
|
||||||
#define SDC_CARD_REMOVE_INT_EN 0x0004
|
|
||||||
#define SDC_CARD_REMOVE_INT_REQ 0x0008
|
|
||||||
|
|
||||||
// Command status bits
|
|
||||||
#define SDC_CMD_INT_STATUS_CC 0x0001 // Command complete
|
|
||||||
#define SDC_CMD_INT_STATUS_EI 0x0002 // Any error
|
|
||||||
#define SDC_CMD_INT_STATUS_CTE 0x0004 // Timeout
|
|
||||||
#define SDC_CMD_INT_STATUS_CCRC 0x0008 // CRC error
|
|
||||||
#define SDC_CMD_INT_STATUS_CIE 0x0010 // Command code check error
|
|
||||||
|
|
||||||
// Data status bits
|
|
||||||
#define SDC_DAT_INT_STATUS_TRS 0x0001 // Transfer complete
|
|
||||||
#define SDC_DAT_INT_STATUS_ERR 0x0002 // Any error
|
|
||||||
#define SDC_DAT_INT_STATUS_CTE 0x0004 // Timeout
|
|
||||||
#define SDC_DAT_INT_STATUS_CRC 0x0008 // CRC error
|
|
||||||
#define SDC_DAT_INT_STATUS_CFE 0x0010 // Data FIFO underrun or overrun
|
|
||||||
|
|
||||||
#define CMD_TIMEOUT_MS 1000
|
|
||||||
#define BUSY_TIMEOUT_MS 500
|
|
||||||
|
|
||||||
struct sdc_regs {
|
|
||||||
volatile uint32_t argument;
|
|
||||||
volatile uint32_t command;
|
|
||||||
volatile uint32_t response1;
|
|
||||||
volatile uint32_t response2;
|
|
||||||
volatile uint32_t response3;
|
|
||||||
volatile uint32_t response4;
|
|
||||||
volatile uint32_t data_timeout;
|
|
||||||
volatile uint32_t control;
|
|
||||||
volatile uint32_t cmd_timeout;
|
|
||||||
volatile uint32_t clock_divider;
|
|
||||||
volatile uint32_t software_reset;
|
|
||||||
volatile uint32_t power_control;
|
|
||||||
volatile uint32_t capability;
|
|
||||||
volatile uint32_t cmd_int_status;
|
|
||||||
volatile uint32_t cmd_int_enable;
|
|
||||||
volatile uint32_t dat_int_status;
|
|
||||||
volatile uint32_t dat_int_enable;
|
|
||||||
volatile uint32_t block_size;
|
|
||||||
volatile uint32_t block_count;
|
|
||||||
volatile uint32_t card_detect;
|
|
||||||
volatile uint32_t res_50;
|
|
||||||
volatile uint32_t res_54;
|
|
||||||
volatile uint32_t res_58;
|
|
||||||
volatile uint32_t res_5c;
|
|
||||||
volatile uint64_t dma_addres;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sdc_host {
|
|
||||||
struct platform_device * pdev;
|
|
||||||
struct sdc_regs __iomem * regs;
|
|
||||||
uint32_t clk_freq;
|
|
||||||
spinlock_t lock;
|
|
||||||
struct mmc_request * mrq;
|
|
||||||
struct mmc_data * data;
|
|
||||||
unsigned dma_addr_bits;
|
|
||||||
unsigned dma_count;
|
|
||||||
dma_addr_t dma_addr;
|
|
||||||
unsigned dma_size;
|
|
||||||
int irq;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct of_device_id axi_sdc_of_match_table[] = {
|
|
||||||
{ .compatible = "riscv,axi-sd-card-1.0" },
|
|
||||||
{},
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(of, axi_sdc_of_match_table);
|
|
||||||
|
|
||||||
/* Set clock prescalar value based on the required clock in HZ */
|
|
||||||
static void sdc_set_clock(struct sdc_host * host, uint clock) {
|
|
||||||
unsigned clk_div;
|
|
||||||
|
|
||||||
/* Min clock frequency should be 400KHz */
|
|
||||||
if (clock < 400000) clock = 400000;
|
|
||||||
|
|
||||||
clk_div = host->clk_freq / (2 * clock);
|
|
||||||
if (clk_div > 0x100) clk_div = 0x100;
|
|
||||||
if (clk_div < 1) clk_div = 1;
|
|
||||||
|
|
||||||
if (host->regs->clock_divider != clk_div - 1) {
|
|
||||||
host->regs->clock_divider = clk_div - 1;
|
|
||||||
udelay(10000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sdc_cmd_finish(struct sdc_host * host, struct mmc_command * cmd) {
|
|
||||||
while (1) {
|
|
||||||
unsigned status = host->regs->cmd_int_status;
|
|
||||||
if (status) {
|
|
||||||
// clear interrupts
|
|
||||||
host->regs->cmd_int_status = 0;
|
|
||||||
while (host->regs->software_reset != 0) {}
|
|
||||||
if (status == SDC_CMD_INT_STATUS_CC) {
|
|
||||||
// get response
|
|
||||||
cmd->resp[0] = host->regs->response1;
|
|
||||||
if (cmd->flags & MMC_RSP_136) {
|
|
||||||
cmd->resp[1] = host->regs->response2;
|
|
||||||
cmd->resp[2] = host->regs->response3;
|
|
||||||
cmd->resp[3] = host->regs->response4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cmd->error = (status & SDC_CMD_INT_STATUS_CTE) ? -ETIME : -EIO;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sdc_setup_data_xfer(struct sdc_host * host, struct mmc_host * mmc, struct mmc_data * data) {
|
|
||||||
uint64_t timeout = 0;
|
|
||||||
|
|
||||||
data->bytes_xfered = 0;
|
|
||||||
|
|
||||||
if (host->dma_addr & 3) return -EINVAL;
|
|
||||||
if (data->blksz & 3) return -EINVAL;
|
|
||||||
if (data->blksz < 4) return -EINVAL;
|
|
||||||
if (data->blksz > 0x1000) return -EINVAL;
|
|
||||||
if (data->blocks > 0x10000) return -EINVAL;
|
|
||||||
if (host->dma_addr + data->blksz * data->blocks > ((uint64_t)1 << host->dma_addr_bits)) return -EINVAL;
|
|
||||||
if (data->sg->length < data->blksz * data->blocks) return -EINVAL;
|
|
||||||
|
|
||||||
// SD card data transfer time
|
|
||||||
timeout += data->blocks * data->blksz * 8 / (1 << mmc->ios.bus_width);
|
|
||||||
// SD card "busy" time
|
|
||||||
timeout += (uint64_t)mmc->ios.clock * BUSY_TIMEOUT_MS / 1000 * data->blocks;
|
|
||||||
|
|
||||||
host->regs->dma_addres = (uint64_t)host->dma_addr;
|
|
||||||
host->regs->block_size = data->blksz - 1;
|
|
||||||
host->regs->block_count = data->blocks - 1;
|
|
||||||
host->regs->data_timeout = (uint32_t)timeout;
|
|
||||||
if (host->regs->data_timeout != timeout) host->regs->data_timeout = 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sdc_send_cmd(struct sdc_host * host, struct mmc_host * mmc, struct mmc_command * cmd, struct mmc_data * data) {
|
|
||||||
int command = cmd->opcode << 8;
|
|
||||||
uint64_t timeout = 0;
|
|
||||||
int xfer = 0;
|
|
||||||
|
|
||||||
if (cmd->flags & MMC_RSP_PRESENT) {
|
|
||||||
if (cmd->flags & MMC_RSP_136)
|
|
||||||
command |= 2;
|
|
||||||
else {
|
|
||||||
command |= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cmd->flags & MMC_RSP_BUSY) command |= 1 << 2;
|
|
||||||
if (cmd->flags & MMC_RSP_CRC) command |= 1 << 3;
|
|
||||||
if (cmd->flags & MMC_RSP_OPCODE) command |= 1 << 4;
|
|
||||||
|
|
||||||
if (data && (data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)) && data->blocks) {
|
|
||||||
host->dma_count = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, mmc_get_dma_dir(data));
|
|
||||||
if (host->dma_count != 1) {
|
|
||||||
dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, mmc_get_dma_dir(data));
|
|
||||||
return data->error = -EIO;
|
|
||||||
}
|
|
||||||
host->dma_addr = sg_dma_address(data->sg);
|
|
||||||
host->dma_size = sg_dma_len(data->sg);
|
|
||||||
if (data->flags & MMC_DATA_READ) command |= 1 << 5;
|
|
||||||
if (data->flags & MMC_DATA_WRITE) command |= 1 << 6;
|
|
||||||
data->error = sdc_setup_data_xfer(host, mmc, data);
|
|
||||||
if (data->error < 0) {
|
|
||||||
dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, mmc_get_dma_dir(data));
|
|
||||||
return data->error;
|
|
||||||
}
|
|
||||||
xfer = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout = (uint64_t)mmc->ios.clock * CMD_TIMEOUT_MS / 1000;
|
|
||||||
|
|
||||||
host->regs->command = command;
|
|
||||||
host->regs->cmd_timeout = (uint32_t)timeout;
|
|
||||||
if (host->regs->cmd_timeout != timeout) host->regs->cmd_timeout = 0;
|
|
||||||
host->regs->argument = cmd->arg;
|
|
||||||
|
|
||||||
sdc_cmd_finish(host, cmd);
|
|
||||||
if (cmd->error < 0) {
|
|
||||||
if (xfer) dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, mmc_get_dma_dir(data));
|
|
||||||
return cmd->error;
|
|
||||||
}
|
|
||||||
if (xfer) host->data = data;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sdc_request(struct mmc_host * mmc, struct mmc_request * mrq) {
|
|
||||||
struct sdc_host * host = mmc_priv(mmc);
|
|
||||||
|
|
||||||
/* Clear the error statuses in case this is a retry */
|
|
||||||
if (mrq->sbc) mrq->sbc->error = 0;
|
|
||||||
if (mrq->cmd) mrq->cmd->error = 0;
|
|
||||||
if (mrq->data) mrq->data->error = 0;
|
|
||||||
if (mrq->stop) mrq->stop->error = 0;
|
|
||||||
|
|
||||||
spin_lock_irq(&host->lock);
|
|
||||||
host->data = NULL;
|
|
||||||
host->mrq = mrq;
|
|
||||||
|
|
||||||
if (!mrq->sbc || sdc_send_cmd(host, mmc, mrq->sbc, NULL) == 0) {
|
|
||||||
sdc_send_cmd(host, mmc, mrq->cmd, mrq->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (host->data == NULL) {
|
|
||||||
mmc_request_done(mmc, mrq);
|
|
||||||
host->mrq = NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
host->regs->dat_int_enable = SDC_DAT_INT_STATUS_TRS | SDC_DAT_INT_STATUS_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_irq(&host->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sdc_set_ios(struct mmc_host * mmc, struct mmc_ios * ios) {
|
|
||||||
struct sdc_host * host = mmc_priv(mmc);
|
|
||||||
|
|
||||||
spin_lock_irq(&host->lock);
|
|
||||||
|
|
||||||
sdc_set_clock(host, ios->clock);
|
|
||||||
host->regs->control = ios->bus_width == MMC_BUS_WIDTH_4 ? SDC_CONTROL_SD_4BIT : 0;
|
|
||||||
|
|
||||||
spin_unlock_irq(&host->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sdc_reset(struct mmc_host * mmc) {
|
|
||||||
struct sdc_host * host = mmc_priv(mmc);
|
|
||||||
uint32_t card_detect = 0;
|
|
||||||
|
|
||||||
spin_lock_init(&host->lock);
|
|
||||||
|
|
||||||
spin_lock_irq(&host->lock);
|
|
||||||
|
|
||||||
sdc_set_clock(host, 400000);
|
|
||||||
|
|
||||||
// software reset
|
|
||||||
host->regs->software_reset = 1;
|
|
||||||
while ((host->regs->software_reset & 1) == 0) {}
|
|
||||||
// clear software reset
|
|
||||||
host->regs->software_reset = 0;
|
|
||||||
while (host->regs->software_reset != 0) {}
|
|
||||||
udelay(10000);
|
|
||||||
|
|
||||||
// set bus width 1 bit
|
|
||||||
host->regs->control = 0;
|
|
||||||
|
|
||||||
// disable cmd/data interrupts
|
|
||||||
host->regs->cmd_int_enable = 0;
|
|
||||||
host->regs->dat_int_enable = 0;
|
|
||||||
// clear cmd/data interrupts
|
|
||||||
host->regs->cmd_int_status = 0;
|
|
||||||
host->regs->dat_int_status = 0;
|
|
||||||
// enable card detect interrupt
|
|
||||||
card_detect = host->regs->card_detect;
|
|
||||||
if (card_detect & SDC_CARD_INSERT_INT_REQ) {
|
|
||||||
host->regs->card_detect = SDC_CARD_REMOVE_INT_EN;
|
|
||||||
}
|
|
||||||
else if (card_detect & SDC_CARD_REMOVE_INT_REQ) {
|
|
||||||
host->regs->card_detect = SDC_CARD_INSERT_INT_EN;
|
|
||||||
}
|
|
||||||
while (host->regs->software_reset != 0) {}
|
|
||||||
|
|
||||||
spin_unlock_irq(&host->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sdc_card_reset(struct mmc_host * mmc) {
|
|
||||||
struct sdc_host * host = mmc_priv(mmc);
|
|
||||||
uint32_t control = 0;
|
|
||||||
|
|
||||||
spin_lock_irq(&host->lock);
|
|
||||||
|
|
||||||
control = host->regs->control;
|
|
||||||
host->regs->control = control | SDC_CONTROL_SD_RESET;
|
|
||||||
udelay(10);
|
|
||||||
host->regs->control = control & ~(uint32_t)SDC_CONTROL_SD_RESET;
|
|
||||||
udelay(10);
|
|
||||||
|
|
||||||
spin_unlock_irq(&host->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sdc_get_cd(struct mmc_host * mmc) {
|
|
||||||
struct sdc_host * host = mmc_priv(mmc);
|
|
||||||
uint32_t card_detect = host->regs->card_detect;
|
|
||||||
if (card_detect == 0) return 1; /* Card detect not supported */
|
|
||||||
return (card_detect & SDC_CARD_INSERT_INT_REQ) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static irqreturn_t sdc_isr(int irq, void * dev_id) {
|
|
||||||
struct mmc_host * mmc = (struct mmc_host *)dev_id;
|
|
||||||
struct sdc_host * host = mmc_priv(mmc);
|
|
||||||
uint32_t card_detect = 0;
|
|
||||||
uint32_t data_status = 0;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&host->lock, flags);
|
|
||||||
|
|
||||||
card_detect = host->regs->card_detect;
|
|
||||||
if (card_detect & SDC_CARD_INSERT_INT_REQ) {
|
|
||||||
if (card_detect & SDC_CARD_INSERT_INT_EN) {
|
|
||||||
host->regs->card_detect = SDC_CARD_REMOVE_INT_EN;
|
|
||||||
mmc_detect_change(mmc, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (card_detect & SDC_CARD_REMOVE_INT_REQ) {
|
|
||||||
if (card_detect & SDC_CARD_REMOVE_INT_EN) {
|
|
||||||
host->regs->card_detect = SDC_CARD_INSERT_INT_EN;
|
|
||||||
mmc_detect_change(mmc, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((data_status = host->regs->dat_int_status) != 0) {
|
|
||||||
host->regs->dat_int_enable = 0;
|
|
||||||
host->regs->dat_int_status = 0;
|
|
||||||
while (host->regs->software_reset != 0) {}
|
|
||||||
if (host->data) {
|
|
||||||
struct mmc_request * mrq = host->mrq;
|
|
||||||
struct mmc_data * data = host->data;
|
|
||||||
if (data_status == SDC_DAT_INT_STATUS_TRS) {
|
|
||||||
data->bytes_xfered = data->blksz * data->blocks;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data->error = -EIO;
|
|
||||||
if (data_status & SDC_DAT_INT_STATUS_CTE) data->error = -ETIME;
|
|
||||||
}
|
|
||||||
if (mrq->stop) sdc_send_cmd(host, mmc, mrq->stop, NULL);
|
|
||||||
mmc_request_done(mmc, mrq);
|
|
||||||
dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, mmc_get_dma_dir(data));
|
|
||||||
host->data = NULL;
|
|
||||||
host->mrq = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&host->lock, flags);
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static const struct mmc_host_ops axi_sdc_ops = {
|
|
||||||
.request = sdc_request,
|
|
||||||
.set_ios = sdc_set_ios,
|
|
||||||
.get_cd = sdc_get_cd,
|
|
||||||
.card_hw_reset = sdc_card_reset,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int axi_sdc_probe(struct platform_device * pdev) {
|
|
||||||
struct device * dev = &pdev->dev;
|
|
||||||
struct resource * iomem;
|
|
||||||
struct sdc_host * host;
|
|
||||||
struct mmc_host * mmc;
|
|
||||||
void __iomem * ioaddr;
|
|
||||||
uint32_t capability;
|
|
||||||
int irq;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
||||||
ioaddr = devm_ioremap_resource(dev, iomem);
|
|
||||||
if (IS_ERR(ioaddr)) return PTR_ERR(ioaddr);
|
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
|
||||||
if (irq <= 0) return -ENXIO;
|
|
||||||
|
|
||||||
mmc = mmc_alloc_host(sizeof(*host), dev);
|
|
||||||
if (!mmc) return -ENOMEM;
|
|
||||||
|
|
||||||
mmc->ops = &axi_sdc_ops;
|
|
||||||
host = mmc_priv(mmc);
|
|
||||||
host->pdev = pdev;
|
|
||||||
host->regs = (struct sdc_regs __iomem *)ioaddr;
|
|
||||||
host->irq = irq;
|
|
||||||
|
|
||||||
ret = of_property_read_u32(dev->of_node, "clock", &host->clk_freq);
|
|
||||||
if (ret) host->clk_freq = 100000000;
|
|
||||||
|
|
||||||
ret = mmc_of_parse(mmc);
|
|
||||||
if (ret) {
|
|
||||||
mmc_free_host(mmc);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mmc->f_min == 0) mmc->f_min = host->clk_freq / 0x200; /* maximum clock division 256 * 2 */
|
|
||||||
if (mmc->f_max == 0) mmc->f_max = host->clk_freq / 2; /* minimum clock division 2 */
|
|
||||||
if ((mmc->caps2 & MMC_CAP2_NO_SDIO) == 0) {
|
|
||||||
/* TODO: deprecated 10/19/2022, set in DTS */
|
|
||||||
mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
|
|
||||||
mmc->caps2 |= MMC_CAP2_NO_SDIO;
|
|
||||||
}
|
|
||||||
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
|
|
||||||
mmc->max_segs = 1;
|
|
||||||
mmc->max_req_size = 0x2000000;
|
|
||||||
mmc->max_seg_size = 0x2000000;
|
|
||||||
mmc->max_blk_size = 0x1000;
|
|
||||||
mmc->max_blk_count = 0x10000;
|
|
||||||
|
|
||||||
ret = request_irq(host->irq, sdc_isr, IRQF_TRIGGER_HIGH, "fpga-axi-sdc", mmc);
|
|
||||||
if (ret) {
|
|
||||||
mmc_free_host(mmc);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
host->dma_addr_bits = 32;
|
|
||||||
capability = host->regs->capability;
|
|
||||||
if (capability & SDC_CAPABILITY_ADDR) {
|
|
||||||
host->dma_addr_bits = (capability & SDC_CAPABILITY_ADDR) >> __builtin_ctz(SDC_CAPABILITY_ADDR);
|
|
||||||
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(host->dma_addr_bits));
|
|
||||||
if (ret) {
|
|
||||||
printk(KERN_ERR "AXI-SDC: Can't set DMA mask\n");
|
|
||||||
mmc_free_host(mmc);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sdc_reset(mmc);
|
|
||||||
|
|
||||||
ret = mmc_add_host(mmc);
|
|
||||||
if (ret) {
|
|
||||||
printk(KERN_ERR "AXI-SDC: Can't register device\n");
|
|
||||||
mmc_free_host(mmc);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//spin_lock_init(&host->lock);
|
|
||||||
|
|
||||||
platform_set_drvdata(pdev, host);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int axi_sdc_remove(struct platform_device * pdev) {
|
|
||||||
struct sdc_host * host = platform_get_drvdata(pdev);
|
|
||||||
struct mmc_host * mmc = mmc_from_priv(host);
|
|
||||||
|
|
||||||
free_irq(host->irq, mmc);
|
|
||||||
mmc_remove_host(mmc);
|
|
||||||
mmc_free_host(mmc);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct platform_driver axi_sdc_driver = {
|
|
||||||
.driver = {
|
|
||||||
.name = "riscv-axi-sdc",
|
|
||||||
.of_match_table = axi_sdc_of_match_table,
|
|
||||||
},
|
|
||||||
.probe = axi_sdc_probe,
|
|
||||||
.remove = axi_sdc_remove,
|
|
||||||
};
|
|
||||||
|
|
||||||
module_platform_driver(axi_sdc_driver);
|
|
||||||
|
|
||||||
MODULE_DESCRIPTION("AXI SD Card driver");
|
|
||||||
MODULE_AUTHOR("Eugene Tarassov");
|
|
||||||
MODULE_LICENSE("GPL v2");
|
|
@ -1,12 +0,0 @@
|
|||||||
diff --git a/package/Config.in b/package/Config.in
|
|
||||||
index 82b28d2835..29e8bb66ac 100644
|
|
||||||
--- a/package/Config.in
|
|
||||||
+++ b/package/Config.in
|
|
||||||
@@ -469,6 +469,7 @@ endmenu
|
|
||||||
source "package/fconfig/Config.in"
|
|
||||||
source "package/flashrom/Config.in"
|
|
||||||
source "package/fmtools/Config.in"
|
|
||||||
+ source "package/fpga-axi-sdc/Config.in"
|
|
||||||
source "package/freescale-imx/Config.in"
|
|
||||||
source "package/fxload/Config.in"
|
|
||||||
source "package/gcnano-binaries/Config.in"
|
|
File diff suppressed because it is too large
Load Diff
@ -192,9 +192,9 @@ if {$DEBUG > 0} {
|
|||||||
# suppress spurious warnngs about
|
# suppress spurious warnngs about
|
||||||
# "Extra checking for conflicts with always_comb done at vopt time"
|
# "Extra checking for conflicts with always_comb done at vopt time"
|
||||||
# because vsim will run vopt
|
# because vsim will run vopt
|
||||||
set INC_DIRS "+incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared +incdir+${FCRVVI} +incdir+${FCRVVI}/rv32 +incdir+${FCRVVI}/rv64 +incdir+${FCRVVI}/common +incdir+${FCRVVI}"
|
set INC_DIRS "+incdir+${CONFIG}/${CFG} +incdir+${CONFIG}/deriv/${CFG} +incdir+${CONFIG}/shared +incdir+${FCRVVI} +incdir+${FCRVVI}/rv32 +incdir+${FCRVVI}/rv64 +incdir+${FCRVVI}/rv64_priv +incdir+${FCRVVI}/common +incdir+${FCRVVI}"
|
||||||
set SOURCES "${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv"
|
set SOURCES "${SRC}/cvw.sv ${TB}/${TESTBENCH}.sv ${TB}/common/*.sv ${SRC}/*/*.sv ${SRC}/*/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*.sv ${WALLY}/addins/verilog-ethernet/*/*/*/*.sv"
|
||||||
vlog -lint +nowarnRDGN -work ${WKDIR} {*}${INC_DIRS} {*}${FCvlog} {*}${FCdefineCOVER_EXTS} {*}${lockstepvlog} ${FCdefineRVVI_COVERAGE} {*}${SOURCES} -suppress 2244 -suppress 2282 -suppress 2583 -suppress 7063,2596,13286
|
vlog -permissive -lint -work ${WKDIR} {*}${INC_DIRS} {*}${FCvlog} {*}${FCdefineCOVER_EXTS} {*}${lockstepvlog} ${FCdefineRVVI_COVERAGE} {*}${SOURCES} -suppress 2282,2583,7053,7063,2596,13286
|
||||||
|
|
||||||
# start and run simulation
|
# start and run simulation
|
||||||
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
|
# remove +acc flag for faster sim during regressions if there is no need to access internal signals
|
||||||
|
@ -64,6 +64,16 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi);
|
|||||||
logic wfiM;
|
logic wfiM;
|
||||||
logic InterruptM, InterruptW;
|
logic InterruptM, InterruptW;
|
||||||
|
|
||||||
|
//For VM Verification
|
||||||
|
|
||||||
|
logic [(P.XLEN-1):0] VAdrIM,VAdrDM,VAdrIW,VAdrDW;
|
||||||
|
logic [(P.XLEN-1):0] PTE_iM,PTE_dM,PTE_iW,PTE_dW;
|
||||||
|
logic [(P.PA_BITS-1):0] PAIM,PADM,PAIW,PADW;
|
||||||
|
logic [(P.PPN_BITS-1):0] PPN_iM,PPN_dM,PPN_iW,PPN_dW;
|
||||||
|
logic ReadAccessM,WriteAccessM,ReadAccessW,WriteAccessW;
|
||||||
|
logic ExecuteAccessF,ExecuteAccessD,ExecuteAccessE,ExecuteAccessM,ExecuteAccessW;
|
||||||
|
|
||||||
|
|
||||||
assign clk = testbench.dut.clk;
|
assign clk = testbench.dut.clk;
|
||||||
// assign InstrValidF = testbench.dut.core.ieu.InstrValidF; // not needed yet
|
// assign InstrValidF = testbench.dut.core.ieu.InstrValidF; // not needed yet
|
||||||
assign InstrValidD = testbench.dut.core.ieu.c.InstrValidD;
|
assign InstrValidD = testbench.dut.core.ieu.c.InstrValidD;
|
||||||
@ -93,6 +103,20 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi);
|
|||||||
assign wfiM = testbench.dut.core.priv.priv.wfiM;
|
assign wfiM = testbench.dut.core.priv.priv.wfiM;
|
||||||
assign InterruptM = testbench.dut.core.priv.priv.InterruptM;
|
assign InterruptM = testbench.dut.core.priv.priv.InterruptM;
|
||||||
|
|
||||||
|
//FOr VM Verification
|
||||||
|
assign VAdrIM = testbench.dut.core.ifu.immu.immu.tlb.tlb.VAdr;
|
||||||
|
assign VAdrDM = testbench.dut.core.lsu.dmmu.dmmu.tlb.tlb.VAdr;
|
||||||
|
assign PAIM = testbench.dut.core.ifu.immu.immu.PhysicalAddress;
|
||||||
|
assign PADM = testbench.dut.core.lsu.dmmu.dmmu.PhysicalAddress;
|
||||||
|
assign ReadAccessM = testbench.dut.core.lsu.dmmu.dmmu.ReadAccessM;
|
||||||
|
assign WriteAccessM = testbench.dut.core.lsu.dmmu.dmmu.WriteAccessM;
|
||||||
|
assign ExecuteAccessF = testbench.dut.core.ifu.immu.immu.ExecuteAccessF;
|
||||||
|
assign PTE_iM = testbench.dut.core.ifu.immu.immu.PTE;
|
||||||
|
assign PTE_dM = testbench.dut.core.lsu.dmmu.dmmu.PTE;
|
||||||
|
assign PPN_iM = testbench.dut.core.ifu.immu.immu.tlb.tlb.PPN;
|
||||||
|
assign PPN_dM = testbench.dut.core.lsu.dmmu.dmmu.tlb.tlb.PPN;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
logic valid;
|
logic valid;
|
||||||
int csrid;
|
int csrid;
|
||||||
@ -276,6 +300,22 @@ module wallyTracer import cvw::*; #(parameter cvw_t P) (rvviTrace rvvi);
|
|||||||
flopenrc #(12) CSRAdrWReg (clk, reset, FlushW, ~StallW, CSRAdrM, CSRAdrW);
|
flopenrc #(12) CSRAdrWReg (clk, reset, FlushW, ~StallW, CSRAdrM, CSRAdrW);
|
||||||
flopenrc #(1) CSRWriteWReg (clk, reset, FlushW, ~StallW, CSRWriteM, CSRWriteW);
|
flopenrc #(1) CSRWriteWReg (clk, reset, FlushW, ~StallW, CSRWriteM, CSRWriteW);
|
||||||
|
|
||||||
|
//for VM Verification
|
||||||
|
flopenrc #(P.XLEN) VAdrIWReg (clk, reset, FlushW, ~StallW, VAdrIM, VAdrIW);
|
||||||
|
flopenrc #(P.XLEN) VAdrDWReg (clk, reset, FlushW, ~StallW, VAdrDM, VAdrDW);
|
||||||
|
flopenrc #(P.PA_BITS) PAIWReg (clk, reset, FlushW, ~StallW, PAIM, PAIW);
|
||||||
|
flopenrc #(P.PA_BITS) PADWReg (clk, reset, FlushW, ~StallW, PADM, PADW);
|
||||||
|
flopenrc #(P.XLEN) PTE_iWReg (clk, reset, FlushW, ~StallW, PTE_iM, PTE_iW);
|
||||||
|
flopenrc #(P.XLEN) PTE_dWReg (clk, reset, FlushW, ~StallW, PTE_dM, PTE_dW);
|
||||||
|
flopenrc #(P.PPN_BITS) PPN_iWReg (clk, reset, FlushW, ~StallW, PPN_iM, PPN_iW);
|
||||||
|
flopenrc #(P.PPN_BITS) PPN_dWReg (clk, reset, FlushW, ~StallW, PPN_dM, PPN_dW);
|
||||||
|
flopenrc #(1) ReadAccessWReg (clk, reset, FlushW, ~StallW, ReadAccessM, ReadAccessW);
|
||||||
|
flopenrc #(1) WriteAccessWReg (clk, reset, FlushW, ~StallW, WriteAccessM, WriteAccessW);
|
||||||
|
flopenrc #(1) ExecuteAccessDReg (clk, reset, FlushE, ~StallE, ExecuteAccessF, ExecuteAccessD);
|
||||||
|
flopenrc #(1) ExecuteAccessEReg (clk, reset, FlushE, ~StallE, ExecuteAccessD, ExecuteAccessE);
|
||||||
|
flopenrc #(1) ExecuteAccessMReg (clk, reset, FlushM, ~StallM, ExecuteAccessE, ExecuteAccessM);
|
||||||
|
flopenrc #(1) ExecuteAccessWReg (clk, reset, FlushW, ~StallW, ExecuteAccessM, ExecuteAccessW);
|
||||||
|
|
||||||
// Initially connecting the writeback stage signals, but may need to use M stage
|
// Initially connecting the writeback stage signals, but may need to use M stage
|
||||||
// and gate on ~FlushW.
|
// and gate on ~FlushW.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user