12 Commits

Author SHA1 Message Date
Philip Smart
b0ad5db6c6 Alpha release candidate rc1 2023-04-17 21:46:26 +01:00
Philip Smart
2200e233e2 Added arbiter and bug fixes 2023-03-05 22:28:27 +00:00
Philip Smart
bd8cc2e964 Update RFS driver to install ROMS 2023-03-04 16:01:07 +00:00
Philip Smart
fe53a4c871 Updates for the Sharp MZ TTY driver 2023-03-03 20:02:26 +00:00
Philip Smart
09c9f0dadc Updates to support full memory in bank 4 of TZFS 2023-02-26 19:37:06 +00:00
Philip Smart
e88777b04b Added attributes 2023-02-22 21:46:25 +00:00
Philip Smart
582a50dd80 Added license 2023-02-22 21:45:23 +00:00
Philip Smart
a3cfebc7f9 Added TZFS device driver and K64F CPU 2023-02-22 14:53:46 +00:00
Philip Smart
652bdd81eb SD Write bug fixed 2023-02-15 16:57:45 +00:00
Philip Smart
db177d2240 More updates to get git in-sync with dvlp env 2023-02-14 11:50:03 +00:00
Philip Smart
dfa3dd5a57 Files not in repository 2023-02-14 11:37:54 +00:00
Philip Smart
826783ab79 MZ80A Virtual RFS Driver added 2023-02-14 09:16:03 +00:00
1553 changed files with 28267 additions and 405018 deletions

7
.gitattributes vendored Normal file
View File

@@ -0,0 +1,7 @@
* linguist-vendored
*.asm linguist-vendored=false
*.c linguist-vendored=false
*.cpp linguist-vendored=false
*.pl linguist-vendored=false
*.sh linguist-vendored=false
*.vhd linguist-vendored=false

92
.gitignore vendored
View File

@@ -3,18 +3,14 @@
**/build/**
c5_pin_model_dump.txt
_config.yml
CPLD
CPLD/build/db/
CPLD/build/incremental_db/
CPLD/build/output_files/
CPLD/build/simulation/
CPLD/build/tranZPUterSW_constraints.sdc.clk
CPLD/mz80b/
CPLD/v1.0
CPLD/v1.0.bak/
CPLD/v1.0/build/greybox_tmp/
CPLD/v1.0/MZ2000
CPLD/v1.0/MZ2000/build
CPLD/v1.0/MZ2000/build/db/
CPLD/v1.0/MZ2000/build/greybox_tmp
CPLD/v1.0/MZ2000/build/greybox_tmp/
@@ -35,8 +31,6 @@ CPLD/v1.0/MZ2000/tranZPUterSW700.vhd.sav3
CPLD/v1.0/MZ2000/tranZPUterSW.sav2
CPLD/v1.0/MZ2000/tranZPUterSW.vhd.clk
CPLD/v1.0/MZ2000/tranZPUterSW.vhd.presweep
CPLD/v1.0/MZ700
CPLD/v1.0/MZ700/build
CPLD/v1.0/MZ700/build/db
CPLD/v1.0/MZ700/build/db/
CPLD/v1.0/MZ700/build/greybox_tmp
@@ -58,8 +52,6 @@ CPLD/v1.0/MZ700/tranZPUterSW.vhd.clk
CPLD/v1.0/MZ700/tranZPUterSW.vhd.presweep
CPLD/v1.0/MZ700/working
CPLD/v1.0/MZ700/working2
CPLD/v1.0/MZ80A
CPLD/v1.0/MZ80A/build
CPLD/v1.0/MZ80A/build/db/
CPLD/v1.0/MZ80A/build/emuMZ_ClockII.qip
CPLD/v1.0/MZ80A/build/greybox_tmp
@@ -341,7 +333,6 @@ software/FusionX/src/driver/Makefile3
software/FusionX/src/driver/MZ2000/old/
software/FusionX/src/driver/MZ700/old/
software/FusionX/src/driver/mz700.rom
software/FusionX/src/driver/MZ80A/
software/FusionX/src/driver/MZ80A/old/
software/FusionX/src/driver/test
software/FusionX/src/driver/.tmp_versions
@@ -350,6 +341,7 @@ software/FusionX/src/driver/Z80
software/FusionX/src/driver/Z80/
software/FusionX/src/driver/Z80.c.old
software/FusionX/src/driver/z80ctrl
software/FusionX/src/driver/k64fcpu
software/FusionX/src/driver/Z80.rc.in
software/FusionX/src/hello
software/FusionX/src/spitools
@@ -1668,4 +1660,86 @@ software/linux/kernel/drivers/sstar/emac/modules.order
software/linux/kernel/drivers/sstar/netphy/modules.builtin
software/linux/kernel/drivers/sstar/netphy/modules.order
software/linux/project/release/nvr/i2m/011A/glibc/8.2.1/bin/kernel/spinand/
README.md.last
software/CPM
software/FusionX/history
software/FusionX/src/driver.ng/
software/FusionX/src/driver/Makefile.old
software/FusionX/src/driver/Z80.c.old2
software/FusionX/src/driver/Zeta.test/
software/FusionX/src/driver/sa1510.orig
software/linux/kernel/arch/arm/boot/dts/hold/
software/linux/kernel/arch/arm/configs/infinity2m_spinand_fusionx_defconfig.hld2
CPLD/v1.0/MZ80A.ng/
software/FusionX/src/driver/MZ80A/emumz.c
software/FusionX/src/driver/MZ80A/sharpmz.c
software/FusionX/src/driver/MZ700/emumz.c
software/FusionX/src/driver/MZ700/sharpmz.c
software/FusionX/src/driver/MZ2000/emumz.c
software/FusionX/src/driver/MZ2000/sharpmz.c
software/FusionX/src/driver/MZ80A/z80driver.c.bad
software/FusionX/src/driver/MZ80A/z80vhw_rfs.c.bad
software/FusionX/disk
software/FusionX/roms
software/linux/project/FusionX/
software/FusionX/src/driver/MZ80A/k64fcpu.c.hld
software/linux/buildroot/.config.old
software/linux/kernel/scripts/kconfig/.mconf.cmd
software/FusionX/src/ttymz/.tmp_versions/
software/FusionX/src/ttymz/.ttymzdrv.ko.cmd
software/FusionX/src/ttymz/Makefile.orig
software/FusionX/src/ttymz/Module.symvers
software/FusionX/src/ttymz/modules.order
software/FusionX/src/ttymz/ttymzdrv.ko
software/FusionX/src/ttymz/ttymzdrv.mod.c
software/FusionX/src/z80drv/.tmp_versions/
software/FusionX/src/z80drv/.z80drv.ko.cmd
software/FusionX/src/z80drv/Kbuild.in
software/FusionX/src/z80drv/MZ80A/emumz.c
software/FusionX/src/z80drv/MZ80A/k64fcpu.c.hld
software/FusionX/src/z80drv/MZ80A/z80driver.c.bad
software/FusionX/src/z80drv/MZ80A/z80vhw_rfs.c.bad
software/FusionX/src/z80drv/Makefile.old
software/FusionX/src/z80drv/Makefile1
software/FusionX/src/z80drv/Makefile3
software/FusionX/src/z80drv/Module.symvers
software/FusionX/src/z80drv/Z80.c.old
software/FusionX/src/z80drv/Z80.c.old2
software/FusionX/src/z80drv/Z80.rc.in
software/FusionX/src/z80drv/Z80.x/
software/FusionX/src/z80drv/Zeta.test/
software/FusionX/src/z80drv/k64fcpu
software/FusionX/src/z80drv/modules.order
software/FusionX/src/z80drv/mz700.rom
software/FusionX/src/z80drv/sa1510.orig
software/FusionX/src/z80drv/test
software/FusionX/src/z80drv/x.mzf
software/FusionX/src/z80drv/z80ctrl
software/FusionX/src/z80drv/z80drv.ko
software/FusionX/src/z80drv/z80drv.mod.c
software/FusionX/host/
software/FusionX/src/z80drv/sharpbiter
CPLD/v1.0/MZ2000/tzpuFusionX.vhd.bak
CPLD/v1.0/MZ2000/tzpuFusionX.vhd.new
CPLD/v1.0/MZ700/tzpuFusionX.vhd.old
CPLD/v1.0/MZ80A/tzpuFusionX.vhd.bak
software/FusionX/src/ttymz/Makefile.kmod
software/FusionX/src/ttymz/z80io.h.old
software/FusionX/src/z80drv/1
software/FusionX/src/z80drv/2
software/FusionX/src/z80drv/Makefile.mod
software/FusionX/src/z80drv/Makefile.x
software/FusionX/src/z80drv/Z80.c.old3
software/FusionX/src/z80drv/Zeta.old3/
software/FusionX/src/z80drv/integral.h
software/FusionX/src/z80drv/src.mz2000/
software/FusionX/src/z80drv/src.mz80a/
software/FusionX/src/z80drv/src.pcw/
software/FusionX/src/z80drv/src/PCW8256_boot.hex
software/FusionX/src/z80drv/src/PCW8256_boot.rom
software/FusionX/src/z80drv/src/ccc
software/FusionX/src/z80drv/src/k64fcpu.c.hld
software/FusionX/src/z80drv/src/z80driver.c.bad
software/FusionX/src/z80drv/src/z80vhw_rfs.c.bad
CPLD/v1.0/MZ2000.old/

10
.gitmodules vendored
View File

@@ -1,6 +1,12 @@
[submodule "software/FusionX/src/driver/Z80"]
path = software/FusionX/src/driver/Z80
path = software/FusionX/src/z80drv/Z80
url = https://github.com/redcode/Z80.git
[submodule "software/FusionX/src/driver/Zeta"]
path = software/FusionX/src/driver/Zeta
path = software/FusionX/src/z80drv/Zeta
url = https://github.com/redcode/Zeta.git
[submodule "software/FusionX/src/driver/6502"]
path = software/FusionX/src/z80drv/6502
url = https://github.com/redcode/6502.git
[submodule "software/FusionX/src/driver/software/FusionX/src/driver/6502"]
path = software/FusionX/src/z80drv/software/FusionX/src/driver/6502
url = https://github.com/redcode/6502.git

View File

@@ -127,10 +127,10 @@ set_location_assignment PIN_21 -to VSOM_RSV[1]
# SOM Control Signals
# ===================
set_location_assignment PIN_28 -to VSOM_READY
set_location_assignment PIN_18 -to VSOM_LTSTATE
set_location_assignment PIN_19 -to VSOM_LTSTATE
set_location_assignment PIN_27 -to VSOM_BUSRQ
set_location_assignment PIN_26 -to VSOM_BUSACK
set_location_assignment PIN_19 -to VSOM_INT
set_location_assignment PIN_18 -to VSOM_INT
set_location_assignment PIN_22 -to VSOM_NMI
set_location_assignment PIN_25 -to VSOM_WAIT
set_location_assignment PIN_23 -to VSOM_RESET

View File

@@ -2,16 +2,17 @@
--
-- Name: tzpuFusionX.vhd
-- Version: MZ-2000
-- Created: June 2020
-- Created: Jan 2023
-- Author(s): Philip Smart
-- Description: tzpuFusionX CPLD logic definition file.
-- This module contains the definition of the tzpuFusionX project plus enhancements
-- for the MZ-2000.
--
-- Credits:
-- Copyright: (c) 2018-22 Philip Smart <philip.smart@net2net.org>
-- Copyright: (c) 2018-23 Philip Smart <philip.smart@net2net.org>
--
-- History: Oct 2022 - Initial write for the MZ-2000.
-- History: Jan 2023 v1.0 - Initial write for the MZ-2000.
-- Apr 2023 v1.1 - Updates from the PCW8256 development.
--
---------------------------------------------------------------------------------------------------------
-- This source file is free software: you can redistribute it and-or modify
@@ -128,7 +129,7 @@ end entity;
architecture rtl of cpld512 is
-- Finite State Machine states.
-- Z80 Finite State Machine states.
type SOMFSMState is
(
IdleCycle,
@@ -174,6 +175,14 @@ architecture rtl of cpld512 is
BusReqCycle
);
-- Controller FSM states.
type CTRLFSMState is
(
CTRLCMD_Idle,
CTRLCMD_ReadIOWrite,
CTRLCMD_ReadIOWrite_1
);
-- CPU Interface internal signals.
signal Z80_BUSRQni : std_logic;
signal Z80_INTni : std_logic;
@@ -185,7 +194,6 @@ architecture rtl of cpld512 is
signal Z80_HALTni : std_logic;
signal Z80_M1ni : std_logic;
signal Z80_RFSHni : std_logic;
signal Z80_DATAi : std_logic_vector(7 downto 0);
signal Z80_BUSRQ_ACKni : std_logic;
-- Internal CPU state control.
@@ -203,9 +211,10 @@ architecture rtl of cpld512 is
-- Refresh control.
signal FSM_STATE : SOMFSMState := IdleCycle;
signal NEW_SPI_CMD : std_logic := '0';
signal CTRL_STATE : CTRLFSMState := CTRLCMD_Idle;
signal NEW_SPI_DATA : std_logic := '0';
signal VCPU_CS_EDGE : std_logic_vector(1 downto 0) := "11";
signal AUTOREFRESH_CNT : integer range 0 to 7;
signal AUTOREFRESH_CNT : integer range 0 to 63;
signal FSM_STATUS : std_logic := '0';
signal FSM_CHECK_WAIT : std_logic := '0';
signal FSM_WAIT_ACTIVE : std_logic := '0';
@@ -229,11 +238,12 @@ architecture rtl of cpld512 is
signal SPI_RX_SREG : std_logic_vector(7 downto 0); -- RX Shift Register
signal SPI_TX_DATA : std_logic_vector(31 downto 0); -- Data to transmit.
signal SPI_RX_DATA : std_logic_vector(31 downto 0); -- Data received.
signal SPI_BIT_CNT : integer range 0 to 16; -- Count of bits tx/rx'd.
signal SPI_BIT_CNT : integer range 0 to 7; -- Count of bits tx/rx'd.
signal SPI_FRAME_CNT : integer range 0 to 4; -- Number of frames received (8bit chunks).
-- SPI Command interface.
signal SOM_CMD : std_logic_vector(7 downto 0) := (others => '0');
signal SOM_PARAM_CNT : integer range 0 to 3;
signal SPI_NEW_DATA : std_logic;
signal SPI_PROCESSING : std_logic;
signal SPI_CPU_ADDR : std_logic_vector(15 downto 0) := (others => '0');
@@ -275,7 +285,7 @@ begin
-- On the second edge, if occurring within 1 second of the first, the PM_RESET signal to the SOM is triggered, held low for 1 second,
-- forcing the SOM to reboot.
SYSRESET: process( Z80_CLKi, Z80_RESETn )
variable timer1 : integer range 0 to 354000 := 0;
variable timer1 : integer range 0 to 400000 := 0;
variable timer100 : integer range 0 to 10 := 0;
variable timerPMReset : integer range 0 to 10 := 0;
variable resetCount : integer range 0 to 3 := 0;
@@ -311,7 +321,7 @@ begin
end if;
-- 100ms interval.
if(timer1 = 354000) then
if(timer1 = 400000) then
timer100 := timer100 + 1;
if(timer100 >= 10) then
@@ -340,8 +350,11 @@ begin
-- SPI Slave input. Receive command and data from the SOM.
SPI_INPUT : process(VSOM_SPI_CLK)
begin
-- Chip Select inactive, disable process and reset control flags.
if(VSOM_SPI_CSn = '1') then
-- SPI_CLK_POLARITY='0' => falling edge; SPI_CLK_POLARITY='1' => rising edge
if(VSOM_SPI_CLK'event and VSOM_SPI_CLK = SPI_CLK_POLARITY) then
elsif(VSOM_SPI_CLK'event and VSOM_SPI_CLK = SPI_CLK_POLARITY) then
if(VSOM_SPI_CSn = '0') then
SPI_RX_SREG <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
@@ -356,7 +369,7 @@ begin
elsif(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 3 and SPI_BIT_CNT = 0) then
SPI_RX_DATA(23 downto 16) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
elsif(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 4 and SPI_BIT_CNT = 0) then
elsif(SPI_FRAME_CNT = 4 and SPI_BIT_CNT = 0) then
SPI_RX_DATA(31 downto 24) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
end if;
end if;
@@ -366,18 +379,22 @@ begin
-- SPI Slave output. Return the current data set as selected by the input signals XACT.
SPI_OUTPUT : process(VSOM_SPI_CLK,VSOM_SPI_CSn,SPI_TX_DATA)
begin
-- Chip Select inactive, disable process and reset control flags.
if(VSOM_SPI_CSn = '1') then
SPI_SHIFT_EN <= '0';
SPI_BIT_CNT <= 15;
SPI_BIT_CNT <= 7;
-- SPI_CLK_POLARITY='0' => falling edge; SPI_CLK_POLARITY='1' => risinge edge
elsif(VSOM_SPI_CLK'event and VSOM_SPI_CLK = not SPI_CLK_POLARITY) then
-- Each clock reset the shift enable and done flag in preparation for the next cycle.
SPI_SHIFT_EN <= '1';
-- Bit count decrements to detect when last bit of byte is sent.
if(SPI_BIT_CNT > 0) then
SPI_BIT_CNT <= SPI_BIT_CNT - 1;
end if;
-- Shift out the next bit.
VSOM_SPI_MISO <= SPI_TX_SREG(6);
SPI_TX_SREG <= SPI_TX_SREG(5 downto 0) & '0';
@@ -392,6 +409,7 @@ begin
SPI_FRAME_CNT<= 1;
VSOM_SPI_MISO<= SPI_TX_DATA(7);
SPI_TX_SREG <= SPI_TX_DATA(6 downto 0);
-- Increment frame count for each word received. We handle 8bit (1 frame), 16bit (2 frames) or 32bit (4 frames) reception.
elsif(SPI_FRAME_CNT = 1) then
SPI_FRAME_CNT<= 2;
VSOM_SPI_MISO<= SPI_TX_DATA(15);
@@ -400,13 +418,14 @@ begin
SPI_FRAME_CNT<= 3;
VSOM_SPI_MISO<= SPI_TX_DATA(23);
SPI_TX_SREG <= SPI_TX_DATA(22 downto 16);
else
elsif(SPI_FRAME_CNT = 3) then
-- Increment frame count for each word received. We handle 8bit (1 frame), 16bit (2 frames) or 32bit (4 frames) reception.
SPI_FRAME_CNT<= 4;
VSOM_SPI_MISO<= SPI_TX_DATA(31);
SPI_TX_SREG <= SPI_TX_DATA(30 downto 24);
else
SPI_FRAME_CNT<= 0;
end if;
SPI_BIT_CNT <= 7;
end if;
end if;
@@ -424,6 +443,7 @@ begin
AUTOREFRESH <= '0';
SPI_LOOPBACK_TEST <= '0';
SOM_CMD <= (others => '0');
SOM_PARAM_CNT <= 0;
SPI_CPU_ADDR <= (others => '0');
SPI_NEW_DATA <= '0';
@@ -432,6 +452,7 @@ begin
-- for 8bit, 16bit and 32bit transmissions.
-- The packet is formatted as follows:
--
-- < SPI_CPU_ADDR > < SPI_CPU_DATA >< SOM_CMD>
-- < SPI_FRAME_CNT=4 >< SPI_FRAME=3 > < SPI_FRAME_CNT=2 >< SPI_FRAME_CNT=1>
-- < 16bit Z80 Address > < Z80 Data ><Command=00..80>
-- 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
@@ -441,66 +462,110 @@ begin
--
elsif(VSOM_SPI_CSn'event and VSOM_SPI_CSn = '1') then
-- Command is always located in the upper byte of frame 1.
SOM_CMD <= SPI_RX_DATA(7 downto 0);
-- If active, decrement parameter count. Parameters sent after a command are not considered as commands.
if(SOM_PARAM_CNT > 0) then
SOM_PARAM_CNT <= SOM_PARAM_CNT - 1;
end if;
-- Toggle flag to indicate new data arrived.
SPI_NEW_DATA <= not SPI_NEW_DATA;
-- Process if command, store parameters.
if(SOM_PARAM_CNT = 0) then
-- Command is always located in the upper byte of frame 1.
SOM_CMD <= SPI_RX_DATA(7 downto 0);
-- Process the command. Some commands require the FSM, others can be serviced immediately.
case SPI_RX_DATA(7 downto 0) is
-- Toggle flag to indicate new data arrived.
SPI_NEW_DATA <= not SPI_NEW_DATA;
-- Z80XACT(0..15): Setup data and address as provided then execute FSM.
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" | -- Fetch
X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" | -- Write
X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" | -- Read
X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" | -- WriteIO
X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" | -- ReadIO
X"38" | X"39" | X"3A" | X"3B" | X"3C" | X"3D" | X"3E" | X"3F" | --
X"40" | X"41" | X"42" | X"43" | X"44" | X"45" | X"46" | X"47" | --
X"48" | X"49" | X"4A" | X"4B" | X"4C" | X"4D" | X"4E" | X"4F" =>
-- Process the command. Some commands require the FSM, others can be serviced immediately.
case SPI_RX_DATA(7 downto 0) is
-- Direct address set.
if(SPI_FRAME_CNT = 4) then
SPI_CPU_ADDR <= SPI_RX_DATA(31 downto 16);
else
-- if(SPI_CPU_ADDR >= X"D010" and SPI_CPU_ADDR < X"D020") then
-- SPI_CPU_ADDR <= std_logic_vector(X"D020" + unsigned(SPI_RX_DATA(2 downto 0)));
-- else
SPI_CPU_ADDR <= std_logic_vector(unsigned(SPI_CPU_ADDR) + unsigned(SPI_RX_DATA(2 downto 0)));
-- end if;
end if;
-- Z80XACT(0..15): Setup data and address as provided then execute FSM.
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" | -- Fetch
X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" | -- Write
X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" | -- Read
X"48" | X"49" | X"4A" | X"4B" | X"4C" | X"4D" | X"4E" | X"4F" =>
if(SPI_FRAME_CNT > 1) then
SPI_CPU_DATA <= SPI_RX_DATA(15 downto 8);
end if;
-- Direct address set.
if(SPI_FRAME_CNT = 4) then
SPI_CPU_ADDR <= SPI_RX_DATA(31 downto 16);
else
SPI_CPU_ADDR <= std_logic_vector(unsigned(SPI_CPU_ADDR) + unsigned(SPI_RX_DATA(2 downto 0)));
end if;
-- SETSIGSET1: Set control lines directly.
when X"F0" =>
VIDEO_SRCi <= SPI_RX_DATA(8);
MONO_VIDEO_SRCi <= SPI_RX_DATA(9);
AUDIO_SRC_Li <= SPI_RX_DATA(10);
AUDIO_SRC_Ri <= SPI_RX_DATA(11);
VBUS_ENi <= SPI_RX_DATA(12);
VGA_BLANKn <= not SPI_RX_DATA(13);
if(SPI_FRAME_CNT > 1) then
SPI_CPU_DATA <= SPI_RX_DATA(15 downto 8);
end if;
-- Enable auto refresh DRAM cycle.
when X"F1" =>
AUTOREFRESH <= '1';
when X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" => -- WriteIO
-- Disable auto refresh DRAM cycle.
when X"F2" =>
AUTOREFRESH <= '0';
-- Direct address set.
if(SPI_FRAME_CNT = 4) then
SPI_CPU_ADDR <= SPI_RX_DATA(31 downto 16);
else
SPI_CPU_ADDR <= X"000" & '0' & std_logic_vector(unsigned(SPI_RX_DATA(2 downto 0)));
end if;
-- SETLOOPBACK: Enable loopback test mode.
when X"FE" =>
SPI_LOOPBACK_TEST<= '1';
if(SPI_FRAME_CNT > 1) then
SPI_CPU_DATA <= SPI_RX_DATA(15 downto 8);
end if;
-- No action, called to retrieve status.
when X"00" | X"FF" =>
when X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" | -- ReadIO
X"38" | X"39" | X"3A" | X"3B" | X"3C" | X"3D" | X"3E" | X"3F" => -- ReadIO-Write
when others =>
end case;
-- Direct address set.
if(SPI_FRAME_CNT = 4) then
SPI_CPU_ADDR <= SPI_RX_DATA(31 downto 16);
elsif(SPI_FRAME_CNT = 2) then
SPI_CPU_ADDR <= X"00" & SPI_RX_DATA(15 downto 8);
else
SPI_CPU_ADDR <= X"000" & '0' & std_logic_vector(unsigned(SPI_RX_DATA(2 downto 0)));
end if;
if(SPI_FRAME_CNT > 1) then
SPI_CPU_DATA <= SPI_RX_DATA(15 downto 8);
end if;
-- ReadIO-Write, Read-WriteIO commands require target address, so indicate parameter needed.
if(SPI_RX_DATA(7 downto 0) >= X"38" and SPI_RX_DATA(7 downto 0) < X"40") then
SOM_PARAM_CNT <= 1;
end if;
-- SETSIGSET1: Set control lines directly.
when X"F0" =>
VIDEO_SRCi <= SPI_RX_DATA(8);
MONO_VIDEO_SRCi <= SPI_RX_DATA(9);
AUDIO_SRC_Li <= SPI_RX_DATA(10);
AUDIO_SRC_Ri <= SPI_RX_DATA(11);
VBUS_ENi <= SPI_RX_DATA(12);
VGA_BLANKn <= not SPI_RX_DATA(13);
-- Enable auto refresh DRAM cycle.
when X"F1" =>
AUTOREFRESH <= '1';
-- Disable auto refresh DRAM cycle.
when X"F2" =>
AUTOREFRESH <= '0';
-- SETLOOPBACK: Enable loopback test mode.
when X"FE" =>
SPI_LOOPBACK_TEST<= '1';
-- No action, called to retrieve status.
when X"00" | X"FF" =>
when others =>
end case;
else
-- Store parameter depending on number of frames, either ADDR+DATA, ADDR or DATA.
if(SPI_FRAME_CNT = 4) then
SPI_CPU_ADDR <= SPI_RX_DATA(31 downto 16);
SPI_CPU_DATA <= SPI_RX_DATA(15 downto 8);
elsif(SPI_FRAME_CNT = 2) then
SPI_CPU_ADDR <= SPI_RX_DATA(15 downto 0);
else
SPI_CPU_DATA <= SPI_RX_DATA(7 downto 0);
end if;
end if;
end if;
end process;
@@ -561,9 +626,9 @@ begin
CPU_DATA_EN <= '0';
CPU_DATA_IN <= (others => '0');
REFRESH_ADDR <= (others => '0');
AUTOREFRESH_CNT <= 7;
AUTOREFRESH_CNT <= 63;
IPAR <= (others => '0');
NEW_SPI_CMD <= '0';
NEW_SPI_DATA <= '0';
VCPU_CS_EDGE <= "11";
SPI_PROCESSING <= '0';
@@ -580,98 +645,12 @@ begin
-- New command, set flag as the signal is only 1 clock wide.
if(SPI_LOOPBACK_TEST = '0' and VSOM_SPI_CSn = '1' and VCPU_CS_EDGE = "01") then
NEW_SPI_CMD <= '1';
NEW_SPI_DATA <= '1';
end if;
-- Whenever we return to Idle or just prior to Refresh from a Fetch cycle set all control signals to default.
if(FSM_STATE = IdleCycle or FSM_STATE = RefreshCycle) then
CPU_DATA_EN <= '0';
Z80_MREQni <= '1';
Z80_IORQni <= '1';
Z80_RDni <= '1';
Z80_WRni <= '1';
Z80_M1ni <= '1';
FSM_STATUS <= '0';
Z80_RFSHni <= '1';
-- Auto DRAM refresh cycles. When enabled, every 7 host clock cycles, a 2 cycle refresh period commences.
-- This will be overriden if the SPI receives a new command.
--
if AUTOREFRESH = '1' and FSM_STATE = IdleCycle then
AUTOREFRESH_CNT <= AUTOREFRESH_CNT - 1;
if(AUTOREFRESH_CNT = 0) then
FSM_STATE <= RefreshCycle_3;
end if;
end if;
end if;
-- If new command has been given and the FSM enters idle state, load up new command for processing.
if(NEW_SPI_CMD = '1' and FSM_STATE = IdleCycle and Z80_CLK_RE = '1') then
NEW_SPI_CMD <= '0';
-- Store new address and data for this command.
CPU_ADDR <= SPI_CPU_ADDR;
if(SPI_CPU_DATA /= CPU_DATA_OUT) then
CPU_DATA_OUT <= SPI_CPU_DATA;
end if;
-- Process the SOM command. The SPI_REGISTER executes non FSM commands and stores FSM
-- data prior to this execution block, which fires 1 cycle later on the same control clock.
-- If the command is not for the FSM then the READY mechanism is held for one
-- further cycle before going inactive.
case SOM_CMD is
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" =>
-- Initiate a Fetch Cycle.
FSM_STATE <= FetchCycle;
when X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" =>
-- Set the Z80 data bus value and initiate a Write Cycle.
FSM_STATE <= WriteCycle;
when X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" =>
-- Initiate a Read Cycle.
FSM_STATE <= ReadCycle;
when X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" =>
-- Set the Z80 data bus value and initiate an IO Write Cycle.
-- The SOM should set 15:8 to the B register value.
FSM_STATE <= WriteIOCycle;
when X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" =>
-- Initiate a Read IO Cycle.
FSM_STATE <= ReadIOCycle;
when X"50" =>
-- Register a Halt state.
FSM_STATE <= HaltCycle;
when X"51" =>
-- Initiate a refresh cycle.
FSM_STATE <= RefreshCycle_3;
when X"E0" =>
-- Initiate a Halt Cycle.
FSM_STATE <= HaltCycle;
-- Set the Refresh Address register.
when X"E1" =>
REFRESH_ADDR <= CPU_DATA_OUT;
-- Set the Interrupt Page Address Register.
when X"E2" =>
IPAR <= CPU_DATA_OUT;
when others =>
end case;
-- Toggle the processing flag to negate the new data flag. Used to indicate device is busy.
if(SPI_NEW_DATA /= SPI_PROCESSING) then
SPI_PROCESSING <= not SPI_PROCESSING;
end if;
-- FSM Status bit. When processing a command it is set, cleared when idle. Used by SOM to determine command completion.
FSM_STATUS <= '1';
-- Decrement refresh counter on each Z80 cycle, thus when idle and time expired, a refresh can be performed within parameters (256 cycles in 4ms).
if(AUTOREFRESH = '1' and AUTOREFRESH_CNT /= 0 and Z80_CLK_RE = '1') then
AUTOREFRESH_CNT <= AUTOREFRESH_CNT - 1;
end if;
-- Refresh status bit. Indicates a Refresh cycle is under way.
@@ -686,7 +665,143 @@ begin
FSM_WAIT_ACTIVE <= '1';
end if;
-- On each Z80 edge we advance the FSM to recreate the Z80 external signal transactions.
-- Whenever we return to Idle or just prior to Refresh from a Fetch cycle set all control signals to default.
if((FSM_STATE = IdleCycle or FSM_STATE = RefreshCycle) and Z80_CLK_RE = '1') then
CPU_DATA_EN <= '0';
Z80_MREQni <= '1';
Z80_IORQni <= '1';
Z80_RDni <= '1';
Z80_WRni <= '1';
Z80_M1ni <= '1';
FSM_STATUS <= '0';
Z80_RFSHni <= '1';
-- Auto DRAM refresh cycles. When enabled, every 15.6us a refresh period commences.
-- This period may be extended if the SPI receives a new command.
--
if AUTOREFRESH = '1' and FSM_STATE = IdleCycle then
if(AUTOREFRESH_CNT = 0) then
FSM_STATE <= RefreshCycle_3;
FSM_STATUS<= '1';
-- 4164 DRAM = 256 cycles in 4ms.
AUTOREFRESH_CNT <= 63;
end if;
end if;
end if;
--------------------------------------------------------------------------------------------
-- CPLD Macro Command Finite State Machine.
--------------------------------------------------------------------------------------------
-- Controller state machine.
-- When idle, accept and process SPI commands which can lead to a controller macro command.
case CTRL_STATE is
when CTRLCMD_Idle =>
-- If new command has been given and the FSM enters idle state, load up new command for processing.
if(NEW_SPI_DATA = '1' and FSM_STATE = IdleCycle and Z80_CLK_RE = '1') then
-- Store new address and data for this command.
if(NEW_SPI_DATA = '1') then
CPU_ADDR <= SPI_CPU_ADDR;
CPU_DATA_OUT <= SPI_CPU_DATA;
end if;
-- Process the SOM command. The SPI_REGISTER executes non FSM commands and stores FSM
-- data prior to this execution block, which fires 1 cycle later on the same control clock.
-- If the command is not for the FSM then the READY mechanism is held for one
-- further cycle before going inactive.
case SOM_CMD is
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" =>
-- Initiate a Fetch Cycle.
FSM_STATE <= FetchCycle;
when X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" =>
-- Set the Z80 data bus value and initiate a Write Cycle.
FSM_STATE <= WriteCycle;
when X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" =>
-- Initiate a Read Cycle.
FSM_STATE <= ReadCycle;
when X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" =>
-- Set the Z80 data bus value and initiate an IO Write Cycle.
-- The SOM should set 15:8 to the B register value.
FSM_STATE <= WriteIOCycle;
when X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" =>
-- Initiate a Read IO Cycle.
FSM_STATE <= ReadIOCycle;
when X"38" | X"39" | X"3A" | X"3B" | X"3C" | X"3D" | X"3E" | X"3F" =>
-- Initiate a read IO write memory cycle via the controller FSM.
CTRL_STATE <= CTRLCMD_ReadIOWrite;
FSM_STATE <= ReadIOCycle;
when X"50" =>
-- Register a Halt state.
FSM_STATE <= HaltCycle;
when X"51" =>
-- Initiate a refresh cycle.
FSM_STATE <= RefreshCycle_3;
when X"E0" =>
-- Initiate a Halt Cycle.
FSM_STATE <= HaltCycle;
-- Set the Refresh Address register.
when X"E1" =>
REFRESH_ADDR <= CPU_DATA_OUT;
-- Set the Interrupt Page Address Register.
when X"E2" =>
IPAR <= CPU_DATA_OUT;
when others =>
end case;
-- Toggle the processing flag to negate the new data flag. Used to indicate device is busy.
if(SPI_NEW_DATA /= SPI_PROCESSING) then
SPI_PROCESSING<= not SPI_PROCESSING;
end if;
-- Clear new data flag ready for next cmd/param transfer.
NEW_SPI_DATA <= '0';
-- FSM Status bit. When processing a command it is set, cleared when idle. Used by SOM to determine command completion.
FSM_STATUS <= '1';
end if;
when CTRLCMD_ReadIOWrite =>
if(NEW_SPI_DATA = '1' and FSM_STATE = IdleCycle and Z80_CLK_RE = '1') then
NEW_SPI_DATA <= '0';
CPU_DATA_EN <= '0';
Z80_IORQni <= '1';
Z80_RDni <= '1';
Z80_RFSHni <= '1';
CPU_ADDR <= SPI_CPU_ADDR;
CPU_DATA_OUT <= CPU_DATA_IN;
FSM_STATE <= WriteCycle;
CTRL_STATE <= CTRLCMD_ReadIOWrite_1;
end if;
when CTRLCMD_ReadIOWrite_1 =>
if(FSM_STATE = WriteCycle_31) then
CTRL_STATE <= CTRLCMD_Idle;
end if;
when others =>
CTRL_STATE <= CTRLCMD_Idle;
end case;
--------------------------------------------------------------------------------------------
-- Z80 Finite State Machine.
--------------------------------------------------------------------------------------------
-- On each Z80 edge we advance the Z80 FSM to recreate the Z80 external signal transactions.
if(Z80_CLK_TGL = '1') then
-- The FSM advances to the next stage on each Z80 edge unless in Idle state.
@@ -704,7 +819,7 @@ begin
when IdleCycle =>
CPU_LAST_T_STATE <= '1';
-- FSM_STATE <= IdleCycle;
FSM_STATUS <= '0';
-----------------------------
-- Z80 Fetch Cycle.
@@ -727,7 +842,7 @@ begin
when FetchCycle_30 =>
-- To meet the timing diagrams, just after Rising edge on T3 clear signals. Data wont be available until
-- a short period before the falling edge of T3 (could be an MZ-2000 design restriction or the Z80 timing diagrams are a bit out).
-- a short period before the falling edge of T3.
FSM_STATE <= RefreshCycle;
-----------------------------
@@ -736,18 +851,18 @@ begin
when RefreshCycle =>
-- Latch data from mainboard.
CPU_DATA_IN <= Z80_DATA;
FSM_STATUS <= '0';
Z80_RFSHni <= '0';
when RefreshCycle_11 =>
-- Falling edge of T3 activates the MREQ line.
Z80_MREQni <= '0';
FSM_STATUS <= '0';
when RefreshCycle_20 =>
when RefreshCycle_21 =>
Z80_MREQni <= '1';
REFRESH_ADDR(6 downto 0) <= REFRESH_ADDR(6 downto 0) + 1;
REFRESH_ADDR <= REFRESH_ADDR + 1;
FSM_STATE <= IdleCycle;
when RefreshCycle_3 =>
@@ -769,7 +884,7 @@ begin
when WriteCycle_21 =>
Z80_WRni <= '0';
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
FSM_STATE <= WriteCycle_20;
FSM_STATE <= WriteCycle_20;
end if;
when WriteCycle_30 =>
@@ -794,7 +909,7 @@ begin
when ReadCycle_21 =>
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
FSM_STATE <= ReadCycle_20;
FSM_STATE <= ReadCycle_20;
end if;
when ReadCycle_30 =>
@@ -805,7 +920,6 @@ begin
FSM_STATUS <= '0';
FSM_STATE <= IdleCycle;
-----------------------------
-- Z80 IO Write Cycle.
-----------------------------
@@ -825,7 +939,7 @@ begin
when WriteIOCycle_31 =>
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
FSM_STATE <= WriteIOCycle_20;
FSM_STATE <= WriteIOCycle_30;
end if;
when WriteIOCycle_40 =>
@@ -854,7 +968,7 @@ begin
when ReadIOCycle_31 =>
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
FSM_STATE <= ReadIOCycle_20;
FSM_STATE <= ReadIOCycle_30;
end if;
when ReadIOCycle_40 =>
@@ -902,8 +1016,6 @@ begin
Z80_DATA <= CPU_DATA_OUT when Z80_BUSRQ_ACKni = '1' and CPU_DATA_EN = '1'
else
(others => 'Z');
-- Z80_DATAi <= Z80_DATA when Z80_RDn = '0'
-- else (others => '1');
Z80_RDn <= Z80_RDni when Z80_BUSRQ_ACKni = '1'
else 'Z';
Z80_WRn <= Z80_WRni when Z80_BUSRQ_ACKni = '1'
@@ -944,7 +1056,7 @@ begin
-- Signal mirrors.
VSOM_READY <= '0' when FSM_STATUS='1' or SPI_NEW_DATA /= SPI_PROCESSING
else '1'; -- FSM Ready (1), Busy (0)
else '1'; -- FSM Ready (1), Busy (0)
VSOM_LTSTATE <= '1' when CPU_LAST_T_STATE = '1' -- Last T-State in current cycle.
else '0';
VSOM_BUSRQ <= not Z80_BUSRQn; -- Host device requesting Z80 Bus.
@@ -981,5 +1093,9 @@ begin
-- DAC clocks.
--VGA_PXL_CLK <= CLK_50M;
MONO_PXL_CLK <= VGA_PXL_CLK;
-- Currently unassigned.
VGA_COLR <= '0';
MONO_RSV <= '0';
end architecture;

View File

@@ -127,10 +127,10 @@ set_location_assignment PIN_21 -to VSOM_RSV[1]
# SOM Control Signals
# ===================
set_location_assignment PIN_28 -to VSOM_READY
set_location_assignment PIN_18 -to VSOM_LTSTATE
set_location_assignment PIN_19 -to VSOM_LTSTATE
set_location_assignment PIN_27 -to VSOM_BUSRQ
set_location_assignment PIN_26 -to VSOM_BUSACK
set_location_assignment PIN_19 -to VSOM_INT
set_location_assignment PIN_18 -to VSOM_INT
set_location_assignment PIN_22 -to VSOM_NMI
set_location_assignment PIN_25 -to VSOM_WAIT
set_location_assignment PIN_23 -to VSOM_RESET

File diff suppressed because it is too large Load Diff

View File

@@ -127,10 +127,10 @@ set_location_assignment PIN_21 -to VSOM_RSV[1]
# SOM Control Signals
# ===================
set_location_assignment PIN_28 -to VSOM_READY
set_location_assignment PIN_18 -to VSOM_LTSTATE
set_location_assignment PIN_19 -to VSOM_LTSTATE
set_location_assignment PIN_27 -to VSOM_BUSRQ
set_location_assignment PIN_26 -to VSOM_BUSACK
set_location_assignment PIN_19 -to VSOM_INT
set_location_assignment PIN_18 -to VSOM_INT
set_location_assignment PIN_22 -to VSOM_NMI
set_location_assignment PIN_25 -to VSOM_WAIT
set_location_assignment PIN_23 -to VSOM_RESET

View File

@@ -9,9 +9,13 @@
-- for the MZ-80A.
--
-- Credits:
-- Copyright: (c) 2018-22 Philip Smart <philip.smart@net2net.org>
-- Copyright: (c) 2018-23 Philip Smart <philip.smart@net2net.org>
--
-- History: Nov 2022 - Initial write for the MZ-2000, adaption to MZ-80A underway.
-- History: Nov 2022 v1.0 - Initial write for the MZ-2000, adaption to the MZ-80A.
-- Feb 2023 v1.1 - Updates, after numerous tests to try and speed up the Z80 transaction
-- from SSD202 issuing a command to data being returned. Source now
-- different to the MZ-700/MZ-2000 so will need back porting.
-- Apr 2023 v1.2 - Updated from the PCW8256 development.
--
---------------------------------------------------------------------------------------------------------
-- This source file is free software: you can redistribute it and-or modify
@@ -128,7 +132,7 @@ end entity;
architecture rtl of cpld512 is
-- Finite State Machine states.
-- Z80 Finite State Machine states.
type SOMFSMState is
(
IdleCycle,
@@ -174,6 +178,14 @@ architecture rtl of cpld512 is
BusReqCycle
);
-- Controller FSM states.
type CTRLFSMState is
(
CTRLCMD_Idle,
CTRLCMD_ReadIOWrite,
CTRLCMD_ReadIOWrite_1
);
-- CPU Interface internal signals.
signal Z80_BUSRQni : std_logic;
signal Z80_INTni : std_logic;
@@ -185,7 +197,6 @@ architecture rtl of cpld512 is
signal Z80_HALTni : std_logic;
signal Z80_M1ni : std_logic;
signal Z80_RFSHni : std_logic;
signal Z80_DATAi : std_logic_vector(7 downto 0);
signal Z80_BUSRQ_ACKni : std_logic;
-- Internal CPU state control.
@@ -203,14 +214,15 @@ architecture rtl of cpld512 is
-- Refresh control.
signal FSM_STATE : SOMFSMState := IdleCycle;
signal NEW_SPI_CMD : std_logic := '0';
signal CTRL_STATE : CTRLFSMState := CTRLCMD_Idle;
signal NEW_SPI_DATA : std_logic := '0';
signal VCPU_CS_EDGE : std_logic_vector(1 downto 0) := "11";
signal AUTOREFRESH_CNT : integer range 0 to 7;
signal AUTOREFRESH_CNT : integer range 0 to 31;
signal FSM_STATUS : std_logic := '0';
signal FSM_CHECK_WAIT : std_logic := '0';
signal FSM_WAIT_ACTIVE : std_logic := '0';
signal RFSH_STATUS : std_logic := '0';
signal REFRESH_ADDR : std_logic_vector(7 downto 0);
signal REFRESH_ADDR : std_logic_vector(6 downto 0);
signal IPAR : std_logic_vector(7 downto 0);
signal AUTOREFRESH : std_logic;
@@ -229,11 +241,12 @@ architecture rtl of cpld512 is
signal SPI_RX_SREG : std_logic_vector(7 downto 0); -- RX Shift Register
signal SPI_TX_DATA : std_logic_vector(31 downto 0); -- Data to transmit.
signal SPI_RX_DATA : std_logic_vector(31 downto 0); -- Data received.
signal SPI_BIT_CNT : integer range 0 to 16; -- Count of bits tx/rx'd.
signal SPI_BIT_CNT : integer range 0 to 7; -- Count of bits tx/rx'd.
signal SPI_FRAME_CNT : integer range 0 to 4; -- Number of frames received (8bit chunks).
-- SPI Command interface.
signal SOM_CMD : std_logic_vector(7 downto 0) := (others => '0');
signal SOM_PARAM_CNT : integer range 0 to 3;
signal SPI_NEW_DATA : std_logic;
signal SPI_PROCESSING : std_logic;
signal SPI_CPU_ADDR : std_logic_vector(15 downto 0) := (others => '0');
@@ -272,7 +285,7 @@ begin
-- On the second edge, if occurring within 1 second of the first, the PM_RESET signal to the SOM is triggered, held low for 1 second,
-- forcing the SOM to reboot.
SYSRESET: process( Z80_CLKi, Z80_RESETn )
variable timer1 : integer range 0 to 354000 := 0;
variable timer1 : integer range 0 to 200000 := 0;
variable timer100 : integer range 0 to 10 := 0;
variable timerPMReset : integer range 0 to 10 := 0;
variable resetCount : integer range 0 to 3 := 0;
@@ -308,7 +321,7 @@ begin
end if;
-- 100ms interval.
if(timer1 = 354000) then
if(timer1 = 200000) then
timer100 := timer100 + 1;
if(timer100 >= 10) then
@@ -337,8 +350,11 @@ begin
-- SPI Slave input. Receive command and data from the SOM.
SPI_INPUT : process(VSOM_SPI_CLK)
begin
-- Chip Select inactive, disable process and reset control flags.
if(VSOM_SPI_CSn = '1') then
-- SPI_CLK_POLARITY='0' => falling edge; SPI_CLK_POLARITY='1' => rising edge
if(VSOM_SPI_CLK'event and VSOM_SPI_CLK = SPI_CLK_POLARITY) then
elsif(VSOM_SPI_CLK'event and VSOM_SPI_CLK = SPI_CLK_POLARITY) then
if(VSOM_SPI_CSn = '0') then
SPI_RX_SREG <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
@@ -353,7 +369,7 @@ begin
elsif(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 3 and SPI_BIT_CNT = 0) then
SPI_RX_DATA(23 downto 16) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
elsif(SPI_SHIFT_EN = '1' and SPI_FRAME_CNT = 4 and SPI_BIT_CNT = 0) then
elsif(SPI_FRAME_CNT = 4 and SPI_BIT_CNT = 0) then
SPI_RX_DATA(31 downto 24) <= SPI_RX_SREG(6 downto 0) & VSOM_SPI_MOSI;
end if;
end if;
@@ -363,18 +379,22 @@ begin
-- SPI Slave output. Return the current data set as selected by the input signals XACT.
SPI_OUTPUT : process(VSOM_SPI_CLK,VSOM_SPI_CSn,SPI_TX_DATA)
begin
-- Chip Select inactive, disable process and reset control flags.
if(VSOM_SPI_CSn = '1') then
SPI_SHIFT_EN <= '0';
SPI_BIT_CNT <= 15;
SPI_BIT_CNT <= 7;
-- SPI_CLK_POLARITY='0' => falling edge; SPI_CLK_POLARITY='1' => risinge edge
elsif(VSOM_SPI_CLK'event and VSOM_SPI_CLK = not SPI_CLK_POLARITY) then
-- Each clock reset the shift enable and done flag in preparation for the next cycle.
SPI_SHIFT_EN <= '1';
-- Bit count decrements to detect when last bit of byte is sent.
if(SPI_BIT_CNT > 0) then
SPI_BIT_CNT <= SPI_BIT_CNT - 1;
end if;
-- Shift out the next bit.
VSOM_SPI_MISO <= SPI_TX_SREG(6);
SPI_TX_SREG <= SPI_TX_SREG(5 downto 0) & '0';
@@ -389,6 +409,7 @@ begin
SPI_FRAME_CNT<= 1;
VSOM_SPI_MISO<= SPI_TX_DATA(7);
SPI_TX_SREG <= SPI_TX_DATA(6 downto 0);
-- Increment frame count for each word received. We handle 8bit (1 frame), 16bit (2 frames) or 32bit (4 frames) reception.
elsif(SPI_FRAME_CNT = 1) then
SPI_FRAME_CNT<= 2;
VSOM_SPI_MISO<= SPI_TX_DATA(15);
@@ -397,13 +418,14 @@ begin
SPI_FRAME_CNT<= 3;
VSOM_SPI_MISO<= SPI_TX_DATA(23);
SPI_TX_SREG <= SPI_TX_DATA(22 downto 16);
else
elsif(SPI_FRAME_CNT = 3) then
-- Increment frame count for each word received. We handle 8bit (1 frame), 16bit (2 frames) or 32bit (4 frames) reception.
SPI_FRAME_CNT<= 4;
VSOM_SPI_MISO<= SPI_TX_DATA(31);
SPI_TX_SREG <= SPI_TX_DATA(30 downto 24);
else
SPI_FRAME_CNT<= 0;
end if;
SPI_BIT_CNT <= 7;
end if;
end if;
@@ -421,6 +443,7 @@ begin
AUTOREFRESH <= '0';
SPI_LOOPBACK_TEST <= '0';
SOM_CMD <= (others => '0');
SOM_PARAM_CNT <= 0;
SPI_CPU_ADDR <= (others => '0');
SPI_NEW_DATA <= '0';
@@ -429,6 +452,7 @@ begin
-- for 8bit, 16bit and 32bit transmissions.
-- The packet is formatted as follows:
--
-- < SPI_CPU_ADDR > < SPI_CPU_DATA >< SOM_CMD>
-- < SPI_FRAME_CNT=4 >< SPI_FRAME=3 > < SPI_FRAME_CNT=2 >< SPI_FRAME_CNT=1>
-- < 16bit Z80 Address > < Z80 Data ><Command=00..80>
-- 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
@@ -438,66 +462,110 @@ begin
--
elsif(VSOM_SPI_CSn'event and VSOM_SPI_CSn = '1') then
-- Command is always located in the upper byte of frame 1.
SOM_CMD <= SPI_RX_DATA(7 downto 0);
-- If active, decrement parameter count. Parameters sent after a command are not considered as commands.
if(SOM_PARAM_CNT > 0) then
SOM_PARAM_CNT <= SOM_PARAM_CNT - 1;
end if;
-- Toggle flag to indicate new data arrived.
SPI_NEW_DATA <= not SPI_NEW_DATA;
-- Process if command, store parameters.
if(SOM_PARAM_CNT = 0) then
-- Command is always located in the upper byte of frame 1.
SOM_CMD <= SPI_RX_DATA(7 downto 0);
-- Process the command. Some commands require the FSM, others can be serviced immediately.
case SPI_RX_DATA(7 downto 0) is
-- Toggle flag to indicate new data arrived.
SPI_NEW_DATA <= not SPI_NEW_DATA;
-- Z80XACT(0..15): Setup data and address as provided then execute FSM.
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" | -- Fetch
X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" | -- Write
X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" | -- Read
X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" | -- WriteIO
X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" | -- ReadIO
X"38" | X"39" | X"3A" | X"3B" | X"3C" | X"3D" | X"3E" | X"3F" | --
X"40" | X"41" | X"42" | X"43" | X"44" | X"45" | X"46" | X"47" | --
X"48" | X"49" | X"4A" | X"4B" | X"4C" | X"4D" | X"4E" | X"4F" =>
-- Process the command. Some commands require the FSM, others can be serviced immediately.
case SPI_RX_DATA(7 downto 0) is
-- Direct address set.
if(SPI_FRAME_CNT = 4) then
SPI_CPU_ADDR <= SPI_RX_DATA(31 downto 16);
else
-- if(SPI_CPU_ADDR >= X"D010" and SPI_CPU_ADDR < X"D020") then
-- SPI_CPU_ADDR <= std_logic_vector(X"D020" + unsigned(SPI_RX_DATA(2 downto 0)));
-- else
SPI_CPU_ADDR <= std_logic_vector(unsigned(SPI_CPU_ADDR) + unsigned(SPI_RX_DATA(2 downto 0)));
-- end if;
end if;
-- Z80XACT(0..15): Setup data and address as provided then execute FSM.
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" | -- Fetch
X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" | -- Write
X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" | -- Read
X"48" | X"49" | X"4A" | X"4B" | X"4C" | X"4D" | X"4E" | X"4F" =>
if(SPI_FRAME_CNT > 1) then
SPI_CPU_DATA <= SPI_RX_DATA(15 downto 8);
end if;
-- Direct address set.
if(SPI_FRAME_CNT = 4) then
SPI_CPU_ADDR <= SPI_RX_DATA(31 downto 16);
else
SPI_CPU_ADDR <= std_logic_vector(unsigned(SPI_CPU_ADDR) + unsigned(SPI_RX_DATA(2 downto 0)));
end if;
-- SETSIGSET1: Set control lines directly.
when X"F0" =>
VIDEO_SRCi <= SPI_RX_DATA(8);
MONO_VIDEO_SRCi <= SPI_RX_DATA(9);
AUDIO_SRC_Li <= SPI_RX_DATA(10);
AUDIO_SRC_Ri <= SPI_RX_DATA(11);
VBUS_ENi <= SPI_RX_DATA(12);
VGA_BLANKn <= not SPI_RX_DATA(13);
if(SPI_FRAME_CNT > 1) then
SPI_CPU_DATA <= SPI_RX_DATA(15 downto 8);
end if;
-- Enable auto refresh DRAM cycle.
when X"F1" =>
AUTOREFRESH <= '1';
when X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" => -- WriteIO
-- Disable auto refresh DRAM cycle.
when X"F2" =>
AUTOREFRESH <= '0';
-- Direct address set.
if(SPI_FRAME_CNT = 4) then
SPI_CPU_ADDR <= SPI_RX_DATA(31 downto 16);
else
SPI_CPU_ADDR <= X"000" & '0' & std_logic_vector(unsigned(SPI_RX_DATA(2 downto 0)));
end if;
-- SETLOOPBACK: Enable loopback test mode.
when X"FE" =>
SPI_LOOPBACK_TEST<= '1';
if(SPI_FRAME_CNT > 1) then
SPI_CPU_DATA <= SPI_RX_DATA(15 downto 8);
end if;
-- No action, called to retrieve status.
when X"00" | X"FF" =>
when X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" | -- ReadIO
X"38" | X"39" | X"3A" | X"3B" | X"3C" | X"3D" | X"3E" | X"3F" => -- ReadIO-Write
when others =>
end case;
-- Direct address set.
if(SPI_FRAME_CNT = 4) then
SPI_CPU_ADDR <= SPI_RX_DATA(31 downto 16);
elsif(SPI_FRAME_CNT = 2) then
SPI_CPU_ADDR <= X"00" & SPI_RX_DATA(15 downto 8);
else
SPI_CPU_ADDR <= X"000" & '0' & std_logic_vector(unsigned(SPI_RX_DATA(2 downto 0)));
end if;
if(SPI_FRAME_CNT > 1) then
SPI_CPU_DATA <= SPI_RX_DATA(15 downto 8);
end if;
-- ReadIO-Write, Read-WriteIO commands require target address, so indicate parameter needed.
if(SPI_RX_DATA(7 downto 0) >= X"38" and SPI_RX_DATA(7 downto 0) < X"40") then
SOM_PARAM_CNT <= 1;
end if;
-- SETSIGSET1: Set control lines directly.
when X"F0" =>
VIDEO_SRCi <= SPI_RX_DATA(8);
MONO_VIDEO_SRCi <= SPI_RX_DATA(9);
AUDIO_SRC_Li <= SPI_RX_DATA(10);
AUDIO_SRC_Ri <= SPI_RX_DATA(11);
VBUS_ENi <= SPI_RX_DATA(12);
VGA_BLANKn <= not SPI_RX_DATA(13);
-- Enable auto refresh DRAM cycle.
when X"F1" =>
AUTOREFRESH <= '1';
-- Disable auto refresh DRAM cycle.
when X"F2" =>
AUTOREFRESH <= '0';
-- SETLOOPBACK: Enable loopback test mode.
when X"FE" =>
SPI_LOOPBACK_TEST<= '1';
-- No action, called to retrieve status.
when X"00" | X"FF" =>
when others =>
end case;
else
-- Store parameter depending on number of frames, either ADDR+DATA, ADDR or DATA.
if(SPI_FRAME_CNT = 4) then
SPI_CPU_ADDR <= SPI_RX_DATA(31 downto 16);
SPI_CPU_DATA <= SPI_RX_DATA(15 downto 8);
elsif(SPI_FRAME_CNT = 2) then
SPI_CPU_ADDR <= SPI_RX_DATA(15 downto 0);
else
SPI_CPU_DATA <= SPI_RX_DATA(7 downto 0);
end if;
end if;
end if;
end process;
@@ -558,9 +626,9 @@ begin
CPU_DATA_EN <= '0';
CPU_DATA_IN <= (others => '0');
REFRESH_ADDR <= (others => '0');
AUTOREFRESH_CNT <= 7;
AUTOREFRESH_CNT <= 31;
IPAR <= (others => '0');
NEW_SPI_CMD <= '0';
NEW_SPI_DATA <= '0';
VCPU_CS_EDGE <= "11";
SPI_PROCESSING <= '0';
@@ -577,98 +645,12 @@ begin
-- New command, set flag as the signal is only 1 clock wide.
if(SPI_LOOPBACK_TEST = '0' and VSOM_SPI_CSn = '1' and VCPU_CS_EDGE = "01") then
NEW_SPI_CMD <= '1';
NEW_SPI_DATA <= '1';
end if;
-- Whenever we return to Idle or just prior to Refresh from a Fetch cycle set all control signals to default.
if(FSM_STATE = IdleCycle or FSM_STATE = RefreshCycle) then
CPU_DATA_EN <= '0';
Z80_MREQni <= '1';
Z80_IORQni <= '1';
Z80_RDni <= '1';
Z80_WRni <= '1';
Z80_M1ni <= '1';
FSM_STATUS <= '0';
Z80_RFSHni <= '1';
-- Auto DRAM refresh cycles. When enabled, every 7 host clock cycles, a 2 cycle refresh period commences.
-- This will be overriden if the SPI receives a new command.
--
if AUTOREFRESH = '1' and FSM_STATE = IdleCycle then
AUTOREFRESH_CNT <= AUTOREFRESH_CNT - 1;
if(AUTOREFRESH_CNT = 0) then
FSM_STATE <= RefreshCycle_3;
end if;
end if;
end if;
-- If new command has been given and the FSM enters idle state, load up new command for processing.
if(NEW_SPI_CMD = '1' and FSM_STATE = IdleCycle and Z80_CLK_RE = '1') then
NEW_SPI_CMD <= '0';
-- Store new address and data for this command.
CPU_ADDR <= SPI_CPU_ADDR;
if(SPI_CPU_DATA /= CPU_DATA_OUT) then
CPU_DATA_OUT <= SPI_CPU_DATA;
end if;
-- Process the SOM command. The SPI_REGISTER executes non FSM commands and stores FSM
-- data prior to this execution block, which fires 1 cycle later on the same control clock.
-- If the command is not for the FSM then the READY mechanism is held for one
-- further cycle before going inactive.
case SOM_CMD is
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" =>
-- Initiate a Fetch Cycle.
FSM_STATE <= FetchCycle;
when X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" =>
-- Set the Z80 data bus value and initiate a Write Cycle.
FSM_STATE <= WriteCycle;
when X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" =>
-- Initiate a Read Cycle.
FSM_STATE <= ReadCycle;
when X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" =>
-- Set the Z80 data bus value and initiate an IO Write Cycle.
-- The SOM should set 15:8 to the B register value.
FSM_STATE <= WriteIOCycle;
when X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" =>
-- Initiate a Read IO Cycle.
FSM_STATE <= ReadIOCycle;
when X"50" =>
-- Register a Halt state.
FSM_STATE <= HaltCycle;
when X"51" =>
-- Initiate a refresh cycle.
FSM_STATE <= RefreshCycle_3;
when X"E0" =>
-- Initiate a Halt Cycle.
FSM_STATE <= HaltCycle;
-- Set the Refresh Address register.
when X"E1" =>
REFRESH_ADDR <= CPU_DATA_OUT;
-- Set the Interrupt Page Address Register.
when X"E2" =>
IPAR <= CPU_DATA_OUT;
when others =>
end case;
-- Toggle the processing flag to negate the new data flag. Used to indicate device is busy.
if(SPI_NEW_DATA /= SPI_PROCESSING) then
SPI_PROCESSING <= not SPI_PROCESSING;
end if;
-- FSM Status bit. When processing a command it is set, cleared when idle. Used by SOM to determine command completion.
FSM_STATUS <= '1';
-- Decrement refresh counter on each Z80 cycle, thus when idle and time expired, a refresh can be performed within parameters (256 cycles in 4ms).
if(AUTOREFRESH = '1' and AUTOREFRESH_CNT /= 0 and Z80_CLK_RE = '1') then
AUTOREFRESH_CNT <= AUTOREFRESH_CNT - 1;
end if;
-- Refresh status bit. Indicates a Refresh cycle is under way.
@@ -683,7 +665,143 @@ begin
FSM_WAIT_ACTIVE <= '1';
end if;
-- On each Z80 edge we advance the FSM to recreate the Z80 external signal transactions.
-- Whenever we return to Idle or just prior to Refresh from a Fetch cycle set all control signals to default.
if((FSM_STATE = IdleCycle or FSM_STATE = RefreshCycle) and Z80_CLK_RE = '1') then
CPU_DATA_EN <= '0';
Z80_MREQni <= '1';
Z80_IORQni <= '1';
Z80_RDni <= '1';
Z80_WRni <= '1';
Z80_M1ni <= '1';
FSM_STATUS <= '0';
Z80_RFSHni <= '1';
-- Auto DRAM refresh cycles. When enabled, every 15.6us a refresh period commences.
-- This period may be extended if the SPI receives a new command.
--
if AUTOREFRESH = '1' and FSM_STATE = IdleCycle then
if(AUTOREFRESH_CNT = 0) then
FSM_STATE <= RefreshCycle_3;
FSM_STATUS<= '1';
-- 4116 DRAM = 128 cycles in 2ms.
AUTOREFRESH_CNT <= 31;
end if;
end if;
end if;
--------------------------------------------------------------------------------------------
-- CPLD Macro Command Finite State Machine.
--------------------------------------------------------------------------------------------
-- Controller state machine.
-- When idle, accept and process SPI commands which can lead to a controller macro command.
case CTRL_STATE is
when CTRLCMD_Idle =>
-- If new command has been given and the FSM enters idle state, load up new command for processing.
if(NEW_SPI_DATA = '1' and FSM_STATE = IdleCycle and Z80_CLK_RE = '1') then
-- Store new address and data for this command.
if(NEW_SPI_DATA = '1') then
CPU_ADDR <= SPI_CPU_ADDR;
CPU_DATA_OUT <= SPI_CPU_DATA;
end if;
-- Process the SOM command. The SPI_REGISTER executes non FSM commands and stores FSM
-- data prior to this execution block, which fires 1 cycle later on the same control clock.
-- If the command is not for the FSM then the READY mechanism is held for one
-- further cycle before going inactive.
case SOM_CMD is
when X"10" | X"11" | X"12" | X"13" | X"14" | X"15" | X"16" | X"17" =>
-- Initiate a Fetch Cycle.
FSM_STATE <= FetchCycle;
when X"18" | X"19" | X"1A" | X"1B" | X"1C" | X"1D" | X"1E" | X"1F" =>
-- Set the Z80 data bus value and initiate a Write Cycle.
FSM_STATE <= WriteCycle;
when X"20" | X"21" | X"22" | X"23" | X"24" | X"25" | X"26" | X"27" =>
-- Initiate a Read Cycle.
FSM_STATE <= ReadCycle;
when X"28" | X"29" | X"2A" | X"2B" | X"2C" | X"2D" | X"2E" | X"2F" =>
-- Set the Z80 data bus value and initiate an IO Write Cycle.
-- The SOM should set 15:8 to the B register value.
FSM_STATE <= WriteIOCycle;
when X"30" | X"31" | X"32" | X"33" | X"34" | X"35" | X"36" | X"37" =>
-- Initiate a Read IO Cycle.
FSM_STATE <= ReadIOCycle;
when X"38" | X"39" | X"3A" | X"3B" | X"3C" | X"3D" | X"3E" | X"3F" =>
-- Initiate a read IO write memory cycle via the controller FSM.
CTRL_STATE <= CTRLCMD_ReadIOWrite;
FSM_STATE <= ReadIOCycle;
when X"50" =>
-- Register a Halt state.
FSM_STATE <= HaltCycle;
when X"51" =>
-- Initiate a refresh cycle.
FSM_STATE <= RefreshCycle_3;
when X"E0" =>
-- Initiate a Halt Cycle.
FSM_STATE <= HaltCycle;
-- Set the Refresh Address register.
when X"E1" =>
REFRESH_ADDR <= CPU_DATA_OUT(6 downto 0);
-- Set the Interrupt Page Address Register.
when X"E2" =>
IPAR <= CPU_DATA_OUT;
when others =>
end case;
-- Toggle the processing flag to negate the new data flag. Used to indicate device is busy.
if(SPI_NEW_DATA /= SPI_PROCESSING) then
SPI_PROCESSING<= not SPI_PROCESSING;
end if;
-- Clear new data flag ready for next cmd/param transfer.
NEW_SPI_DATA <= '0';
-- FSM Status bit. When processing a command it is set, cleared when idle. Used by SOM to determine command completion.
FSM_STATUS <= '1';
end if;
when CTRLCMD_ReadIOWrite =>
if(NEW_SPI_DATA = '1' and FSM_STATE = IdleCycle and Z80_CLK_RE = '1') then
NEW_SPI_DATA <= '0';
CPU_DATA_EN <= '0';
Z80_IORQni <= '1';
Z80_RDni <= '1';
Z80_RFSHni <= '1';
CPU_ADDR <= SPI_CPU_ADDR;
CPU_DATA_OUT <= CPU_DATA_IN;
FSM_STATE <= WriteCycle;
CTRL_STATE <= CTRLCMD_ReadIOWrite_1;
end if;
when CTRLCMD_ReadIOWrite_1 =>
if(FSM_STATE = WriteCycle_31) then
CTRL_STATE <= CTRLCMD_Idle;
end if;
when others =>
CTRL_STATE <= CTRLCMD_Idle;
end case;
--------------------------------------------------------------------------------------------
-- Z80 Finite State Machine.
--------------------------------------------------------------------------------------------
-- On each Z80 edge we advance the Z80 FSM to recreate the Z80 external signal transactions.
if(Z80_CLK_TGL = '1') then
-- The FSM advances to the next stage on each Z80 edge unless in Idle state.
@@ -701,7 +819,7 @@ begin
when IdleCycle =>
CPU_LAST_T_STATE <= '1';
-- FSM_STATE <= IdleCycle;
FSM_STATUS <= '0';
-----------------------------
-- Z80 Fetch Cycle.
@@ -724,7 +842,7 @@ begin
when FetchCycle_30 =>
-- To meet the timing diagrams, just after Rising edge on T3 clear signals. Data wont be available until
-- a short period before the falling edge of T3 (could be an MZ-80A design restriction or the Z80 timing diagrams are a bit out).
-- a short period before the falling edge of T3.
FSM_STATE <= RefreshCycle;
-----------------------------
@@ -733,18 +851,18 @@ begin
when RefreshCycle =>
-- Latch data from mainboard.
CPU_DATA_IN <= Z80_DATA;
FSM_STATUS <= '0';
Z80_RFSHni <= '0';
when RefreshCycle_11 =>
-- Falling edge of T3 activates the MREQ line.
Z80_MREQni <= '0';
FSM_STATUS <= '0';
when RefreshCycle_20 =>
when RefreshCycle_21 =>
Z80_MREQni <= '1';
REFRESH_ADDR(6 downto 0) <= REFRESH_ADDR(6 downto 0) + 1;
REFRESH_ADDR <= REFRESH_ADDR + 1;
FSM_STATE <= IdleCycle;
when RefreshCycle_3 =>
@@ -766,7 +884,7 @@ begin
when WriteCycle_21 =>
Z80_WRni <= '0';
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
FSM_STATE <= WriteCycle_20;
FSM_STATE <= WriteCycle_20;
end if;
when WriteCycle_30 =>
@@ -791,7 +909,7 @@ begin
when ReadCycle_21 =>
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
FSM_STATE <= ReadCycle_20;
FSM_STATE <= ReadCycle_20;
end if;
when ReadCycle_30 =>
@@ -802,7 +920,6 @@ begin
FSM_STATUS <= '0';
FSM_STATE <= IdleCycle;
-----------------------------
-- Z80 IO Write Cycle.
-----------------------------
@@ -822,7 +939,7 @@ begin
when WriteIOCycle_31 =>
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
FSM_STATE <= WriteIOCycle_20;
FSM_STATE <= WriteIOCycle_30;
end if;
when WriteIOCycle_40 =>
@@ -851,7 +968,7 @@ begin
when ReadIOCycle_31 =>
if(Z80_WAITn = '0' or FSM_WAIT_ACTIVE = '1') then
FSM_STATE <= ReadIOCycle_20;
FSM_STATE <= ReadIOCycle_30;
end if;
when ReadIOCycle_40 =>
@@ -891,7 +1008,7 @@ begin
Z80_CLKi <= not Z80_CLK;
-- CPU Interface tri-state control based on acknowledged bus request.
Z80_ADDR <= IPAR & REFRESH_ADDR when Z80_RFSHni = '0'
Z80_ADDR <= IPAR & '0' & REFRESH_ADDR when Z80_RFSHni = '0'
else
CPU_ADDR when Z80_BUSRQ_ACKni = '1'
else
@@ -899,8 +1016,6 @@ begin
Z80_DATA <= CPU_DATA_OUT when Z80_BUSRQ_ACKni = '1' and CPU_DATA_EN = '1'
else
(others => 'Z');
-- Z80_DATAi <= Z80_DATA when Z80_RDn = '0'
-- else (others => '1');
Z80_RDn <= Z80_RDni when Z80_BUSRQ_ACKni = '1'
else 'Z';
Z80_WRn <= Z80_WRni when Z80_BUSRQ_ACKni = '1'
@@ -941,7 +1056,7 @@ begin
-- Signal mirrors.
VSOM_READY <= '0' when FSM_STATUS='1' or SPI_NEW_DATA /= SPI_PROCESSING
else '1'; -- FSM Ready (1), Busy (0)
else '1'; -- FSM Ready (1), Busy (0)
VSOM_LTSTATE <= '1' when CPU_LAST_T_STATE = '1' -- Last T-State in current cycle.
else '0';
VSOM_BUSRQ <= not Z80_BUSRQn; -- Host device requesting Z80 Bus.
@@ -978,5 +1093,9 @@ begin
-- DAC clocks.
--VGA_PXL_CLK <= CLK_50M;
MONO_PXL_CLK <= VGA_PXL_CLK;
-- Currently unassigned.
VGA_COLR <= '0';
MONO_RSV <= '0';
end architecture;

View File

@@ -10,9 +10,9 @@
-- project which targets the MZ-80A host.
--
-- Credits:
-- Copyright: (c) 2018-22 Philip Smart <philip.smart@net2net.org>
-- Copyright: (c) 2018-23 Philip Smart <philip.smart@net2net.org>
--
-- History: Nov 2022 - Snapshot taken from the MZ-2000 version of the tzpuFusionX source.
-- History: Nov 2022 v1.0 - Snapshot taken from the MZ-2000 version of the tzpuFusionX source.
--
---------------------------------------------------------------------------------------------------------
-- This source file is free software: you can redistribute it and-or modify

View File

@@ -9,9 +9,9 @@
-- which targets the MZ-80A host.
--
-- Credits:
-- Copyright: (c) 2018-22 Philip Smart <philip.smart@net2net.org>
-- Copyright: (c) 2018-23 Philip Smart <philip.smart@net2net.org>
--
-- History: Nov 2022 - Snapshot taken from the MZ-2000 version of the tzpuFusionX source.
-- History: Nov 2022 v1.0 - Snapshot taken from the MZ-2000 version of the tzpuFusionX source.
--
---------------------------------------------------------------------------------------------------------
-- This source file is free software: you can redistribute it and-or modify

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,227 @@
---------------------------------------------------------------------------------------------------------
--
-- Name: tzpuFusionX_Toplevel.vhd
-- Version: Amstrad PCW-8256
-- Created: Mar 2023
-- Author(s): Philip Smart
-- Description: tzpuFusionX CPLD Top Level module.
--
-- This module contains the basic pin definition of the CPLD<->logic needed in the
-- project which targets the MZ-80A host.
--
-- Credits:
-- Copyright: (c) 2018-23 Philip Smart <philip.smart@net2net.org>
--
-- History: Nov 2022 v1.0 - Initial write for the MZ-2000, adaption to the MZ-80A.
-- Feb 2023 v1.1 - Updates, after numerous tests to try and speed up the Z80 transaction
-- from SSD202 issuing a command to data being returned. Source now
-- different to the MZ-700/MZ-2000 so will need back porting.
-- Mar 2023 v1.0 - Snapshot taken from MZ-80A source for the Amstrad PCW-8256 version.
-- Version reset to v1.0 for the Amstrad.
--
---------------------------------------------------------------------------------------------------------
-- This source file is free software: you can redistribute it and-or modify
-- it under the terms of the GNU General Public License as published
-- by the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This source file is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- along with this program. If not, see <http:--www.gnu.org-licenses->.
---------------------------------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.tzpuFusionX_pkg.all;
library altera;
use altera.altera_syn_attributes.all;
entity tzpuFusionX_PCW8256 is
port (
-- Z80 Address Bus
Z80_ADDR : inout std_logic_vector(15 downto 0);
-- Z80 Data Bus
Z80_DATA : inout std_logic_vector(7 downto 0);
-- Z80 Control signals.
Z80_BUSRQn : in std_logic;
Z80_BUSAKn : out std_logic;
Z80_INTn : in std_logic;
Z80_IORQn : inout std_logic;
Z80_MREQn : inout std_logic;
Z80_NMIn : in std_logic;
Z80_RDn : inout std_logic;
Z80_WRn : inout std_logic;
Z80_RESETn : in std_logic; -- Host CPU Reset signal, also CPLD reset.
Z80_HALTn : out std_logic;
Z80_WAITn : in std_logic;
Z80_M1n : inout std_logic;
Z80_RFSHn : inout std_logic;
-- SOM SPI
VSOM_SPI_CSn : in std_logic; -- SPI Slave Select
VSOM_SPI_CLK : in std_logic; -- SPI Clock
VSOM_SPI_MOSI : in std_logic; -- SPI Master Output Slave Input
VSOM_SPI_MISO : out std_logic; -- SPI Master Input Slave Output
-- SOM Parallel Bus.
VSOM_DATA_OUT : out std_logic_vector(7 downto 0); -- Address/Data bus for CPLD control registers.
VSOM_HBYTE : in std_logic; -- Parallel Bus High (1)/Low (0) byte.
VSOM_READY : out std_logic; -- FSM Ready (1), Busy (0)
VSOM_LTSTATE : out std_logic; -- Last T-State in current cycle, 1 = active.
VSOM_BUSRQ : out std_logic; -- Host device requesting Z80 Bus.
VSOM_BUSACK : out std_logic; -- Host device granted Z80 Bus
VSOM_INT : out std_logic; -- Z80 INT signal
VSOM_NMI : out std_logic; -- Z80 NMI signal
VSOM_WAIT : out std_logic; -- Z80 WAIT signal
VSOM_RESET : out std_logic; -- Z80 RESET signal
VSOM_RSV : out std_logic_vector(1 downto 1); -- Reserved pins.
-- SOM Control Signals
PM_RESET : out std_logic; -- Reset SOM
-- VGA_Palette Control
VGA_R : in std_logic_vector(9 downto 7); -- Signals used for detecting blank or no video output.
VGA_G : in std_logic_vector(9 downto 7);
VGA_B : in std_logic_vector(9 downto 8);
-- VGA Control Signals
VGA_PXL_CLK : in std_logic; -- VGA Pixel clock for DAC conversion.
VGA_DISPEN : in std_logic; -- Displayed Enabled (SOM video output).
VGA_VSYNCn : in std_logic; -- SOM VSync.
VGA_HSYNCn : in std_logic; -- SOM HSync.
VGA_COLR : out std_logic; -- COLR colour carrier frequency.
VGA_CSYNCn : out std_logic; -- VGA Composite Sync.
VGA_BLANKn : out std_logic; -- VGA Blank detected.
-- CRT Control Signals
MONO_PXL_CLK : out std_logic; -- Mono CRT pixel clock for DAC conversion.
MONO_BLANKn : out std_logic; -- Mono CRT Blank (no active pixel) detection.
MONO_CSYNCn : out std_logic; -- Mono CRT composite sync.
MONO_RSV : out std_logic;
-- CRT Lower Chrominance Control
MONO_R : out std_logic_vector(2 downto 0); -- Signals to fine tune Red level of monochrome chrominance.
MONO_G : out std_logic_vector(2 downto 0); -- Signals to fine tune Green level of monochrome chrominance.
MONO_B : out std_logic_vector(2 downto 1); -- Signals to fine tune Blue level of monochrome chrominance.
-- MUX Control Signals
VIDEO_SRC : out std_logic; -- Select video source, Mainboard or SOM.
MONO_VIDEO_SRC : out std_logic; -- Select crt video source, Mainboard or SOM.
AUDIO_SRC_L : out std_logic; -- Select Audio Source Left Channel, Mainboard or SOM.
AUDIO_SRC_R : out std_logic; -- Select Audio Source Right Channel, Mainboard or SOM.
-- Mainboard Reset Signals
MB_RESETn : in std_logic; -- Motherboard Reset pressed.
MB_IPLn : in std_logic; -- Motherboard IPL pressed.
-- USB Power Control
VBUS_EN : out std_logic; -- USB Enable Power Output
-- Clocks.
Z80_CLK : in std_logic; -- Host CPU Clock
CLK_50M : in std_logic -- 50MHz oscillator.
);
END entity;
architecture rtl of tzpuFusionX_PCW8256 is
begin
cpldl512Toplevel : entity work.cpld512
generic map (
SPI_CLK_POLARITY => '0'
)
port map
(
-- Z80 Address Bus
Z80_ADDR => Z80_ADDR,
-- Z80 Data Bus
Z80_DATA => Z80_DATA,
-- Z80 Control signals.
Z80_BUSRQn => Z80_BUSRQn,
Z80_BUSAKn => Z80_BUSAKn,
Z80_INTn => Z80_INTn,
Z80_IORQn => Z80_IORQn,
Z80_MREQn => Z80_MREQn,
Z80_NMIn => Z80_NMIn,
Z80_RDn => Z80_RDn,
Z80_WRn => Z80_WRn,
Z80_RESETn => Z80_RESETn,
Z80_HALTn => Z80_HALTn,
Z80_WAITn => Z80_WAITn,
Z80_M1n => Z80_M1n,
Z80_RFSHn => Z80_RFSHn,
-- SOM SPI
VSOM_SPI_CSn => VSOM_SPI_CSn, -- SPI Slave Select
VSOM_SPI_CLK => VSOM_SPI_CLK, -- SPI Clock
VSOM_SPI_MOSI => VSOM_SPI_MOSI, -- SPI Master Output Slave Input
VSOM_SPI_MISO => VSOM_SPI_MISO, -- SPI Master Input Slave Output
-- SOM Parallel Bus.
VSOM_DATA_OUT => VSOM_DATA_OUT, -- Address/Data bus for CPLD control registers.
VSOM_HBYTE => VSOM_HBYTE, -- Parallel Bus High (1)/Low (0) byte.
VSOM_READY => VSOM_READY, -- FSM Ready (1), Busy (0)
VSOM_LTSTATE => VSOM_LTSTATE, -- Last T-State in current cycle.
VSOM_BUSRQ => VSOM_BUSRQ, -- Host device requesting Z80 Bus.
VSOM_BUSACK => VSOM_BUSACK, -- Host device granted Z80 Bus
VSOM_INT => VSOM_INT, -- Z80 INT signal
VSOM_NMI => VSOM_NMI, -- Z80 NMI signal
VSOM_WAIT => VSOM_WAIT, -- Z80 WAIT signal
VSOM_RESET => VSOM_RESET, -- Z80 RESET signal
VSOM_RSV => VSOM_RSV, -- Reserved pins.
-- SOM Control Signals
PM_RESET => PM_RESET, -- Reset SOM
-- VGA_Palette Control
VGA_R => VGA_R, -- Signals used for detecting blank or no video output.
VGA_G => VGA_G,
VGA_B => VGA_B,
-- VGA Control Signals
VGA_PXL_CLK => VGA_PXL_CLK, -- VGA Pixel clock for DAC conversion.
VGA_DISPEN => VGA_DISPEN, -- Displayed Enabled (SOM video output).
VGA_VSYNCn => VGA_VSYNCn, -- SOM VSync.
VGA_HSYNCn => VGA_HSYNCn, -- SOM HSync.
VGA_COLR => VGA_COLR, -- COLR colour carrier frequency.
VGA_CSYNCn => VGA_CSYNCn, -- VGA Composite Sync.
VGA_BLANKn => VGA_BLANKn, -- VGA Blank detected.
-- CRT Control Signals
MONO_PXL_CLK => MONO_PXL_CLK, -- Mono CRT pixel clock for DAC conversion.
MONO_BLANKn => MONO_BLANKn, -- Mono CRT Blank (no active pixel) detection.
MONO_CSYNCn => MONO_CSYNCn, -- Mono CRT composite sync.
MONO_RSV => MONO_RSV,
-- CRT Lower Chrominance Control
MONO_R => MONO_R, -- Signals to fine tune Red level of monochrome chrominance.
MONO_G => MONO_G, -- Signals to fine tune Green level of monochrome chrominance.
MONO_B => MONO_B, -- Signals to fine tune Blue level of monochrome chrominance.
-- MUX Control Signals
VIDEO_SRC => VIDEO_SRC, -- Select video source, Mainboard or SOM.
MONO_VIDEO_SRC => MONO_VIDEO_SRC, -- Select crt video source, Mainboard or SOM.
AUDIO_SRC_L => AUDIO_SRC_L, -- Select Audio Source Left Channel, Mainboard or SOM.
AUDIO_SRC_R => AUDIO_SRC_R, -- Select Audio Source Right Channel, Mainboard or SOM.
-- Mainboard Reset Signals=> MONO_R,
MB_RESETn => MB_RESETn, -- Motherboard Reset pressed.
MB_IPLn => MB_IPLn, -- Motherboard IPL pressed.
-- USB Power Control
VBUS_EN => VBUS_EN, -- USB Enable Power Output
-- Clocks.
Z80_CLK => Z80_CLK, -- Host CPU Clock
CLK_50M => CLK_50M -- 50MHz oscillator.
);
end architecture;

View File

@@ -0,0 +1,227 @@
---------------------------------------------------------------------------------------------------------
--
-- Name: tzpuFusionX_pkg.vhd
-- Created: Mar 2023
-- Author(s): Philip Smart
-- Description: tzpuFusionX CPLD configuration file.
--
-- This module contains parameters for the CPLD in the tzpuFusionX project
-- which targets the Amstrad PCW8256 host.
--
-- Credits:
-- Copyright: (c) 2018-23 Philip Smart <philip.smart@net2net.org>
--
-- History: Nov 2022 v1.0 - Initial write for the MZ-2000, adaption to the MZ-80A.
-- Feb 2023 v1.1 - Updates, after numerous tests to try and speed up the Z80 transaction
-- from SSD202 issuing a command to data being returned. Source now
-- different to the MZ-700/MZ-2000 so will need back porting.
-- Mar 2023 v1.0 - Snapshot taken from MZ-80A source for the Amstrad PCW-8256 version.
-- Version reset to v1.0 for the Amstrad.
--
---------------------------------------------------------------------------------------------------------
-- This source file is free software: you can redistribute it and-or modify
-- it under the terms of the GNU General Public License as published
-- by the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This source file is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http:--www.gnu.org-licenses->.
---------------------------------------------------------------------------------------------------------
library ieee;
library pkgs;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
package tzpuFusionX_pkg is
------------------------------------------------------------
-- Constants
------------------------------------------------------------
-- Potential logic state constants.
constant YES : std_logic := '1';
constant NO : std_logic := '0';
constant HI : std_logic := '1';
constant LO : std_logic := '0';
constant ONE : std_logic := '1';
constant ZERO : std_logic := '0';
constant HIZ : std_logic := 'Z';
-- CPLD Command instructions.
constant CPLD_CMD_RESET_HOST : integer := 1;
constant CPLD_CMD_HOLD_HOST_BUS : integer := 2;
constant CPLD_CMD_RELEASE_HOST_BUS: integer := 3;
-- Target hardware modes.
constant MODE_MZ80K : integer := 0;
constant MODE_MZ80C : integer := 1;
constant MODE_MZ1200 : integer := 2;
constant MODE_MZ80A : integer := 3;
constant MODE_MZ700 : integer := 4;
constant MODE_MZ800 : integer := 5;
constant MODE_MZ80B : integer := 6;
constant MODE_MZ2000 : integer := 7;
constant MODE_PCW8256 : integer := 8;
-- Memory management modes.
constant TZMM_ORIG : integer := 00; -- Original Sharp mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
constant TZMM_BOOT : integer := 01; -- Original mode but E800-EFFF is mapped to tranZPUter RAM so TZFS can be booted.
constant TZMM_TZFS : integer := 02; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-FFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected.
constant TZMM_TZFS2 : integer := 03; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 1.
constant TZMM_TZFS3 : integer := 04; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 2.
constant TZMM_TZFS4 : integer := 05; -- TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 3.
constant TZMM_CPM : integer := 06; -- CPM main memory configuration, all memory on the tranZPUter board, 64K block 4 selected. Special case for F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
constant TZMM_CPM2 : integer := 07; -- CPM main memory configuration, F000-FFFF are on the tranZPUter board in block 4, 0040-CFFF and E800-EFFF are in block 5, mainboard for D000-DFFF (video), E000-E800 (Memory control) selected.
-- Special case for 0000:003F (interrupt vectors) which resides in block 4, F3FE:F3FF & F7FE:F7FF (floppy disk paging vectors) which resides on the mainboard.
constant TZMM_COMPAT : integer := 08; -- Compatibility monitor mode, monitor ROM on mainboard, RAM on tranZPUter in Block 0 1000-CFFF.
constant TZMM_HOSTACCESS : integer := 09; -- Monitor ROM 0000-0FFF and Main DRAM 0x1000-0xD000, video and memory mapped I/O are on the host machine, User/Floppy ROM E800-FFFF are in tranZPUter memory.
constant TZMM_MZ700_0 : integer := 10; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the mainboard.
constant TZMM_MZ700_1 : integer := 11; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
constant TZMM_MZ700_2 : integer := 12; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
constant TZMM_MZ700_3 : integer := 13; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
constant TZMM_MZ700_4 : integer := 14; -- MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
constant TZMM_MZ800 : integer := 15; -- MZ800 Mode - Running on MZ800 hardware, configuration set according to MZ700/MZ800 mode.
constant TZMM_MZ2000 : integer := 16; -- MZ2000 Mode - Running on MZ2000 hardware, configuration set according to runtime configuration registers.
constant TZMM_FPGA : integer := 21; -- Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked.
constant TZMM_TZPUM : integer := 22; -- Everything in on mainboard, no access to tranZPUter memory.
constant TZMM_TZPU : integer := 23; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
constant TZMM_TZPU0 : integer := 24; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
constant TZMM_TZPU1 : integer := 25; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 1 is selected.
constant TZMM_TZPU2 : integer := 26; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 2 is selected.
constant TZMM_TZPU3 : integer := 27; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 3 is selected.
constant TZMM_TZPU4 : integer := 28; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 4 is selected.
constant TZMM_TZPU5 : integer := 29; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 5 is selected.
constant TZMM_TZPU6 : integer := 30; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 6 is selected.
constant TZMM_TZPU7 : integer := 31; -- Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 7 is selected.
------------------------------------------------------------
-- Configurable parameters.
------------------------------------------------------------
-- Target hardware.
constant CPLD_HOST_HW : integer := MODE_PCW8256;
-- Target video hardware.
constant CPLD_HAS_FPGA_VIDEO : std_logic := '1';
-- Version of hdl.
constant CPLD_VERSION : integer := 2;
-- Clock source for the secondary clock. If a K64F is installed then enable it otherwise use the onboard oscillator.
--
constant USE_K64F_CTL_CLOCK : integer := 1;
------------------------------------------------------------
-- Function prototypes
------------------------------------------------------------
-- Find the maximum of two integers.
function IntMax(a : in integer; b : in integer) return integer;
-- Find the number of bits required to represent an integer.
function log2ceil(arg : positive) return natural;
-- Function to calculate the number of whole 'clock' cycles in a given time period, the period being in ns.
function clockTicks(period : in integer; clock : in integer) return integer;
-- Function to reverse the order of the bits in a standard logic vector.
-- ie. 1010 becomes 0101
function reverse_vector(slv:std_logic_vector) return std_logic_vector;
-- Function to convert an integer (0 or 1) into std_logic.
--
function to_std_logic(i : in integer) return std_logic;
-- Function to return the value of a bit as an integer for array indexing etc.
function bit_to_integer( s : std_logic ) return natural;
------------------------------------------------------------
-- Records
------------------------------------------------------------
------------------------------------------------------------
-- Components
------------------------------------------------------------
end tzpuFusionX_pkg;
------------------------------------------------------------
-- Function definitions.
------------------------------------------------------------
package body tzpuFusionX_pkg is
-- Find the maximum of two integers.
function IntMax(a : in integer; b : in integer) return integer is
begin
if a > b then
return a;
else
return b;
end if;
return a;
end function IntMax;
-- Find the number of bits required to represent an integer.
function log2ceil(arg : positive) return natural is
variable tmp : positive := 1;
variable log : natural := 0;
begin
if arg = 1 then
return 0;
end if;
while arg > tmp loop
tmp := tmp * 2;
log := log + 1;
end loop;
return log;
end function;
-- Function to calculate the number of whole 'clock' cycles in a given time period, the period being in ns.
function clockTicks(period : in integer; clock : in integer) return integer is
variable ticks : real;
variable fracTicks : real;
begin
ticks := (Real(period) * Real(clock)) / 1000000000.0;
fracTicks := ticks - CEIL(ticks);
if fracTicks > 0.0001 then
return Integer(CEIL(ticks + 1.0));
else
return Integer(CEIL(ticks));
end if;
end function;
function reverse_vector(slv:std_logic_vector) return std_logic_vector is
variable target : std_logic_vector(slv'high downto slv'low);
begin
for idx in slv'high downto slv'low loop
target(idx) := slv(slv'low + (slv'high-idx));
end loop;
return target;
end reverse_vector;
function to_std_logic(i : in integer) return std_logic is
begin
if i = 0 then
return '0';
end if;
return '1';
end function;
-- Function to return the value of a bit as an integer for array indexing etc.
function bit_to_integer( s : std_logic ) return natural is
begin
if s = '1' then
return 1;
else
return 0;
end if;
end function;
end package body;

BIN
software/FusionX/bin/k64fcpu vendored Executable file

Binary file not shown.

BIN
software/FusionX/bin/sharpbiter vendored Executable file

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,54 @@
#!/bin/sh
FUSIONXDIR=/apps/FusionX
# Setup screen width, used to load correct RFS ROM images.
SCREENWIDTH=40
if [[ "$#" -ne 0 ]]; then
if [[ "$1" -eq 80 ]]; then
SCREENWIDTH=80
fi
fi
echo "Screen width set to: ${SCREENWIDTH}"
# Detach CPU 1 from scheduler and IRQ's as it will be dedicated to the z80drv.
for f in `ps -eaf |grep -v kthread_z80 | awk '{print $1}'`
do
taskset -pc 0 $f >/dev/null 2>/dev/null
done
# Detach IRQ's
for I in $(ls /proc/irq)
do
if [[ -d "/proc/irq/$I" ]]
then
echo 0 > /proc/irq/$I/smp_affinity_list 2>/dev/null
fi
done
# Load the Z80 driver. Small pause to ensure the driver is fully loaded and initialsed prior to loading ROM images.
cd ${FUSIONXDIR}/modules
rmmod z80drv 2>/dev/null
insmod z80drv.ko
sleep 1
# Add the RFS Virtual Hardware to the driver.
${FUSIONXDIR}/bin/z80ctrl --adddev --device rfs
# Load the original RFS ROM images. These are loaded by the RFS driver but here for reference or to load alternate. If
# alternate roms are loaded then ensure they are loaded prior to the start command below.
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/rom/MROM_256_${SCREENWIDTH}c.bin --addr 0x000000 --type 1
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/rom/USER_ROM_256_${SCREENWIDTH}c.bin --addr 0x80000 --type 1
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/rom/USER_ROM_II_256_${SCREENWIDTH}c.bin --addr 0x100000 --type 1
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/rom/USER_ROM_III_256_${SCREENWIDTH}c.bin --addr 0x180000 --type 1
# Start the Z80 (ie. MZ-80A virtual processor).
${FUSIONXDIR/bin/z80ctrl --start
# Ensure the system is set for performance mode with max frequency.
# NB: Enabling this prior to starting the Z80 results in a kernel error.
echo performance > /sys/devices//system/cpu/cpufreq/policy0/scaling_governor
echo 1200000 > /sys/devices//system/cpu/cpufreq/policy0/scaling_min_freq
# Done.
echo "FusionX loaded and configured in RFS mode."

View File

@@ -0,0 +1,54 @@
#!/bin/sh
FUSIONXDIR=/apps/FusionX
# Setup screen width, used to load correct Monitor ROM image.
SCREENWIDTH=40
if [[ "$#" -ne 0 ]]; then
if [[ "$1" -eq 80 ]]; then
SCREENWIDTH=80
fi
fi
echo "Screen width set to: ${SCREENWIDTH}"
# Detach CPU 1 from scheduler and IRQ's as it will be dedicated to the z80drv.
for f in `ps -eaf |grep -v kthread_z80 | awk '{print $1}'`
do
taskset -pc 0 $f >/dev/null 2>/dev/null
done
# Detach IRQ's
for I in $(ls /proc/irq)
do
if [[ -d "/proc/irq/$I" ]]
then
echo 0 > /proc/irq/$I/smp_affinity_list 2>/dev/null
fi
done
# Load the Z80 driver. Small pause to ensure the driver is fully loaded and initialsed prior to loading ROM images.
cd ${FUSIONXDIR}/modules
rmmod z80drv 2>/dev/null
insmod z80drv.ko
sleep 1
# Add the TZPU Virtual Hardware to the driver.
${FUSIONXDIR}/bin/z80ctrl --adddev --device tzpu
# Start the K64F Virtual CPU Emulation.
${FUSIONXDIR}/bin/k64fcpu &
# Load the original Monitor and TZFS ROM images. This is done in the K64F daemon but can be manually enabled.
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/roms/monitor_${SCREENWIDTH}c_sa1510.rom --addr 0x000000 --type 1
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/roms/tzfs.rom --offset 0x000000 --len 0x001800 --addr 0x00E800 --type 1
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/roms/tzfs.rom --offset 0x001800 --len 0x001000 --addr 0x01F000 --type 1
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/roms/tzfs.rom --offset 0x002800 --len 0x001000 --addr 0x02F000 --type 1
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/roms/tzfs.rom --offset 0x003800 --len 0x001000 --addr 0x03F000 --type 1
# Ensure the system is set for performance mode with max frequency.
# NB: Enabling this prior to starting the Z80 results in a kernel error.
echo performance > /sys/devices//system/cpu/cpufreq/policy0/scaling_governor
echo 1200000 > /sys/devices//system/cpu/cpufreq/policy0/scaling_min_freq
# Done.
echo "FusionX loaded and configured in TZFS mode."

View File

@@ -1,8 +1,11 @@
#!/bin/sh
cd /customer
./cpuset.sh
FUSIONXDIR=/apps/FusionX
cd ${FUSIONXDIR}/modules
${FUSIONXDIR/etc/cpuset.sh
rmmod z80drv 2>/dev/null
insmod z80drv.ko
#echo performance > /sys/devices//system/cpu/cpufreq/policy0/scaling_governor
#drvid=`ps -eaf | grep kthread_z80 | grep -v grep | awk '{print $1}'`
#taskset -pc 1 $drvid

BIN
software/FusionX/modules/ttymzdrv.ko vendored Normal file

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,326 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: z80driver.h
// Created: Oct 2022
// Author(s): Philip Smart
// Description: Z80 Driver
// This file contains the declarations used in the z80drv device driver.
//
// Credits: Zilog Z80 CPU Emulator v0.2 written by Manuel Sainz de Baranda y Goñi
// The Z80 CPU Emulator is the heart of this driver and in all ways, is compatible with
// the original Z80.
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
// (c) 1999-2022 Manuel Sainz de Baranda y Goñi
//
// History: Oct 2022 - Initial write of the z80 kernel driver software.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef Z80DRIVER_H
#define Z80DRIVER_H
// Constants.
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ2000 1
#define Z80_VIRTUAL_ROM_SIZE 16384 // Sized to maximum ROM which is the MZ-800 ROM.
#define Z80_VIRTUAL_RAM_SIZE (65536 * 8) // (PAGE_SIZE * 2) // max size mmaped to userspace
#define Z80_VIRTUAL_MEMORY_SIZE Z80_VIRTUAL_RAM_SIZE + Z80_VIRTUAL_ROM_SIZE
#define Z80_MEMORY_PAGE_SIZE 16
#define MAX_SCREEN_WIDTH 132
#define DEVICE_NAME "z80drv"
#define CLASS_NAME "mogu"
// Memory and IO page types. Used to create a memory page which maps type of address space to real address space on host or virtual memory.
#define MEMORY_TYPE_VIRTUAL_MASK 0x00FFFFFF
#define MEMORY_TYPE_REAL_MASK 0x0000FFFF
#define IO_TYPE_MASK 0x0000FFFF
#define MEMORY_TYPE_INHIBIT 0x00000000
#define MEMORY_TYPE_PHYSICAL_RAM 0x80000000
#define MEMORY_TYPE_PHYSICAL_ROM 0x40000000
#define MEMORY_TYPE_PHYSICAL_VRAM 0x20000000
#define MEMORY_TYPE_PHYSICAL_HW 0x10000000
#define MEMORY_TYPE_VIRTUAL_RAM 0x08000000
#define MEMORY_TYPE_VIRTUAL_ROM 0x04000000
#define MEMORY_TYPE_VIRTUAL_HW 0x02000000
#define IO_TYPE_PHYSICAL_HW 0x80000000
#define IO_TYPE_VIRTUAL_HW 0x40000000
// Approximate governor delays to regulate emulated CPU speed.
// MZ-700
#if(TARGET_HOST_MZ700 == 1)
#define INSTRUCTION_DELAY_ROM_3_54MHZ 253
#define INSTRUCTION_DELAY_ROM_7MHZ 126
#define INSTRUCTION_DELAY_ROM_14MHZ 63
#define INSTRUCTION_DELAY_ROM_28MHZ 32
#define INSTRUCTION_DELAY_ROM_56MHZ 16
#define INSTRUCTION_DELAY_ROM_112MHZ 8
#define INSTRUCTION_DELAY_ROM_224MHZ 4
#define INSTRUCTION_DELAY_ROM_448MHZ 1
#define INSTRUCTION_DELAY_RAM_3_54MHZ 253
#define INSTRUCTION_DELAY_RAM_7MHZ 126
#define INSTRUCTION_DELAY_RAM_14MHZ 63
#define INSTRUCTION_DELAY_RAM_28MHZ 32
#define INSTRUCTION_DELAY_RAM_56MHZ 16
#define INSTRUCTION_DELAY_RAM_112MHZ 8
#define INSTRUCTION_DELAY_RAM_224MHZ 4
#define INSTRUCTION_DELAY_RAM_448MHZ 1
#endif
// MZ-2000
#if(TARGET_HOST_MZ2000 == 1)
#define INSTRUCTION_DELAY_ROM_3_54MHZ 243
#define INSTRUCTION_DELAY_ROM_7MHZ 122
#define INSTRUCTION_DELAY_ROM_14MHZ 61
#define INSTRUCTION_DELAY_ROM_28MHZ 30
#define INSTRUCTION_DELAY_ROM_56MHZ 15
#define INSTRUCTION_DELAY_ROM_112MHZ 7
#define INSTRUCTION_DELAY_ROM_224MHZ 3
#define INSTRUCTION_DELAY_ROM_448MHZ 1
#define INSTRUCTION_DELAY_RAM_3_54MHZ 218
#define INSTRUCTION_DELAY_RAM_7MHZ 112
#define INSTRUCTION_DELAY_RAM_14MHZ 56
#define INSTRUCTION_DELAY_RAM_28MHZ 28
#define INSTRUCTION_DELAY_RAM_56MHZ 14
#define INSTRUCTION_DELAY_RAM_112MHZ 7
#define INSTRUCTION_DELAY_RAM_224MHZ 3
#define INSTRUCTION_DELAY_RAM_448MHZ 1
#endif
// IOCTL commands. Passed from user space using the IOCTL method to command the driver to perform an action.
#define IOCTL_CMD_Z80_STOP 's'
#define IOCTL_CMD_Z80_START 'S'
#define IOCTL_CMD_Z80_PAUSE 'P'
#define IOCTL_CMD_Z80_RESET 'R'
#define IOCTL_CMD_Z80_CONTINUE 'C'
#define IOCTL_CMD_USE_HOST_RAM 'x'
#define IOCTL_CMD_USE_VIRTUAL_RAM 'X'
#define IOCTL_CMD_DUMP_MEMORY 'M'
#define IOCTL_CMD_Z80_CPU_FREQ 'F'
#define IOCTL_CMD_CPLD_CMD 'z'
#define IOCTL_CMD_SEND _IOW('c', 'c', int32_t *)
#define IOCTL_CMD_SETPC _IOW('p', 'p', int32_t *)
#define IOCTL_CMD_SYNC_TO_HOST_RAM 'V'
#define IOCTL_CMD_SPI_TEST '1'
#define IOCTL_CMD_PRL_TEST '2'
#define IOCTL_CMD_Z80_MEMTEST '3'
// Chip Select map MZ80K-MZ700.
//
// 0000 - 0FFF = CS_ROMni : R/W : MZ80K/A/700 = Monitor ROM or RAM (MZ80A rom swap)
// 1000 - CFFF = CS_RAMni : R/W : MZ80K/A/700 = RAM
// C000 - CFFF = CS_ROMni : R/W : MZ80A = Monitor ROM (MZ80A rom swap)
// D000 - D7FF = CS_VRAMni : R/W : MZ80K/A/700 = VRAM
// D800 - DFFF = CS_VRAMni : R/W : MZ700 = Colour VRAM (MZ700)
// E000 - E003 = CS_8255n : R/W : MZ80K/A/700 = 8255
// E004 - E007 = CS_8254n : R/W : MZ80K/A/700 = 8254
// E008 - E00B = CS_LS367n : R/W : MZ80K/A/700 = LS367
// E00C - E00F = CS_ESWPn : R : MZ80A = Memory Swap (MZ80A)
// E010 - E013 = CS_ESWPn : R : MZ80A = Reset Memory Swap (MZ80A)
// E014 = CS_E5n : R/W : MZ80A/700 = Normal CRT display (in Video Controller)
// E015 = CS_E6n : R/W : MZ80A/700 = Reverse CRT display (in Video Controller)
// E200 - E2FF = : R/W : MZ80A/700 = VRAM roll up/roll down.
// E800 - EFFF = : R/W : MZ80K/A/700 = User ROM socket or DD Eprom (MZ700)
// F000 - F7FF = : R/W : MZ80K/A/700 = Floppy Disk interface.
// F800 - FFFF = : R/W : MZ80K/A/700 = Floppy Disk interface.
//
// Chip Select map MZ800
//
// FC - FF = CS_PIOn : R/W : MZ800/MZ1500 = Z80 PIO Printer Interface
// F2 = CS_PSG0n : W : MZ800/MZ1500 = Programable Sound Generator, MZ-800 = Mono, MZ-1500 = Left Channel
// F3 = CS_PSG1n : W : MZ1500 = Programable Sound Generator, MZ-1500 = Right Channel
// E9 = CS_PSG(X)n: W : MZ1500 = Simultaneous write to both PSG's.
// F0 - F1 = CS_JOYSTK : R : MZ800 = Joystick 1 and 2
// CC = CS_GWF : W : MZ800 = CRTC GWF Write format Register
// CD = CS_GRF : W : MZ800 = CRTC GRF Read format Register
// CE = CS_GDMD : W : MZ800 = CRTC GDMD Mode Register
// CF = CS_GCRTC : W : MZ800 = CRTC GCRTC Control Register
// D4 - D7 = CS
// D000 - DFFF
// MZ700/MZ800 memory mode switch?
//
// MZ-700 MZ-800
// |0000:0FFF|1000:1FFF|1000:CFFF|C000:CFFF|D000:FFFF |0000:7FFF|1000:1FFF|2000:7FFF|8000:BFFF|C000:CFFF|C000:DFFF|E000:FFFF
// -------------------------------------------------- ----------------------------------------------------------------------
// OUT 0xE0 = |DRAM | | | | |DRAM | | | | | |
// OUT 0xE1 = | | | | |DRAM | | | | | | |DRAM
// OUT 0xE2 = |MONITOR | | | | |MONITOR | | | | | |
// OUT 0xE3 = | | | | |Memory Mapped I/O | | | | | | |Upper MONITOR ROM
// OUT 0xE4 = |MONITOR | |DRAM | |Memory Mapped I/O |MONITOR |CGROM |DRAM |VRAM | |DRAM |Upper MONITOR ROM
// OUT 0xE5 = | | | | |Inhibit | | | | | | |Inhibit
// OUT 0xE6 = | | | | |<return> | | | | | | |<return>
// IN 0xE0 = | |CGROM* | |VRAM* | | |CGROM | |VRAM | | |
// IN 0xE1 = | |DRAM | |DRAM | | |<return> | |DRAM | | |
//
// <return> = Return to the state prior to the complimentary command being invoked.
// * = MZ-800 host only.
// Macros to lookup and test to see if a given memory block or IO byte is of a given type. Also macros to read/write to the memory block and IO byte.
#define MEMORY_BLOCK_GRANULARITY 0x800
#define MEMORY_BLOCK_SLOTS (0x10000 / MEMORY_BLOCK_GRANULARITY)
#define MEMORY_BLOCK_MASK (0x10000 - MEMORY_BLOCK_GRANULARITY)
#define MEMORY_BLOCK_SHIFT 11
#define getPageData(a) (Z80Ctrl->page[(a & 0xF800) >> MEMORY_BLOCK_SHIFT])
#define getIOPageData(a) (Z80Ctrl->iopage[(a & 0xFFFF])
#define getPageType(a, mask) (getPageData(a) & mask)
#define getPageAddr(a, mask) ((getPageData(a) & mask) + (a & (MEMORY_BLOCK_GRANULARITY-1)))
#define getIOPageType(a, mask) (getIOPageData(a) & mask)
#define getIOPageAddr(a, mask) (getIOPageData(a) & mask)
#define realAddress(a) (Z80Ctrl->page[getPageAddr(a, MEMORY_TYPE_REAL_MASK)])
#define realPort(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_MASK)
#define isPhysicalRAM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_RAM))
#define isPhysicalVRAM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_VRAM))
#define isPhysicalROM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_ROM))
#define isPhysicalMemory(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_ROM | MEMORY_TYPE_PHYSICAL_RAM | MEMORY_TYPE_PHYSICAL_VRAM))])
#define isPhysicalHW(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_HW))
#define isPhysical(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_HW | MEMORY_TYPE_PHYSICAL_ROM | MEMORY_TYPE_PHYSICAL_RAM | MEMORY_TYPE_PHYSICAL_VRAM)))
#define isPhysicalIO(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_PHYSICAL_HW)
#define isVirtualRAM(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_RAM))
#define isVirtualROM(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_ROM))
#define isVirtualMemory(a) (getPageType(a, (MEMORY_TYPE_VIRTUAL_ROM | MEMORY_TYPE_VIRTUAL_RAM)))
#define isVirtualHW(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_HW))
#define isVirtualIO(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_VIRTUAL_HW)
#define isHW(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_HW | MEMORY_TYPE_VIRTUAL_HW)))
#define readVirtualRAM(a) (Z80Ctrl->memory[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ])
#define readVirtualROM(a) (Z80Ctrl->memory[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) + Z80_VIRTUAL_RAM_SIZE ])
#define writeVirtualRAM(a, d) { Z80Ctrl->memory[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ] = d; }
#define setMemoryType(_block_,_type_,_addr_) { Z80Ctrl->page[_block_] = _type_ | _addr_; }
#define backupMemoryType(_block_) { Z80Ctrl->shadowPage[_block_] = Z80Ctrl->page[_block_]; }
#define restoreMemoryType(_block_) { Z80Ctrl->page[_block_] = Z80Ctrl->shadowPage[_block_]; }
#define IO_ADDR_E0 0xE0
#define IO_ADDR_E1 0xE1
#define IO_ADDR_E2 0xE2
#define IO_ADDR_E3 0xE3
#define IO_ADDR_E4 0xE4
#define IO_ADDR_E5 0xE5
#define IO_ADDR_E6 0xE6
#define IO_ADDR_E7 0xE7
#define IO_ADDR_E8 0xE8
#define IO_ADDR_E9 0xE9
#define IO_ADDR_EA 0xEA
#define IO_ADDR_EB 0xEB
enum Z80_RUN_STATES {
Z80_STOP = 0x00,
Z80_STOPPED = 0x01,
Z80_PAUSE = 0x02,
Z80_PAUSED = 0x03,
Z80_CONTINUE = 0x04,
Z80_RUNNING = 0x05,
};
enum Z80_MEMORY_PROFILE {
USE_PHYSICAL_RAM = 0x00,
USE_VIRTUAL_RAM = 0x01
};
typedef struct {
// Main memory, linear but indexed as though it were banks in 1K pages.
uint8_t memory[Z80_VIRTUAL_MEMORY_SIZE];
// Page pointer map.
//
// Each pointer points to a byte or block of bytes in the Z80 Memory frame, 64K Real + Banked.
// This is currently set at a block of size 0x800 per memory pointer for the MZ-700.
// The LSB of the pointer is a direct memory index to a byte or block of bytes, the upper byte of the pointer indicates type of memory space.
// 0x80<FFFFFF> - physical host RAM
// 0x40<FFFFFF> - physical host ROM
// 0x20<FFFFFF> - physical host VRAM
// 0x10<FFFFFF> - physical host hardware
// 0x08<FFFFFF> - virtual host RAM
// 0x04<FFFFFF> - virtual host ROM
// 0x02<FFFFFF> - virtual host hardware
// 16bit Input Address -> map -> Pointer to 24bit memory address + type flag.
// -> Pointer+<low bits of address> to 24bit memory address + type flag.
uint32_t page[MEMORY_BLOCK_SLOTS];
uint32_t shadowPage[MEMORY_BLOCK_SLOTS];
// I/O Page map.
//
// This is a map to indicate the use of the I/O page and allow any required remapping.
// <0x80>FF<I/O Address> - physical host hardware
// <0x40>FF<I/O Address> - virtual host hardware
// 16bit Input Address -> map -> Actual 16bit address to use + type flag.
uint32_t iopage[65536];
// Default page mode configured. This value reflects the default page and iotable map.
uint8_t defaultPageMode;
// Refresh DRAM mode. 1 = Refresh, 0 = No refresh. Only applicable when running code in virtual Kernel RAM.
uint8_t refreshDRAM;
// Inhibit mode is where certain memory ranges are inhibitted. The memory page is set to inhibit and this flag
// blocks actions which arent allowed during inhibit.
uint8_t inhibitMode;
// Address caching. Used to minimise instruction length sent to CPLD.
uint16_t z80PrevAddr;
uint16_t z80PrevPort;
#if(TARGET_HOST_MZ2000 == 1)
uint8_t lowMemorySwap;
#endif
// Keyboard strobe and data. Required to detect hotkey press.
uint8_t keyportStrobe;
uint8_t keyportShiftCtrl;
uint8_t keyportHotKey;
// Governor is the delay in a 32bit loop per Z80 opcode, used to govern execution speed when using virtual memory.
// This mechanism will eventually be tied into the M/T-state calculation for a more precise delay, but at the moment,
// with the Z80 assigned to an isolated CPU, it allows time sensitive tasks such as the tape recorder to work.
// The lower the value the faster the CPU speed. Two values are present as the optimiser, seeing ROM code not changing
// is quicker than RAM (both are in the same kernel memory) as a pointer calculation needs to be made.
uint32_t cpuGovernorDelayROM;
uint32_t cpuGovernorDelayRAM;
} t_Z80Ctrl;
// IOCTL structure for passing data from user space to driver to perform commands.
//
struct z80_addr {
uint32_t start;
uint32_t end;
uint32_t size;
};
struct z80_ctrl {
uint16_t pc;
};
struct speed {
uint32_t speedMultiplier;
};
struct cpld_ctrl {
uint32_t cmd;
};
struct ioctlCmd {
int32_t cmd;
union {
struct z80_addr addr;
struct z80_ctrl z80;
struct speed speed;
struct cpld_ctrl cpld;
};
};
// Prototypes.
void setupMemory(enum Z80_MEMORY_PROFILE mode);
#endif

View File

@@ -1,403 +0,0 @@
/* Optparse --- portable, reentrant, embeddable, getopt-like option parser
*
* This is free and unencumbered software released into the public domain.
*
* To get the implementation, define OPTPARSE_IMPLEMENTATION.
* Optionally define OPTPARSE_API to control the API's visibility
* and/or linkage (static, __attribute__, __declspec).
*
* The POSIX getopt() option parser has three fatal flaws. These flaws
* are solved by Optparse.
*
* 1) Parser state is stored entirely in global variables, some of
* which are static and inaccessible. This means only one thread can
* use getopt(). It also means it's not possible to recursively parse
* nested sub-arguments while in the middle of argument parsing.
* Optparse fixes this by storing all state on a local struct.
*
* 2) The POSIX standard provides no way to properly reset the parser.
* This means for portable code that getopt() is only good for one
* run, over one argv with one option string. It also means subcommand
* options cannot be processed with getopt(). Most implementations
* provide a method to reset the parser, but it's not portable.
* Optparse provides an optparse_arg() function for stepping over
* subcommands and continuing parsing of options with another option
* string. The Optparse struct itself can be passed around to
* subcommand handlers for additional subcommand option parsing. A
* full reset can be achieved by with an additional optparse_init().
*
* 3) Error messages are printed to stderr. This can be disabled with
* opterr, but the messages themselves are still inaccessible.
* Optparse solves this by writing an error message in its errmsg
* field. The downside to Optparse is that this error message will
* always be in English rather than the current locale.
*
* Optparse should be familiar with anyone accustomed to getopt(), and
* it could be a nearly drop-in replacement. The option string is the
* same and the fields have the same names as the getopt() global
* variables (optarg, optind, optopt).
*
* Optparse also supports GNU-style long options with optparse_long().
* The interface is slightly different and simpler than getopt_long().
*
* By default, argv is permuted as it is parsed, moving non-option
* arguments to the end. This can be disabled by setting the `permute`
* field to 0 after initialization.
*/
#ifndef OPTPARSE_H
#define OPTPARSE_H
#ifndef OPTPARSE_API
# define OPTPARSE_API
#endif
struct optparse {
char **argv;
int permute;
int optind;
int optopt;
char *optarg;
char errmsg[64];
int subopt;
};
enum optparse_argtype {
OPTPARSE_NONE,
OPTPARSE_REQUIRED,
OPTPARSE_OPTIONAL
};
struct optparse_long {
const char *longname;
int shortname;
enum optparse_argtype argtype;
};
/**
* Initializes the parser state.
*/
OPTPARSE_API
void optparse_init(struct optparse *options, char **argv);
/**
* Read the next option in the argv array.
* @param optstring a getopt()-formatted option string.
* @return the next option character, -1 for done, or '?' for error
*
* Just like getopt(), a character followed by no colons means no
* argument. One colon means the option has a required argument. Two
* colons means the option takes an optional argument.
*/
OPTPARSE_API
int optparse(struct optparse *options, const char *optstring);
/**
* Handles GNU-style long options in addition to getopt() options.
* This works a lot like GNU's getopt_long(). The last option in
* longopts must be all zeros, marking the end of the array. The
* longindex argument may be NULL.
*/
OPTPARSE_API
int optparse_long(struct optparse *options,
const struct optparse_long *longopts,
int *longindex);
/**
* Used for stepping over non-option arguments.
* @return the next non-option argument, or NULL for no more arguments
*
* Argument parsing can continue with optparse() after using this
* function. That would be used to parse the options for the
* subcommand returned by optparse_arg(). This function allows you to
* ignore the value of optind.
*/
OPTPARSE_API
char *optparse_arg(struct optparse *options);
/* Implementation */
#ifdef OPTPARSE_IMPLEMENTATION
#define OPTPARSE_MSG_INVALID "invalid option"
#define OPTPARSE_MSG_MISSING "option requires an argument"
#define OPTPARSE_MSG_TOOMANY "option takes no arguments"
static int
optparse_error(struct optparse *options, const char *msg, const char *data)
{
unsigned p = 0;
const char *sep = " -- '";
while (*msg)
options->errmsg[p++] = *msg++;
while (*sep)
options->errmsg[p++] = *sep++;
while (p < sizeof(options->errmsg) - 2 && *data)
options->errmsg[p++] = *data++;
options->errmsg[p++] = '\'';
options->errmsg[p++] = '\0';
return '?';
}
OPTPARSE_API
void
optparse_init(struct optparse *options, char **argv)
{
options->argv = argv;
options->permute = 1;
options->optind = 1;
options->subopt = 0;
options->optarg = 0;
options->errmsg[0] = '\0';
}
static int
optparse_is_dashdash(const char *arg)
{
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0';
}
static int
optparse_is_shortopt(const char *arg)
{
return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0';
}
static int
optparse_is_longopt(const char *arg)
{
return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0';
}
static void
optparse_permute(struct optparse *options, int index)
{
char *nonoption = options->argv[index];
int i;
for (i = index; i < options->optind - 1; i++)
options->argv[i] = options->argv[i + 1];
options->argv[options->optind - 1] = nonoption;
}
static int
optparse_argtype(const char *optstring, char c)
{
int count = OPTPARSE_NONE;
if (c == ':')
return -1;
for (; *optstring && c != *optstring; optstring++);
if (!*optstring)
return -1;
if (optstring[1] == ':')
count += optstring[2] == ':' ? 2 : 1;
return count;
}
OPTPARSE_API
int
optparse(struct optparse *options, const char *optstring)
{
int type;
char *next;
char *option = options->argv[options->optind];
options->errmsg[0] = '\0';
options->optopt = 0;
options->optarg = 0;
if (option == 0) {
return -1;
} else if (optparse_is_dashdash(option)) {
options->optind++; /* consume "--" */
return -1;
} else if (!optparse_is_shortopt(option)) {
if (options->permute) {
int index = options->optind++;
int r = optparse(options, optstring);
optparse_permute(options, index);
options->optind--;
return r;
} else {
return -1;
}
}
option += options->subopt + 1;
options->optopt = option[0];
type = optparse_argtype(optstring, option[0]);
next = options->argv[options->optind + 1];
switch (type) {
case -1: {
char str[2] = {0, 0};
str[0] = option[0];
options->optind++;
return optparse_error(options, OPTPARSE_MSG_INVALID, str);
}
case OPTPARSE_NONE:
if (option[1]) {
options->subopt++;
} else {
options->subopt = 0;
options->optind++;
}
return option[0];
case OPTPARSE_REQUIRED:
options->subopt = 0;
options->optind++;
if (option[1]) {
options->optarg = option + 1;
} else if (next != 0) {
options->optarg = next;
options->optind++;
} else {
char str[2] = {0, 0};
str[0] = option[0];
options->optarg = 0;
return optparse_error(options, OPTPARSE_MSG_MISSING, str);
}
return option[0];
case OPTPARSE_OPTIONAL:
options->subopt = 0;
options->optind++;
if (option[1])
options->optarg = option + 1;
else
options->optarg = 0;
return option[0];
}
return 0;
}
OPTPARSE_API
char *
optparse_arg(struct optparse *options)
{
char *option = options->argv[options->optind];
options->subopt = 0;
if (option != 0)
options->optind++;
return option;
}
static int
optparse_longopts_end(const struct optparse_long *longopts, int i)
{
return !longopts[i].longname && !longopts[i].shortname;
}
static void
optparse_from_long(const struct optparse_long *longopts, char *optstring)
{
char *p = optstring;
int i;
for (i = 0; !optparse_longopts_end(longopts, i); i++) {
if (longopts[i].shortname && longopts[i].shortname < 127) {
int a;
*p++ = longopts[i].shortname;
for (a = 0; a < (int)longopts[i].argtype; a++)
*p++ = ':';
}
}
*p = '\0';
}
/* Unlike strcmp(), handles options containing "=". */
static int
optparse_longopts_match(const char *longname, const char *option)
{
const char *a = option, *n = longname;
if (longname == 0)
return 0;
for (; *a && *n && *a != '='; a++, n++)
if (*a != *n)
return 0;
return *n == '\0' && (*a == '\0' || *a == '=');
}
/* Return the part after "=", or NULL. */
static char *
optparse_longopts_arg(char *option)
{
for (; *option && *option != '='; option++);
if (*option == '=')
return option + 1;
else
return 0;
}
static int
optparse_long_fallback(struct optparse *options,
const struct optparse_long *longopts,
int *longindex)
{
int result;
char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */
optparse_from_long(longopts, optstring);
result = optparse(options, optstring);
if (longindex != 0) {
*longindex = -1;
if (result != -1) {
int i;
for (i = 0; !optparse_longopts_end(longopts, i); i++)
if (longopts[i].shortname == options->optopt)
*longindex = i;
}
}
return result;
}
OPTPARSE_API
int
optparse_long(struct optparse *options,
const struct optparse_long *longopts,
int *longindex)
{
int i;
char *option = options->argv[options->optind];
if (option == 0) {
return -1;
} else if (optparse_is_dashdash(option)) {
options->optind++; /* consume "--" */
return -1;
} else if (optparse_is_shortopt(option)) {
return optparse_long_fallback(options, longopts, longindex);
} else if (!optparse_is_longopt(option)) {
if (options->permute) {
int index = options->optind++;
int r = optparse_long(options, longopts, longindex);
optparse_permute(options, index);
options->optind--;
return r;
} else {
return -1;
}
}
/* Parse as long option. */
options->errmsg[0] = '\0';
options->optopt = 0;
options->optarg = 0;
option += 2; /* skip "--" */
options->optind++;
for (i = 0; !optparse_longopts_end(longopts, i); i++) {
const char *name = longopts[i].longname;
if (optparse_longopts_match(name, option)) {
char *arg;
if (longindex)
*longindex = i;
options->optopt = longopts[i].shortname;
arg = optparse_longopts_arg(option);
if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) {
return optparse_error(options, OPTPARSE_MSG_TOOMANY, name);
} if (arg != 0) {
options->optarg = arg;
} else if (longopts[i].argtype == OPTPARSE_REQUIRED) {
options->optarg = options->argv[options->optind];
if (options->optarg == 0)
return optparse_error(options, OPTPARSE_MSG_MISSING, name);
else
options->optind++;
}
return options->optopt;
}
}
return optparse_error(options, OPTPARSE_MSG_INVALID, option);
}
#endif /* OPTPARSE_IMPLEMENTATION */
#endif /* OPTPARSE_H */

View File

@@ -1,734 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: z80ctrl.c
// Created: Oct 2022
// Author(s): Philip Smart
// Description: Z80 Control Interface
// This file contains a command line utility tool for controlling the z80drv device
// driver. The tool allows manipulation of the emulated Z80, inspection of its
// memory and data, transmission of adhoc commands to the underlying CPLD-Z80
// gateway and loading/saving of programs and data to/from the Z80 virtual and
// host memory.
//
// Credits: Zilog Z80 CPU Emulator v0.2 written by Manuel Sainz de Baranda y Goñi
// The Z80 CPU Emulator is the heart of the Z80 device driver.
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
// (c) 1999-2022 Manuel Sainz de Baranda y Goñi
//
// History: Oct 2022 - Initial write of the z80 kernel driver software.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdarg.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <sys/select.h>
#include <termios.h>
#include <time.h>
#include <Z/constants/pointer.h>
#include <Z/macros/member.h>
#include <Z/macros/array.h>
#include <Z80.h>
#include "z80driver.h"
#define VERSION "1.0"
#define AUTHOR "P.D.Smart"
#define COPYRIGHT "(c) 2018-22"
// Getopt_long is buggy so we use optparse.
#define OPTPARSE_IMPLEMENTATION
#define OPTPARSE_API static
#include "optparse.h"
// Device driver name.
#define DEVICE_FILENAME "/dev/z80drv"
// Constants for the Sharp MZ80A MZF file format.
#define MZF_HEADER_SIZE 128 // Size of the MZF header.
#define MZF_ATTRIBUTE 0x00 // Code Type, 01 = Machine Code.
#define MZF_FILENAME 0x01 // Title/Name (17 bytes).
#define MZF_FILENAME_LEN 17 // Length of the filename, it is not NULL terminated, generally a CR can be taken as terminator but not guaranteed.
#define MZF_FILESIZE 0x12 // Size of program.
#define MZF_LOADADDR 0x14 // Load address of program.
#define MZF_EXECADDR 0x16 // Exec address of program.
#define MZF_COMMENT 0x18 // Comment, used for details of the file or startup code.
#define MZF_COMMENT_LEN 104 // Length of the comment field.
#define CMT_TYPE_OBJCD 0x001 // MZF contains a binary object.
#define CMT_TYPE_BTX1CD 0x002 // MZF contains a BASIC program.
#define CMT_TYPE_BTX2CD 0x005 // MZF contains a BASIC program.
#define CMT_TYPE_TZOBJCD0 0x0F8 // MZF contains a TZFS binary object for page 0.
#define CMT_TYPE_TZOBJCD1 0x0F9
#define CMT_TYPE_TZOBJCD2 0x0FA
#define CMT_TYPE_TZOBJCD3 0x0FB
#define CMT_TYPE_TZOBJCD4 0x0FC
#define CMT_TYPE_TZOBJCD5 0x0FD
#define CMT_TYPE_TZOBJCD6 0x0FE
#define CMT_TYPE_TZOBJCD7 0x0FF // MZF contains a TZFS binary object for page 7.
#define MZ_CMT_ADDR 0x10F0
// Structure to define a Sharp MZ80A MZF directory structure. This header appears at the beginning of every Sharp MZ80A tape (and more recently archived/emulator) images.
//
typedef struct __attribute__((__packed__)) {
uint8_t attr; // MZF attribute describing the file.
uint8_t fileName[MZF_FILENAME_LEN]; // Each directory entry is the size of an MZF filename.
uint16_t fileSize; // Size of file.
uint16_t loadAddr; // Load address for the file.
uint16_t execAddr; // Execution address where the Z80 starts processing.
uint8_t comment[MZF_COMMENT_LEN]; // Text comment field but often contains a startup machine code program.
} t_svcDirEnt;
// Possible commands to be issued to the Z80 driver.
enum CTRL_COMMANDS {
Z80_CMD_STOP = 0,
Z80_CMD_START = 1,
Z80_CMD_PAUSE = 2,
Z80_CMD_CONTINUE = 3,
Z80_CMD_RESET = 4,
Z80_CMD_SPEED = 5,
Z80_CMD_HOST_RAM = 6,
Z80_CMD_VIRTUAL_RAM = 7,
Z80_CMD_DUMP_MEMORY = 8,
Z80_CMD_MEMORY_TEST = 9,
CPLD_CMD_SEND_CMD = 10,
CPLD_CMD_SPI_TEST = 11,
CPLD_CMD_PRL_TEST = 12
};
// Shared memory between this process and the Z80 driver.
static t_Z80Ctrl *Z80Ctrl = NULL;
// Method to obtain and return the output screen width.
//
uint8_t getScreenWidth(void)
{
return(MAX_SCREEN_WIDTH);
}
struct termios orig_termios;
void reset_terminal_mode()
{
tcsetattr(0, TCSANOW, &orig_termios);
}
void set_conio_terminal_mode()
{
struct termios new_termios;
/* take two copies - one for now, one for later */
tcgetattr(0, &orig_termios);
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
/* register cleanup handler, and set the new terminal mode */
atexit(reset_terminal_mode);
cfmakeraw(&new_termios);
tcsetattr(0, TCSANOW, &new_termios);
}
int kbhit()
{
struct timeval tv = { 0L, 0L };
fd_set fds;
FD_ZERO(&fds);
FD_SET(0, &fds);
return select(1, &fds, NULL, NULL, &tv) > 0;
}
int getch(uint8_t wait)
{
int r;
unsigned char c;
if(wait != 0 || (wait == 0 && kbhit()))
{
if ((r = read(0, &c, sizeof(c))) < 0) {
return r;
} else {
return c;
}
}
return 0;
}
void delay(int number_of_seconds)
{
// Converting time into milli_seconds
int milli_seconds = 1000 * number_of_seconds;
// Storing start time
clock_t start_time = clock();
// looping till required time is not achieved
while (clock() < start_time + milli_seconds);
}
// Function to dump out a given section of memory via the UART.
//
int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryFlag, uint32_t memwidth, uint32_t dispaddr, uint8_t dispwidth)
{
uint8_t displayWidth = dispwidth;;
uint32_t pnt = memaddr;
uint32_t endAddr = memaddr + memsize;
uint32_t addr = dispaddr;
uint32_t i = 0;
//uint32_t data;
int8_t keyIn;
int result = -1;
char c = 0;
// Sanity check. memoryFlag == 0 required kernel driver to dump so we exit as it cannot be performed here.
if(memoryFlag == 0)
return(-1);
// Reconfigure terminal to allow non-blocking key input.
//
set_conio_terminal_mode();
// If not set, calculate output line width according to connected display width.
//
if(displayWidth == 0)
{
switch(getScreenWidth())
{
case 40:
displayWidth = 8;
break;
case 80:
displayWidth = 16;
break;
default:
displayWidth = 32;
break;
}
}
while (1)
{
printf("%08lX", addr); // print address
printf(": ");
// print hexadecimal data
for (i=0; i < displayWidth; )
{
switch(memwidth)
{
case 16:
if(pnt+i < endAddr)
printf("%04X", memoryFlag == 1 ? (uint16_t)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (uint16_t)Z80Ctrl->page[pnt+i] : (uint16_t)Z80Ctrl->iopage[pnt+i]);
else
printf(" ");
i++;
break;
case 32:
if(pnt+i < endAddr)
printf("%08lX", memoryFlag == 1 ? (uint32_t)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (uint32_t)Z80Ctrl->page[pnt+i] : (uint32_t)Z80Ctrl->iopage[pnt+i]);
else
printf(" ");
i++;
break;
case 8:
default:
if(pnt+i < endAddr)
printf("%02X", memoryFlag == 1 ? (uint8_t)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (uint8_t)Z80Ctrl->page[pnt+i] : (uint8_t)Z80Ctrl->iopage[pnt+i]);
else
printf(" ");
i++;
break;
}
fputc((char)' ', stdout);
}
// print ascii data
printf(" |");
// print single ascii char
for (i=0; i < displayWidth; i++)
{
c = memoryFlag == 1 ? (char)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (char)Z80Ctrl->page[pnt+i] : (char)Z80Ctrl->iopage[pnt+i];
if ((pnt+i < endAddr) && (c >= ' ') && (c <= '~'))
fputc((char)c, stdout);
else
fputc((char)' ', stdout);
}
printf("|\r\n");
fflush(stdout);
// Move on one row.
pnt += displayWidth;
addr += displayWidth;
// User abort (ESC), pause (Space) or all done?
//
keyIn = getch(0);
if(keyIn == ' ')
{
do {
keyIn = getch(0);
} while(keyIn != ' ' && keyIn != 0x1b);
}
// Escape key pressed, exit with 0 to indicate this to caller.
if (keyIn == 0x1b)
{
sleep(1);
result = 0;
goto memoryDumpExit;
}
// End of buffer, exit the loop.
if(pnt >= (memaddr + memsize))
{
break;
}
}
// Normal exit, return -1 to show no key pressed.
memoryDumpExit:
reset_terminal_mode();
return(result);
}
// Method to load a program or data file into the Z80 memory. First load into Virtual memory and then trigger a sync to bring Host RAM in line.
//
int z80load(int fdZ80, char *fileName)
{
// Locals.
struct ioctlCmd ioctlCmd;
int ret = 0;
t_svcDirEnt mzfHeader;
// Pause the Z80.
//
ioctlCmd.cmd = IOCTL_CMD_Z80_PAUSE;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
// Open the file and read directly into the Virtual memory via the share.
FILE *ptr;
ptr = fopen(fileName, "rb");
if(ptr)
{
printf("File:%s\n", fileName);
// First the header.
fread((uint8_t *)&mzfHeader, MZF_HEADER_SIZE, 1, ptr);
printf("Load:%x\n", mzfHeader.loadAddr);
if(mzfHeader.loadAddr > 0x1000)
{
printf("Memcpy:%x,%x\n", mzfHeader.loadAddr, mzfHeader.fileSize);
// Copy in the header.
memcpy((uint8_t *)&Z80Ctrl->memory[MZ_CMT_ADDR], (uint8_t *)&mzfHeader, MZF_HEADER_SIZE);
printf("Memcpy:%x,%x\n", mzfHeader.loadAddr, mzfHeader.fileSize);
// Now read in the data.
fread(&Z80Ctrl->memory[mzfHeader.loadAddr], mzfHeader.fileSize, 1, ptr);
printf("Memcpy:%x,%x\n", mzfHeader.loadAddr, mzfHeader.fileSize);
printf("Loaded %s, Size:%04x, Addr:%04x, Exec:%04x\n", fileName, mzfHeader.fileSize, mzfHeader.loadAddr, mzfHeader.execAddr);
}
// Sync the loaded image from Virtual memory to hard memory.
ioctlCmd.cmd = IOCTL_CMD_SYNC_TO_HOST_RAM;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
// Resume Z80 processing.
//
ioctlCmd.cmd = IOCTL_CMD_Z80_CONTINUE;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
}
else
printf("Couldnt open file\n");
return ret;
}
// Method to request basic Z80 operations.
//
int ctrlCmd(int fdZ80, enum CTRL_COMMANDS cmd, long param1, long param2, long param3)
{
// Locals.
struct ioctlCmd ioctlCmd;
uint32_t idx;
int ret = 0;
switch(cmd)
{
case Z80_CMD_STOP:
// Use IOCTL to request Z80 to Stop (power off) processing.
ioctlCmd.cmd = IOCTL_CMD_Z80_STOP;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
case Z80_CMD_START:
// Use IOCTL to request Z80 to Start (power on) processing.
ioctlCmd.cmd = IOCTL_CMD_Z80_START;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
case Z80_CMD_PAUSE:
// Use IOCTL to request Z80 to pause processing.
ioctlCmd.cmd = IOCTL_CMD_Z80_PAUSE;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
case Z80_CMD_CONTINUE:
// Use IOCTL to request Z80 continue processing.
ioctlCmd.cmd = IOCTL_CMD_Z80_CONTINUE;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
case Z80_CMD_RESET:
// Use IOCTL to request Z80 reset.
ioctlCmd.cmd = IOCTL_CMD_Z80_RESET;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
case Z80_CMD_SPEED:
// Check value is in range.
for(idx=1; idx < 256; idx+=idx)
{
if((uint32_t)param1 == idx) break;
}
if(idx == 256)
{
printf("Speed factor is illegal. It must be a multiple value of the original CPU clock, ie. 1x, 2x, 4x etc\n");
ret = -1;
} else
{
// Use IOCTL to request Z80 cpu freq change.
ioctlCmd.speed.speedMultiplier = (uint32_t)param1;
ioctlCmd.cmd = IOCTL_CMD_Z80_CPU_FREQ;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
}
break;
case CPLD_CMD_SEND_CMD:
// Build up the IOCTL command to request the given data is sent to the CPLD.
ioctlCmd.cmd = IOCTL_CMD_CPLD_CMD;
ioctlCmd.cpld.cmd = (uint32_t)param1;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
case Z80_CMD_DUMP_MEMORY:
// If virtual memory, we can dump it via the shared memory segment.
if((uint8_t)param1)
{
memoryDump((uint32_t)param2, (uint32_t)param3, (uint8_t)param1, (uint8_t)param1 == 2 || (uint8_t)param1 == 3 ? 32 : 8, (uint32_t)param2, 0);
} else
{
// Build an IOCTL command to get the driver to dump the memory.
ioctlCmd.cmd = IOCTL_CMD_DUMP_MEMORY;
ioctlCmd.addr.start = (uint32_t)param2;
ioctlCmd.addr.end = (uint32_t)param2+(uint32_t)param3;
ioctlCmd.addr.size = (uint32_t)param3;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
}
break;
case Z80_CMD_HOST_RAM:
// Use IOCTL to request change to host RAM.
ioctlCmd.cmd = IOCTL_CMD_USE_HOST_RAM;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
case Z80_CMD_VIRTUAL_RAM:
// Use IOCTL to request change to host RAM.
ioctlCmd.cmd = IOCTL_CMD_USE_VIRTUAL_RAM;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
case Z80_CMD_MEMORY_TEST:
// Send command to test the SPI.
ioctlCmd.cmd = IOCTL_CMD_Z80_MEMTEST;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
case CPLD_CMD_PRL_TEST:
// Send command to test the SPI.
ioctlCmd.cmd = IOCTL_CMD_PRL_TEST;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
case CPLD_CMD_SPI_TEST:
// Send command to test the SPI.
ioctlCmd.cmd = IOCTL_CMD_SPI_TEST;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
default:
printf("Command not supported!\n");
ret = -1;
break;
}
return ret;
}
// Method to perform some simple tests on the Z80 emulator.
//
int z80test(int fdZ80)
{
// Locals.
struct ioctlCmd ioctlCmd;
int ret = 0;
// Stop the Z80.
//
printf("Send STOP\n");
ioctlCmd.cmd = IOCTL_CMD_Z80_STOP;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
FILE *ptr;
ptr = fopen("/customer/mz700.rom", "rb");
if(ptr)
{
fread(&Z80Ctrl->memory, 65536, 1, ptr);
} else printf("Couldnt open file\n");
// Configure the Z80.
//
printf("Send SETPC\n");
ioctlCmd.z80.pc = 0;
ioctl(fdZ80, IOCTL_CMD_SETPC, &ioctlCmd);
memoryDump(0 , 65536, 1, 8, 0, 0);
// Start the Z80.
//
printf("Send START\n");
ioctlCmd.cmd = IOCTL_CMD_Z80_START;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
delay(10);
printf("Send STOP\n");
ioctlCmd.cmd = IOCTL_CMD_Z80_STOP;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
memoryDump(0, 65536, 1, 8, 0, 0);
out:
return ret;
}
// Output usage screen. So mamy commands you do need to be prompted!!
void showArgs(char *progName, struct optparse *options)
{
printf("%s %s %s %s\n\n", progName, VERSION, COPYRIGHT, AUTHOR);
printf("Synopsis:\n");
printf("%s --help # This help screen.\n", progName);
printf(" --cmd <command> = RESET # Reset the Z80\n");
printf(" = STOP # Stop and power off the Z80\n");
printf(" = START # Power on and start the Z80\n");
printf(" = PAUSE # Pause running Z80\n");
printf(" = CONTINUE # Continue Z80 execution\n");
printf(" = HOSTRAM # Use HOST DRAM\n");
printf(" = VIRTRAM # Use Virtual RAM\n");
printf(" = SPEED --speed <1, 2, 4, 8, 16, 32, 64, 128> # In Virtual RAM mode, set CPU speed to base clock x factor.\n");
printf(" = LOADMZF --file <mzf filename> # Load MZF file into memory.\n");
printf(" = DUMP --start <24bit addr> --end <24bit addr> --virtual <0 - Host RAM, 1 = Virtual RAM, 2 = PageTable, 3 = IOPageTable>\n");
printf(" = CPLDCMD --data <32bit command> # Send adhoc 32bit command to CPLD.\n");
printf(" = Z80TEST # Perform various debugging tests\n");
printf(" = SPITEST # Perform SPI testing\n");
printf(" = PRLTEST # Perform Parallel Bus testing\n");
printf(" = Z80MEMTEST # Perform HOST memory tests.\n");
}
int main(int argc, char *argv[])
{
int fdZ80;
char buff[64];
char cmd[64] = { 0 };
char fileName[256] = { 0 };
int opt;
long hexData = 0;
long speedMultiplier = 1;
long startAddr = 0x0000;
long endAddr = 0x1000;
int virtualMemory = 0;
int helpFlag = 0;
int verboseFlag = 0;
// Define parameters to be processed.
struct optparse options;
static struct optparse_long long_options[] =
{
{"help", 'h', OPTPARSE_NONE},
{"cmd", 'c', OPTPARSE_REQUIRED},
{"file", 'f', OPTPARSE_REQUIRED},
{"data", 'd', OPTPARSE_REQUIRED},
{"speed", 'S', OPTPARSE_REQUIRED},
{"virtual", 'V', OPTPARSE_REQUIRED},
{"start", 's', OPTPARSE_REQUIRED},
{"end", 'e', OPTPARSE_REQUIRED},
{"verbose", 'v', OPTPARSE_NONE},
{0}
};
// Parse the command line options.
//
optparse_init(&options, argv);
while((opt = optparse_long(&options, long_options, NULL)) != -1)
{
switch(opt)
{
// Hex data.
case 'd':
hexData = strtol(options.optarg, NULL, 0);
//printf("Hex data:%08x\n", hexData);
break;
// Start address for memory operations.
case 's':
startAddr = strtol(options.optarg, NULL, 0);
//printf("Start Addr:%04x\n", startAddr);
break;
// Speed multiplication factor for CPU governor when running in virtual memory.
case 'S':
speedMultiplier = strtol(options.optarg, NULL, 0);
//printf("Speed = base freq x %d\n", speedFactor);
break;
// End address for memory operations.
case 'e':
endAddr = strtol(options.optarg, NULL, 0);
//printf("End Addr:%04x\n", endAddr);
break;
// Virtual memory flag, 0 = host, 1 = virtual memory, 2 = page table, 3 = iopage table.
case 'V':
virtualMemory = atoi(options.optarg);
break;
// Filename.
case 'f':
strcpy(fileName, options.optarg);
break;
// Command to execute.
case 'c':
strcpy(cmd, options.optarg);
break;
// Verbose mode.
case 'v':
verboseFlag = 1;
break;
// Command help needed.
case 'h':
helpFlag = 1;
showArgs(argv[0], &options);
break;
// Unrecognised, show synopsis.
case '?':
showArgs(argv[0], &options);
printf("%s: %s\n", argv[0], options.errmsg);
return(1);
}
}
// Open the z80drv driver and attach to its shared memory, basically the Z80 control structure which includes the virtual Z80 memory.
fdZ80 = open(DEVICE_FILENAME, O_RDWR|O_NDELAY);
if(fdZ80 >= 0)
{
Z80Ctrl = (t_Z80Ctrl *)mmap(0, sizeof(t_Z80Ctrl), PROT_READ | PROT_WRITE, MAP_SHARED, fdZ80, 0);
if(Z80Ctrl == (void *)-1)
{
printf("Failed to attach to the Z80 Control structure, cannot continue, exitting....\n");
close(fdZ80);
exit(1);
}
} else
{
printf("Failed to open the Z80 Driver, exitting...\n");
exit(1);
}
// Basic string to method mapping. Started off with just 1 or two but has grown, may need a table!
if(strcasecmp(cmd, "LOADMZF") == 0)
{
z80load(fdZ80, fileName);
} else
if(strcasecmp(cmd, "RESET") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_RESET, 0, 0, 0);
} else
if(strcasecmp(cmd, "STOP") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_STOP, 0, 0, 0);
} else
if(strcasecmp(cmd, "START") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_START, 0, 0, 0);
} else
if(strcasecmp(cmd, "PAUSE") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_PAUSE, 0, 0, 0);
} else
if(strcasecmp(cmd, "CONTINUE") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_CONTINUE, 0, 0, 0);
} else
if(strcasecmp(cmd, "SPEED") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_SPEED, speedMultiplier, 0, 0);
} else
if(strcasecmp(cmd, "DUMP") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_DUMP_MEMORY, virtualMemory, startAddr, (endAddr - startAddr));
} else
if(strcasecmp(cmd, "HOSTRAM") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_HOST_RAM, 0, 0, 0);
} else
if(strcasecmp(cmd, "VIRTRAM") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_VIRTUAL_RAM, 0, 0, 0);
} else
if(strcasecmp(cmd, "CPLDCMD") == 0)
{
ctrlCmd(fdZ80, CPLD_CMD_SEND_CMD, hexData, 0, 0);
} else
// Test methods, if the code is built-in to the driver.
if(strcasecmp(cmd, "Z80TEST") == 0)
{
z80test(fdZ80);
} else
if(strcasecmp(cmd, "SPITEST") == 0)
{
ctrlCmd(fdZ80, CPLD_CMD_SPI_TEST, 0, 0, 0);
} else
if(strcasecmp(cmd, "PRLTEST") == 0)
{
ctrlCmd(fdZ80, CPLD_CMD_PRL_TEST, 0, 0, 0);
} else
if(strcasecmp(cmd, "Z80MEMTEST") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_MEMORY_TEST, 0, 0, 0);
}
else
{
showArgs(argv[0], &options);
printf("No command given, nothing done!\n");
}
// Unmap shared memory and close the device.
munmap(Z80Ctrl, sizeof(t_Z80Ctrl));
close(fdZ80);
return(0);
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,284 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: z80driver.h
// Created: Oct 2022
// Author(s): Philip Smart
// Description: Z80 Driver
// This file contains the declarations used in the z80drv device driver.
//
// Credits: Zilog Z80 CPU Emulator v0.2 written by Manuel Sainz de Baranda y Goñi
// The Z80 CPU Emulator is the heart of this driver and in all ways, is compatible with
// the original Z80.
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
// (c) 1999-2022 Manuel Sainz de Baranda y Goñi
//
// History: Oct 2022 - Initial write of the z80 kernel driver software.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef Z80DRIVER_H
#define Z80DRIVER_H
// Constants.
#define Z80_VIRTUAL_ROM_SIZE 16384 // Sized to maximum ROM which is the MZ-800 ROM.
#define Z80_VIRTUAL_RAM_SIZE (65536 * 8) // (PAGE_SIZE * 2) // max size mmaped to userspace
#define Z80_VIRTUAL_MEMORY_SIZE Z80_VIRTUAL_RAM_SIZE + Z80_VIRTUAL_ROM_SIZE
#define Z80_MEMORY_PAGE_SIZE 16
#define MAX_SCREEN_WIDTH 132
#define DEVICE_NAME "z80drv"
#define CLASS_NAME "mogu"
// Memory and IO page types. Used to create a memory page which maps type of address space to real address space on host or virtual memory.
#define MEMORY_TYPE_VIRTUAL_MASK 0x00FFFFFF
#define MEMORY_TYPE_REAL_MASK 0x0000FFFF
#define IO_TYPE_MASK 0x0000FFFF
#define MEMORY_TYPE_INHIBIT 0x00000000
#define MEMORY_TYPE_PHYSICAL_RAM 0x80000000
#define MEMORY_TYPE_PHYSICAL_ROM 0x40000000
#define MEMORY_TYPE_PHYSICAL_VRAM 0x20000000
#define MEMORY_TYPE_PHYSICAL_HW 0x10000000
#define MEMORY_TYPE_VIRTUAL_RAM 0x08000000
#define MEMORY_TYPE_VIRTUAL_ROM 0x04000000
#define MEMORY_TYPE_VIRTUAL_HW 0x02000000
#define IO_TYPE_PHYSICAL_HW 0x80000000
#define IO_TYPE_VIRTUAL_HW 0x40000000
// Approximate governor delays to regulate emulated CPU speed.
#define MZ700_INSTRUCTION_DELAY_3_54MHZ 253
#define MZ700_INSTRUCTION_DELAY_7MHZ 126
#define MZ700_INSTRUCTION_DELAY_14MHZ 63
#define MZ700_INSTRUCTION_DELAY_28MHZ 32
#define MZ700_INSTRUCTION_DELAY_56MHZ 16
#define MZ700_INSTRUCTION_DELAY_112MHZ 8
#define MZ700_INSTRUCTION_DELAY_224MHZ 4
#define MZ700_INSTRUCTION_DELAY_448MHZ 1
// IOCTL commands. Passed from user space using the IOCTL method to command the driver to perform an action.
#define IOCTL_CMD_Z80_STOP 's'
#define IOCTL_CMD_Z80_START 'S'
#define IOCTL_CMD_Z80_PAUSE 'P'
#define IOCTL_CMD_Z80_RESET 'R'
#define IOCTL_CMD_Z80_CONTINUE 'C'
#define IOCTL_CMD_USE_HOST_RAM 'x'
#define IOCTL_CMD_USE_VIRTUAL_RAM 'X'
#define IOCTL_CMD_DUMP_MEMORY 'M'
#define IOCTL_CMD_Z80_CPU_FREQ 'F'
#define IOCTL_CMD_CPLD_CMD 'z'
#define IOCTL_CMD_SEND _IOW('c', 'c', int32_t *)
#define IOCTL_CMD_SETPC _IOW('p', 'p', int32_t *)
#define IOCTL_CMD_SYNC_TO_HOST_RAM 'V'
#define IOCTL_CMD_SPI_TEST '1'
#define IOCTL_CMD_PRL_TEST '2'
#define IOCTL_CMD_Z80_MEMTEST '3'
// Chip Select map MZ80K-MZ700.
//
// 0000 - 0FFF = CS_ROMni : R/W : MZ80K/A/700 = Monitor ROM or RAM (MZ80A rom swap)
// 1000 - CFFF = CS_RAMni : R/W : MZ80K/A/700 = RAM
// C000 - CFFF = CS_ROMni : R/W : MZ80A = Monitor ROM (MZ80A rom swap)
// D000 - D7FF = CS_VRAMni : R/W : MZ80K/A/700 = VRAM
// D800 - DFFF = CS_VRAMni : R/W : MZ700 = Colour VRAM (MZ700)
// E000 - E003 = CS_8255n : R/W : MZ80K/A/700 = 8255
// E004 - E007 = CS_8254n : R/W : MZ80K/A/700 = 8254
// E008 - E00B = CS_LS367n : R/W : MZ80K/A/700 = LS367
// E00C - E00F = CS_ESWPn : R : MZ80A = Memory Swap (MZ80A)
// E010 - E013 = CS_ESWPn : R : MZ80A = Reset Memory Swap (MZ80A)
// E014 = CS_E5n : R/W : MZ80A/700 = Normal CRT display (in Video Controller)
// E015 = CS_E6n : R/W : MZ80A/700 = Reverse CRT display (in Video Controller)
// E200 - E2FF = : R/W : MZ80A/700 = VRAM roll up/roll down.
// E800 - EFFF = : R/W : MZ80K/A/700 = User ROM socket or DD Eprom (MZ700)
// F000 - F7FF = : R/W : MZ80K/A/700 = Floppy Disk interface.
// F800 - FFFF = : R/W : MZ80K/A/700 = Floppy Disk interface.
//
// Chip Select map MZ800
//
// FC - FF = CS_PIOn : R/W : MZ800/MZ1500 = Z80 PIO Printer Interface
// F2 = CS_PSG0n : W : MZ800/MZ1500 = Programable Sound Generator, MZ-800 = Mono, MZ-1500 = Left Channel
// F3 = CS_PSG1n : W : MZ1500 = Programable Sound Generator, MZ-1500 = Right Channel
// E9 = CS_PSG(X)n: W : MZ1500 = Simultaneous write to both PSG's.
// F0 - F1 = CS_JOYSTK : R : MZ800 = Joystick 1 and 2
// CC = CS_GWF : W : MZ800 = CRTC GWF Write format Register
// CD = CS_GRF : W : MZ800 = CRTC GRF Read format Register
// CE = CS_GDMD : W : MZ800 = CRTC GDMD Mode Register
// CF = CS_GCRTC : W : MZ800 = CRTC GCRTC Control Register
// D4 - D7 = CS
// D000 - DFFF
// MZ700/MZ800 memory mode switch?
//
// MZ-700 MZ-800
// |0000:0FFF|1000:1FFF|1000:CFFF|C000:CFFF|D000:FFFF |0000:7FFF|1000:1FFF|2000:7FFF|8000:BFFF|C000:CFFF|C000:DFFF|E000:FFFF
// -------------------------------------------------- ----------------------------------------------------------------------
// OUT 0xE0 = |DRAM | | | | |DRAM | | | | | |
// OUT 0xE1 = | | | | |DRAM | | | | | | |DRAM
// OUT 0xE2 = |MONITOR | | | | |MONITOR | | | | | |
// OUT 0xE3 = | | | | |Memory Mapped I/O | | | | | | |Upper MONITOR ROM
// OUT 0xE4 = |MONITOR | |DRAM | |Memory Mapped I/O |MONITOR |CGROM |DRAM |VRAM | |DRAM |Upper MONITOR ROM
// OUT 0xE5 = | | | | |Inhibit | | | | | | |Inhibit
// OUT 0xE6 = | | | | |<return> | | | | | | |<return>
// IN 0xE0 = | |CGROM* | |VRAM* | | |CGROM | |VRAM | | |
// IN 0xE1 = | |DRAM | |DRAM | | |<return> | |DRAM | | |
//
// <return> = Return to the state prior to the complimentary command being invoked.
// * = MZ-800 host only.
// Macros to lookup and test to see if a given memory block or IO byte is of a given type. Also macros to read/write to the memory block and IO byte.
#define MEMORY_BLOCK_GRANULARITY 0x800
#define MEMORY_BLOCK_SLOTS (0x10000 / MEMORY_BLOCK_GRANULARITY)
#define MEMORY_BLOCK_MASK (0x10000 - MEMORY_BLOCK_GRANULARITY)
#define MEMORY_BLOCK_SHIFT 11
#define getPageData(a) (Z80Ctrl->page[(a & 0xF800) >> MEMORY_BLOCK_SHIFT])
#define getIOPageData(a) (Z80Ctrl->iopage[(a & 0xFFFF])
#define getPageType(a, mask) (getPageData(a) & mask)
#define getPageAddr(a, mask) ((getPageData(a) & mask) + (a & (MEMORY_BLOCK_GRANULARITY-1)))
#define getIOPageType(a, mask) (getIOPageData(a) & mask)
#define getIOPageAddr(a, mask) (getIOPageData(a) & mask)
#define realAddress(a) (Z80Ctrl->page[getPageAddr(a, MEMORY_TYPE_REAL_MASK)])
#define realPort(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_MASK)
#define isPhysicalRAM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_RAM))
#define isPhysicalVRAM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_VRAM))
#define isPhysicalROM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_ROM))
#define isPhysicalMemory(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_ROM | MEMORY_TYPE_PHYSICAL_RAM | MEMORY_TYPE_PHYSICAL_VRAM))])
#define isPhysicalHW(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_HW))
#define isPhysical(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_HW | MEMORY_TYPE_PHYSICAL_ROM | MEMORY_TYPE_PHYSICAL_RAM | MEMORY_TYPE_PHYSICAL_VRAM)))
#define isPhysicalIO(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_PHYSICAL_HW)
#define isVirtualRAM(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_RAM))
#define isVirtualROM(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_ROM))
#define isVirtualMemory(a) (getPageType(a, (MEMORY_TYPE_VIRTUAL_ROM | MEMORY_TYPE_VIRTUAL_RAM)))
#define isVirtualHW(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_HW))
#define isVirtualIO(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_VIRTUAL_HW)
#define isHW(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_HW | MEMORY_TYPE_VIRTUAL_HW)))
#define readVirtualRAM(a) (Z80Ctrl->memory[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ])
#define readVirtualROM(a) (Z80Ctrl->memory[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) + Z80_VIRTUAL_RAM_SIZE ])
#define writeVirtualRAM(a, d) { Z80Ctrl->memory[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ] = d; }
#define setMemoryType(_block_,_type_,_addr_) { Z80Ctrl->page[_block_] = _type_ | _addr_; }
#define backupMemoryType(_block_) { Z80Ctrl->shadowPage[_block_] = Z80Ctrl->page[_block_]; }
#define restoreMemoryType(_block_) { Z80Ctrl->page[_block_] = Z80Ctrl->shadowPage[_block_]; }
#define IO_ADDR_E0 0xE0
#define IO_ADDR_E1 0xE1
#define IO_ADDR_E2 0xE2
#define IO_ADDR_E3 0xE3
#define IO_ADDR_E4 0xE4
#define IO_ADDR_E5 0xE5
#define IO_ADDR_E6 0xE6
#define IO_ADDR_E7 0xE7
enum Z80_RUN_STATES {
Z80_STOP = 0x00,
Z80_STOPPED = 0x01,
Z80_PAUSE = 0x02,
Z80_PAUSED = 0x03,
Z80_CONTINUE = 0x04,
Z80_RUNNING = 0x05,
};
enum Z80_MEMORY_PROFILE {
USE_PHYSICAL_RAM = 0x00,
USE_VIRTUAL_RAM = 0x01
};
typedef struct {
// Main memory, linear but indexed as though it were banks in 1K pages.
uint8_t memory[Z80_VIRTUAL_MEMORY_SIZE];
// Page pointer map.
//
// Each pointer points to a byte or block of bytes in the Z80 Memory frame, 64K Real + Banked.
// This is currently set at a block of size 0x800 per memory pointer for the MZ-700.
// The LSB of the pointer is a direct memory index to a byte or block of bytes, the upper byte of the pointer indicates type of memory space.
// 0x80<FFFFFF> - physical host RAM
// 0x40<FFFFFF> - physical host ROM
// 0x20<FFFFFF> - physical host VRAM
// 0x10<FFFFFF> - physical host hardware
// 0x08<FFFFFF> - virtual host RAM
// 0x04<FFFFFF> - virtual host ROM
// 0x02<FFFFFF> - virtual host hardware
// 16bit Input Address -> map -> Pointer to 24bit memory address + type flag.
// -> Pointer+<low bits of address> to 24bit memory address + type flag.
uint32_t page[MEMORY_BLOCK_SLOTS];
uint32_t shadowPage[MEMORY_BLOCK_SLOTS];
// I/O Page map.
//
// This is a map to indicate the use of the I/O page and allow any required remapping.
// <0x80>FF<I/O Address> - physical host hardware
// <0x40>FF<I/O Address> - virtual host hardware
// 16bit Input Address -> map -> Actual 16bit address to use + type flag.
uint32_t iopage[65536];
// Default page mode configured. This value reflects the default page and iotable map.
uint8_t defaultPageMode;
// Refresh DRAM mode. 1 = Refresh, 0 = No refresh. Only applicable when running code in virtual Kernel RAM.
uint8_t refreshDRAM;
// Inhibit mode is where certain memory ranges are inhibitted. The memory page is set to inhibit and this flag
// blocks actions which arent allowed during inhibit.
uint8_t inhibitMode;
// Address caching. Used to minimise instruction length sent to CPLD.
uint16_t z80PrevAddr;
uint16_t z80PrevPort;
// Keyboard strobe and data. Required to detect hotkey press.
uint8_t keyportStrobe;
uint8_t keyportShiftCtrl;
uint8_t keyportHotKey;
// Governor is the delay in a 32bit loop per Z80 opcode, used to govern execution speed when using virtual memory.
// This mechanism will eventually be tied into the M/T-state calculation for a more precise delay, but at the moment,
// with the Z80 assigned to an isolated CPU, it allows time sensitive tasks such as the tape recorder to work.
// The lower the value the faster the CPU speed.
uint32_t cpuGovernorDelay;
} t_Z80Ctrl;
// IOCTL structure for passing data from user space to driver to perform commands.
//
struct z80_addr {
uint32_t start;
uint32_t end;
uint32_t size;
};
struct z80_ctrl {
uint16_t pc;
};
struct speed {
uint32_t speedMultiplier;
};
struct cpld_ctrl {
uint32_t cmd;
};
struct ioctlCmd {
int32_t cmd;
union {
struct z80_addr addr;
struct z80_ctrl z80;
struct speed speed;
struct cpld_ctrl cpld;
};
};
// Prototypes.
void setupMemory(enum Z80_MEMORY_PROFILE mode);
#endif

View File

@@ -1,57 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: z80menu.c
// Created: Oct 2022
// Author(s): Philip Smart
// Description: Z80 User Menu
// This file contains the methods used to present a menu of options to a user to aid
// in configuration and load/save of applications and data.
// Credits:
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
//
// History: Oct 2022 - Initial write of the z80 kernel driver software.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/time.h>
#include "z80io.h"
#include "z80menu.h"
#include <gpio_table.h>
#include <asm/io.h>
#include <infinity2m/gpio.h>
#include <infinity2m/registers.h>
void z80menu(void)
{
// Locals.
}

View File

@@ -1,44 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: z80menu.h
// Created: Oct 2022
// Author(s): Philip Smart
// Description: Z80 User Interface Menu
// This file contains the declarations required to provide a menu system allowing a
// user to configure and load/save applications/data.
// Credits:
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
//
// History: Oct 2022 - Initial write of the z80 kernel driver software.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef Z80MENU_H
#define Z80MENU_H
#ifdef __cplusplus
extern "C" {
#endif
// Function definitions.
//
void z80menu(void);
#ifdef __cplusplus
}
#endif
#endif // Z80MENU_H

View File

@@ -1,32 +0,0 @@
MODEL := MZ2000
#MODEL := MZ700
#MODEL := MZ80A
KERNEL := $(PWD)/../../../linux/kernel
FUSIONX := $(PWD)/../..
CROSS := arm-linux-gnueabihf-
ccflags-y += -O2 -I${src}/Zeta/API -I${src}/Z80/API -I${KERNEL}/drivers/sstar/include -I${KERNEL}/drivers/sstar/include/infinity2m -I${KERNEL}/drivers/sstar/gpio/infinity2m
CTRLINC += -IZeta/API -IZ80/API
obj-m += z80drv.o
z80drv-objs += $(MODEL)/z80driver.o Z80.o $(MODEL)/z80io.o $(MODEL)/z80menu.o # emumz.o sharpmz.o osd.o
z80drv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/gpio_table.o
z80drv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/mhal_gpio.o
z80drv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/mhal_pinmux.o
z80drv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/padmux_tables.o
all:
@echo "Build driver for host: $(MODEL)"
@echo ""
make -C $(KERNEL) ARCH=arm CROSS_COMPILE=$(CROSS) M="$(PWD)" modules
$(CROSS)gcc $(CTRLINC) $(MODEL)/z80ctrl.c -o z80ctrl
install:
@echo "Copy kernel driver..."
@cp z80drv.ko $(FUSIONX)/modules/
@echo "Copy z80ctrl app..."
@cp z80ctrl $(FUSIONX)/bin/
clean:
make -C $(KERNEL) M=$(PWD) clean

61
software/FusionX/src/ttymz/Makefile vendored Normal file
View File

@@ -0,0 +1,61 @@
# Select the target host.
#MODEL := MZ2000
#MODEL := MZ700
#MODEL := MZ80A
#MODEL := PCW8XXX
#MODEL := PCW9XXX
KERNEL := $(PWD)/../../../linux/kernel
FUSIONX := $(PWD)/../..
CROSS := arm-linux-gnueabihf-
CTRLINC = -IZeta/API -IZ80/API -DTARGET_HOST_$(MODEL)=1
ccflags-y = -O2 -I${KERNEL}/drivers/sstar/include -I${KERNEL}/drivers/sstar/include/infinity2m -I${KERNEL}/drivers/sstar/gpio/infinity2m -D__KERNEL_DRIVER__ -DTARGET_HOST_$(MODEL)=1
ifeq ($(DEBUG),y)
ccflags-y += -DTTYMZ_DEBUG
endif
obj-m += ttymzdrv.o
ttymzdrv-objs += ttymz.o z80io.o sharpmz.o
ttymzdrv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/gpio_table.o
ttymzdrv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/mhal_gpio.o
ttymzdrv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/mhal_pinmux.o
ttymzdrv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/padmux_tables.o
all:
@echo "Specify target host, ie. make <host>"
@echo "Supported hosts: MZ80A, MZ700, MZ2000, PCW8XXX, PCW9XXX"
MZ80A: MODEL_MZ80A
MZ700: MODEL_MZ700
MZ2000: MODEL_MZ2000
PCW8XXX: MODEL_PCW8XXX
PCW9XXX: MODEL_PCW9XXX
MODEL_MZ80A:
$(MAKE) MODEL=MZ80A BUILD_MZ80A
MODEL_MZ700:
$(MAKE) MODEL=MZ700 BUILD_MZ700
MODEL_MZ2000:
$(MAKE) MODEL=MZ2000 BUILD_MZ2000
MODEL_PCW8XXX:
$(MAKE) MODEL=PCW8XXX BUILD_PCW8XXX
MODEL_PCW9XXX:
$(MAKE) MODEL=PCW8XXX BUILD_PCW9XXX
BUILD_MZ80A: kmod
BUILD_MZ700: kmod
BUILD_MZ2000: kmod
BUILD_PCW8XXX: kmod
BUILD_PCW9XXX: kmod
kmod:
@echo ""
@echo "Build TTYMZ driver for host: $(MODEL)"
make -C $(KERNEL) ARCH=arm CROSS_COMPILE=$(CROSS) M="$(PWD)" modules
install:
@echo "Copy kernel driver..."
@cp ttymzdrv.ko $(FUSIONX)/modules/
clean:
make -C $(KERNEL) M=$(PWD) clean
@rm -f ttymz

File diff suppressed because it is too large Load Diff

445
software/FusionX/src/ttymz/sharpmz.h vendored Executable file
View File

@@ -0,0 +1,445 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: sharpmz.c
// Created: February 2023
// Version: v1.0
// Author(s): Philip Smart
// Description: Sharp MZ Interface Library.
// This file contains methods which allow the Linux TTY driver to access and control the
// Sharp MZ series computer hardware.
//
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: v1.0 Feb 2023 - Initial write of the Sharp MZ series hardware interface software.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef SHARPMZ_H
#define SHARPMZ_H
#ifdef __cplusplus
extern "C" {
#endif
// Build time target. Overrides if compile time definition given.
#if defined(TARGET_HOST_MZ700)
#define TARGET_HOST_MZ700 1
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_MZ80A 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_MZ2000)
#define TARGET_HOST_MZ2000 1
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ80A 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_MZ80A)
#define TARGET_HOST_MZ80A 1
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_PCW8XXX) || defined(TARGET_HOST_PCW9XXX)
#define TARGET_HOST_PCW 1
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ80A 0
#else
#define TARGET_HOST_MZ700 0 // Target compilation for an MZ700
#define TARGET_HOST_MZ2000 0 // MZ2000
#define TARGET_HOST_MZ80A 0 // MZ80A
#define TARGET_HOST_PCW 0 // Amstrad PCW8XXX/9XXX
#endif
// Video display constants.
#define VC_MAX_ROWS 25 // Maximum number of rows on display.
#if defined(TARGET_HOST_MZ700)
#define VC_MAX_COLUMNS 40 // Maximum number of columns on display.
#else
#define VC_MAX_COLUMNS 80 // Maximum number of columns on display.
#endif
#define VC_MAX_BUFFER_ROWS 50 // Maximum number of backing store rows for scrollback feature.
#define VC_DISPLAY_BUFFER_SIZE VC_MAX_COLUMNS * VC_MAX_BUFFER_ROWS // Size of the display buffer for scrollback.
// Keyboard constants.
#define KEYB_AUTOREPEAT_INITIAL_TIME 800 // Time in milliseconds before starting autorepeat.
#define KEYB_AUTOREPEAT_TIME 100 // Time in milliseconds between auto repeating characters.
#define KEYB_FLASH_TIME 350 // Time in milliseconds for the cursor flash change.
#define CURSOR_THICK_BLOCK 0x43 // Thick block cursor for lower case CAPS OFF
#define CURSOR_BLOCK 0xEF // Block cursor for SHIFT Lock.
#define CURSOR_UNDERLINE 0x3E // Thick underscore for CAPS Lock.
#define MAX_KEYB_BUFFER_SIZE 32 // Maximum size of the keyboard buffer.
// Audio constants.
#define TIMER_8253_MZ80A_FREQ 2000000 // Base input frequency of Timer 0 for square wave generation.
#define TIMER_8253_MZ700_FREQ 768000 // Base input frequency of Timer 0 for square wave generation.
// Base addresses and sizes within the Video Controller.
#define VIDEO_BASE_ADDR 0x000000 // Base address of the Video Controller.
#define VIDEO_VRAM_BASE_ADDR VIDEO_BASE_ADDR + 0x00D000 // Base address of the character video RAM using direct addressing.
#define VIDEO_VRAM_SIZE 0x800 // Size of the video RAM.
#define VIDEO_ARAM_BASE_ADDR VIDEO_BASE_ADDR + 0x00D800 // Base address of the character attribute RAM using direct addressing.
#define VIDEO_ARAM_SIZE 0x800 // Size of the attribute RAM.
// Video Module control bits.
#define VMMODE_MASK 0xF8 // Mask to mask out video mode.
#define VMMODE_MZ80K 0x00 // Video mode = MZ80K
#define VMMODE_MZ80C 0x01 // Video mode = MZ80C
#define VMMODE_MZ1200 0x02 // Video mode = MZ1200
#define VMMODE_MZ80A 0x03 // Video mode = MZ80A
#define VMMODE_MZ700 0x04 // Video mode = MZ700
#define VMMODE_MZ800 0x05 // Video mode = MZ800
#define VMMODE_MZ1500 0x06 // Video mode = MZ1500
#define VMMODE_MZ80B 0x07 // Video mode = MZ80B
#define VMMODE_MZ2000 0x08 // Video mode = MZ2000
#define VMMODE_MZ2200 0x09 // Video mode = MZ2200
#define VMMODE_MZ2500 0x0A // Video mode = MZ2500
#define VMMODE_80CHAR 0x80 // Enable 80 character display.
#define VMMODE_80CHAR_MASK 0x7F // Mask to filter out display width control bit.
#define VMMODE_COLOUR 0x20 // Enable colour display.
#define VMMODE_COLOUR_MASK 0xDF // Mask to filter out colour control bit.
// Sharp MZ colour attributes.
#define VMATTR_FG_BLACK 0x00 // Foreground black character attribute.
#define VMATTR_FG_BLUE 0x10 // Foreground blue character attribute.
#define VMATTR_FG_RED 0x20 // Foreground red character attribute.
#define VMATTR_FG_PURPLE 0x30 // Foreground purple character attribute.
#define VMATTR_FG_GREEN 0x40 // Foreground green character attribute.
#define VMATTR_FG_CYAN 0x50 // Foreground cyan character attribute.
#define VMATTR_FG_YELLOW 0x60 // Foreground yellow character attribute.
#define VMATTR_FG_WHITE 0x70 // Foreground white character attribute.
#define VMATTR_FG_MASKOUT 0x8F // Mask to filter out foreground attribute.
#define VMATTR_FG_MASKIN 0x70 // Mask to filter out foreground attribute.
#define VMATTR_BG_BLACK 0x00 // Background black character attribute.
#define VMATTR_BG_BLUE 0x01 // Background blue character attribute.
#define VMATTR_BG_RED 0x02 // Background red character attribute.
#define VMATTR_BG_PURPLE 0x03 // Background purple character attribute.
#define VMATTR_BG_GREEN 0x04 // Background green character attribute.
#define VMATTR_BG_CYAN 0x05 // Background cyan character attribute.
#define VMATTR_BG_YELLOW 0x06 // Background yellow character attribute.
#define VMATTR_BG_WHITE 0x07 // Background white character attribute.
#define VMATTR_BG_MASKOUT 0xF8 // Mask to filter out background attribute.
#define VMATTR_BG_MASKIN 0x07 // Mask to filter out background attribute.
// Sharp MZ constants.
//
#define MBADDR_KEYPA 0xE000 // Mainboard 8255 Port A
#define MBADDR_KEYPB 0xE001 // Mainboard 8255 Port B
#define MBADDR_KEYPC 0xE002 // Mainboard 8255 Port C
#define MBADDR_KEYPF 0xE003 // Mainboard 8255 Mode Control
#define MBADDR_CSTR 0xE002 // Mainboard 8255 Port C
#define MBADDR_CSTPT 0xE003 // Mainboard 8255 Mode Control
#define MBADDR_CONT0 0xE004 // Mainboard 8253 Counter 0
#define MBADDR_CONT1 0xE005 // Mainboard 8253 Counter 1
#define MBADDR_CONT2 0xE006 // Mainboard 8253 Counter 1
#define MBADDR_CONTF 0xE007 // Mainboard 8253 Mode Control
#define MBADDR_SUNDG 0xE008 // Register for reading the tempo timer status (cursor flash). horizontal blank and switching sound on/off.
#define MBADDR_TEMP 0xE008 // As above, different name used in original source when writing.
#define MBADDR_MEMSW 0xE00C // Memory swap, 0000->C000, C000->0000
#define MBADDR_MEMSWR 0xE010 // Reset memory swap.
#define MBADDR_NRMDSP 0xE014 // Return display to normal.
#define MBADDR_INVDSP 0xE015 // Invert display.
#define MBADDR_SCLDSP 0xE200 // Hardware scroll, a read to each location adds 8 to the start of the video access address therefore creating hardware scroll. 00 - reset to power up
#define MBADDR_SCLBASE 0xE2 // High byte scroll base.
#define MBADDR_DSPCTL 0xDFFF // Display 40/80 select register (bit 7)
//Common character definitions.
#define SCROLL 0x01 // Set scroll direction UP.
#define BELL 0x07
#define ENQ 0x05
#define SPACE 0x20
#define TAB 0x09 // TAB ACROSS (8 SPACES FOR SD-BOARD)
#define CR 0x0D
#define LF 0x0A
#define FF 0x0C
#define DELETE 0x7F
#define BACKS 0x08
#define SOH 0x01 // For XModem etc.
#define EOT 0x04
#define ACK 0x06
#define NAK 0x15
#define NUL 0x00
//#define NULL 0x00
#define CTRL_A 0x01
#define CTRL_B 0x02
#define CTRL_C 0x03
#define CTRL_D 0x04
#define CTRL_E 0x05
#define CTRL_F 0x06
#define CTRL_G 0x07
#define CTRL_H 0x08
#define CTRL_I 0x09
#define CTRL_J 0x0A
#define CTRL_K 0x0B
#define CTRL_L 0x0C
#define CTRL_M 0x0D
#define CTRL_N 0x0E
#define CTRL_O 0x0F
#define CTRL_P 0x10
#define CTRL_Q 0x11
#define CTRL_R 0x12
#define CTRL_S 0x13
#define CTRL_T 0x14
#define CTRL_U 0x15
#define CTRL_V 0x16
#define CTRL_W 0x17
#define CTRL_X 0x18
#define CTRL_Y 0x19
#define CTRL_Z 0x1A
#define ESC 0x1B
#define CTRL_SLASH 0x1C
#define CTRL_LB 0x1B
#define CTRL_RB 0x1D
#define CTRL_CAPPA 0x1E
#define CTRL_UNDSCR 0x1F
#define CTRL_AT 0x00
#define FUNC1 0x80
#define FUNC2 0x81
#define FUNC3 0x82
#define FUNC4 0x83
#define FUNC5 0x84
#define FUNC6 0x85
#define FUNC7 0x86
#define FUNC8 0x87
#define FUNC9 0x88
#define FUNC10 0x89
#define PAGEUP 0xE0
#define PAGEDOWN 0xE1
#define CURHOMEKEY 0xE2
#define ALPHAGRAPHKEY 0xE3
#define HOTKEY_ORIGINAL 0xE8
#define HOTKEY_RFS80 0xE9
#define HOTKEY_RFS40 0xEA
#define HOTKEY_TZFS 0xEB
#define HOTKEY_LINUX 0xEC
#define NOKEY 0xF0
#define CURSRIGHT 0xF1
#define CURSLEFT 0xF2
#define CURSUP 0xF3
#define CURSDOWN 0xF4
#define DBLZERO 0xF5
#define INSERT 0xF6
#define CLRKEY 0xF7
#define HOMEKEY 0xF8
#define ENDKEY 0xF9
#define ANSITGLKEY 0xFA
#define BREAKKEY 0xFB
#define GRAPHKEY 0xFC
#define ALPHAKEY 0xFD
#define DEBUGKEY 0xFE // Special key to enable debug features such as the ANSI emulation.
// Macros.
//
// The read/write hardware macros are created in order to allow this module to be used with the zSoft/zOS platform
// as well as the FusionX platform. The ZPU writes direct to memory, the FusionX sends via SPI.
#define WRITE_HARDWARE(__force__,__addr__,__data__)\
{\
if(!ctrl.suspendIO || __force__ == 1)\
{\
SPI_SEND32((uint32_t)__addr__ << 16 | __data__ << 8 | CPLD_CMD_WRITE_ADDR);\
}\
}
#define READ_HARDWARE_INIT(__force__,__addr__)\
{\
if(!ctrl.suspendIO || __force__ == 1)\
{\
SPI_SEND32((uint32_t)__addr__ << 16 | 0x00 << 8 | CPLD_CMD_READ_ADDR);\
while(CPLD_READY() == 0);\
}\
}
#define READ_HARDWARE() (\
z80io_PRL_Read8(1)\
)
// Cursor flash mechanism control states.
//
enum CURSOR_STATES {
CURSOR_OFF = 0x00, // Turn the cursor off.
CURSOR_ON = 0x01, // Turn the cursor on.
CURSOR_RESTORE = 0x02, // Restore the saved cursor character.
CURSOR_FLASH = 0x03 // If enabled, flash the cursor.
};
// Cursor positioning states.
enum CURSOR_POSITION {
CURSOR_UP = 0x00, // Move the cursor up.
CURSOR_DOWN = 0x01, // Move the cursor down.
CURSOR_LEFT = 0x02, // Move the cursor left.
CURSOR_RIGHT = 0x03, // Move the cursor right.
CURSOR_COLUMN = 0x04, // Set cursor column to absolute value.
CURSOR_NEXT_LINE = 0x05, // Move the cursor to the beginning of the next line.
CURSOR_PREV_LINE = 0x06, // Move the cursor to the beginning of the previous line.
};
// Keyboard operating states according to buttons pressed.
//
enum KEYBOARD_MODES {
KEYB_LOWERCASE = 0x00, // Keyboard in lower case mode.
KEYB_CAPSLOCK = 0x01, // Keyboard in CAPS lock mode.
KEYB_SHIFTLOCK = 0x02, // Keyboard in SHIFT lock mode.
KEYB_CTRL = 0x03, // Keyboard in Control mode.
KEYB_GRAPHMODE = 0x04, // Keyboard in Graphics mode.
};
// Keyboard dual key modes. This is for hosts whose keyboards dont support the basic key set or when a key needs to have dual functionality.
enum KEYBOARD_DUALMODES {
KEYB_DUAL_NONE = 0x00, // No dual key modes active.
KEYB_DUAL_GRAPH = 0x01, // MZ-80A, no Alpha key, only Graph, so double function required.
};
// Mapping table from Sharp MZ80A Ascii to real Ascii.
//
typedef struct {
uint8_t asciiCode;
} t_asciiMap;
// Mapping table from Ascii to Sharp MZ display code.
//
typedef struct {
uint8_t dispCode;
} t_dispCodeMap;
// Mapping table from keyboard scan codes to Sharp MZ keys.
//
typedef struct {
uint8_t scanCode[80];
} t_scanCodeMap;
// Mapping table of a sharp keycode to an ANSI escape sequence string.
//
typedef struct {
uint8_t key;
const char* ansiKeySequence;
} t_ansiKeyMap;
// Structure to maintain the Sharp MZ display output parameters and data.
//
typedef struct {
uint8_t displayAttr; // Attributes for each character in the display.
uint16_t backingRow; // Maximum backing RAM row, allows for a larger virtual backing display with the physical display acting as a window.
// Location on the physical display to output data. displayCol is also used in the backing store.
uint8_t displayRow;
uint8_t displayCol;
// History and backing display store. The physical display outputs a portion of this backing store.
uint8_t displayCharBuf[VC_DISPLAY_BUFFER_SIZE];
uint8_t displayAttrBuf[VC_DISPLAY_BUFFER_SIZE];
// Maxims, dynamic to allow for future changes.
uint8_t maxBackingRow;
uint8_t maxDisplayRow;
uint8_t maxBackingCol;
// Features.
uint8_t lineWrap; // Wrap line at display edge (1) else stop printing at display edge.
uint8_t useAnsiTerm; // Enable (1) Ansi Terminal Emulator, (0) disable.
uint8_t inDebug; // Prevent recursion when outputting debug information.
} t_displayBuffer;
// Structure for maintaining the Sharp MZ keyboard parameters and data. Used to retrieve and map a key along with associated
// attributes such as cursor flashing.
//
typedef struct {
uint8_t scanbuf[2][10];
uint8_t keydown[10];
uint8_t keyup[10];
uint8_t keyhold[10];
uint32_t holdTimer;
uint8_t breakKey; // Break key pressed.
uint8_t ctrlKey; // Ctrl key pressed.
uint8_t shiftKey; // Shift key pressed.
uint8_t repeatKey;
uint8_t autorepeat;
enum KEYBOARD_MODES mode; // Keyboard mode and index into mapping table for a specific map set.
enum KEYBOARD_DUALMODES dualmode; // Keyboard dual key override modes.
uint8_t keyBuf[MAX_KEYB_BUFFER_SIZE]; // Keyboard buffer.
uint8_t keyBufPtr; // Pointer into the keyboard buffer for stored key,
uint8_t cursorOn; // Flag to indicate Cursor is switched on.
uint8_t displayCursor; // Cursor being displayed = 1
uint32_t flashTimer; // Timer to indicate next flash time for cursor.
} t_keyboard;
// Structure for maintaining the Sharp MZ Audio parameters and data.
typedef struct {
uint32_t audioStopTimer; // Timer to disable audio once elapsed period has expired. Time in ms.
} t_audio;
// Structure for module control parameters.
typedef struct {
uint8_t suspendIO; // Suspend physical I/O.
uint8_t debug; // Enable debugging features.
} t_control;
// Structure to maintain the Ansi Terminal Emulator state and parameters.
//
typedef struct {
enum {
ANSITERM_ESC,
ANSITERM_BRACKET,
ANSITERM_PARSE,
} state; // States and current state of the FSM parser.
uint8_t charcnt; // Number of characters read into the buffer.
uint8_t paramcnt; // Number of parameters parsed and stored.
uint8_t setDisplayMode; // Display mode command detected.
uint8_t setExtendedMode; // Extended mode command detected.
uint8_t charbuf[80]; // Storage for the parameter characters as they are received.
uint16_t param[10]; // Parsed paraemters.
uint8_t saveRow; // Store the current row when requested.
uint8_t saveCol; // Store the current column when requested.
uint8_t saveDisplayRow; // Store the current display buffer row when requested.
} t_AnsiTerm;
// Application execution constants.
//
// Prototypes.
//
uint8_t mzInitMBHardware(void);
uint8_t mzInit(void);
void mzBeep(uint32_t, uint32_t);
uint8_t mzMoveCursor(enum CURSOR_POSITION, uint8_t);
uint8_t mzSetCursor(uint8_t, uint8_t);
int mzPutChar(char);
int mzPutRaw(char);
uint8_t mzSetAnsiAttribute(uint8_t);
int mzAnsiTerm(char);
int mzPrintChar(char);
uint8_t mzFlashCursor(enum CURSOR_STATES);
uint8_t mzPushKey(char *);
int mzGetKey(uint8_t);
int mzGetChar(void);
void mzClearDisplay(uint8_t, uint8_t);
void mzClearLine(int, int, int, uint8_t);
uint8_t mzGetDisplayWidth(void);
uint8_t mzSetDisplayWidth(uint8_t);
uint8_t mzSetMachineVideoMode(uint8_t);
void mzRefreshDisplay(void);
uint8_t mzScrollUp(uint8_t, uint8_t, uint8_t);
uint8_t mzScrollDown(uint8_t);
void mzDebugOut(uint8_t, uint8_t);
void mzSuspendIO(void);
void mzResumeIO(void);
void mzWriteString(uint8_t, uint8_t, char *, int);
void mzService(void);
// Getter/Setter methods!
#ifdef __cplusplus
}
#endif
#endif // SHARPMZ_H

View File

@@ -0,0 +1,914 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: ttymz.c
// Created: Feb 2023
// Author(s): Philip Smart
// Description: Sharp MZ TTY
// This file contains the methods used to create a linux tty device driver using the
// host Sharp keyboard and screen as input/output.
// This driver forms part of the FusionX developments and allows a user sitting at the
// Sharp MZ Console to access the underlying FusionX Linux SOM.
// Credits: Credits to tiny_tty Greg Kroah-Hartman (greg@kroah.com) and Linux pty which were
// used as base and reference in creating this driver.
//
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Feb 2023 - v1.0 Initial write of the Sharp MZ tty driver software.
// Added suspend I/O logic. This is necessary as I want to enable
// switching between a Linux session and a Z80 session, the idea
// being the TTY will continue to run within the mirrored framebuffer
// and when reselected, refresh the hardware screen.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#define _GNU_SOURCE
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <linux/fcntl.h>
#include <linux/kprobes.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/major.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#include <linux/bitops.h>
#include <linux/devpts_fs.h>
#include <linux/mutex.h>
#include <linux/poll.h>
#include <linux/seq_file.h>
#include <linux/version.h>
#include "z80io.h"
#include "sharpmz.h"
#include "ttymz.h"
// Meta Information.
MODULE_LICENSE(DRIVER_LICENSE);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
MODULE_VERSION(DRIVER_VERSION);
MODULE_INFO(versiondate, DRIVER_VERSION_DATE);
MODULE_INFO(copyright, DRIVER_COPYRIGHT);
// Device control variables.
static t_TTYMZ *ttymzConnections[SHARPMZ_TTY_MINORS]; // Initially all NULL, no devices connected.
static t_TTYMZCtrl ttymzCtrl;
// Read method. Keys entered on the host keyboard are sent to the user process via this method.
//
static void ttymz_read(struct tty_struct *tty, char data)
{
// Locals.
struct tty_port *port;
// Sanity check.
if (!tty)
return;
// Get the port, needed to push data onto the ringbuffer for delivery to the user.
port = tty->port;
// If there is no room, push the characters to the user. Add the new character and push again.
if (!tty_buffer_request_room(port, 1))
tty_flip_buffer_push(port);
tty_insert_flip_char(port, data, TTY_NORMAL);
tty_flip_buffer_push(port);
return;
}
// Method to receive data from the user application to be written onto the Sharp or SSD202 framebuffer.
//
static int ttymz_write(struct tty_struct *tty, const unsigned char *buffer, int count)
{
t_TTYMZ *ttymz = tty->driver_data;
int idx;
int retval = count;
if (!ttymz)
return -ENODEV;
// Lock out other processes.
mutex_lock(&ttymz->mutex);
// Sanity check, ensure port is open.
if (!ttymz->open_count)
goto exit;
// Send the characters to the Sharp MZ interface for display.
for (idx = 0; idx < count; ++idx)
{
mzPrintChar(buffer[idx]);
}
exit:
mutex_unlock(&ttymz->mutex);
return retval;
}
// Method to indicate to the kernel how much buffer space is left in the device.
//
#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0))
static int ttymz_write_room(struct tty_struct *tty)
#else
static unsigned int ttymz_write_room(struct tty_struct *tty)
#endif
{
// Locals.
t_TTYMZ *ttymz = tty->driver_data;
int room = -EINVAL;
// Sanity check.
if(!ttymz)
return -ENODEV;
if(tty->stopped)
return 0;
mutex_lock(&ttymz->mutex);
if(!ttymz->open_count)
{
// Port was not opened
goto exit;
}
// Calculate how much room is left in the device
room = 255;
exit:
mutex_unlock(&ttymz->mutex);
return room;
}
// Timer methods
//
// Timer to scan the Sharp MZ host keyboard and detect key presses. Any key press detected results
// in a character being pushed into the kernel ringbuffer for delivery to the user application.
//
static void ttymz_keyboardTimer(unsigned long timerAddr)
{
// Locals.
t_TTYMZ *ttymz = (t_TTYMZ *)timerAddr;
struct tty_struct *tty;
int key;
// Sanity check.
if (!ttymz)
return;
// Once sanitised, get the tty struct from the given physical address, needed to reset the timer and to
// push data to the client.
tty = ttymz->tty;
// Scan the Sharp MZ host keyboard, push any character received. Mode 2 = Ansi scan without wait.
if((key = mzGetKey(2)) != -1)
{
switch(key)
{
// Hotkeys, send to the Arbiter, not the user process.
case HOTKEY_ORIGINAL:
case HOTKEY_RFS80:
case HOTKEY_RFS40:
case HOTKEY_TZFS:
case HOTKEY_LINUX:
//pr_info("Hotkey detected:%02x\n", key);
ttymzCtrl.hotkey = (uint32_t)key;
sendSignal(ttymzCtrl.arbTask, SIGUSR2);
break;
default:
//pr_info("%d, %08x ", key, (size_t)tty->port);
ttymz_read(tty, (char)key);
break;
}
}
// Resubmit the timer again.
ttymz->timerKeyboard.expires = jiffies + 1;
add_timer(&ttymz->timerKeyboard);
}
//
// Display service timer, used for scheduling tasks within the display driver.
//
static void ttymz_displayTimer(unsigned long timerAddr)
{
// Locals.
t_TTYMZ *ttymz = (t_TTYMZ *)timerAddr;
struct tty_struct *tty;
// Sanity check.
if (!ttymz)
return;
// Once sanitised, get the tty struct from the given physical address, needed to reset the timer and to
// push data to the client.
tty = ttymz->tty;
// Call the display service routine.
mzService();
// Resubmit the timer again.
ttymz->timerDisplay.expires = jiffies + 1;
add_timer(&ttymz->timerDisplay);
}
// Device open.
//
// When a user space application open's the tty device driver, this function is called
// to initialise and allocate any required memory or hardware prior to servicing requests from the
// user space application.
static int ttymz_open(struct tty_struct *tty, struct file *file)
{
// Locals.
t_TTYMZ *ttymz;
int index;
int ret = 0;
struct winsize ws;
struct task_struct *task = get_current();
// Initialize the pointer in case something fails
tty->driver_data = NULL;
// Get the serial object associated with this tty pointer
index = tty->index;
ttymz = ttymzConnections[index];
if(ttymz == NULL)
{
// First time accessing this device, let's create it
ttymz = kmalloc(sizeof(*ttymz), GFP_KERNEL);
if (!ttymz)
return -ENOMEM;
mutex_init(&ttymz->mutex);
ttymz->open_count = 0;
ttymzConnections[index] = ttymz;
}
mutex_lock(&ttymz->mutex);
// Save our structure within the tty structure
tty->driver_data = ttymz;
ttymz->tty = tty;
ttymz->tty->port = tty->port;
// Setup the default terminal size based on compilation (ie. 40/80 cols).
ws.ws_row = VC_MAX_ROWS;
ws.ws_col = VC_MAX_COLUMNS;
tty->winsize = ws;
// Port opened, perform initialisation.
//
++ttymz->open_count;
if(ttymz->open_count == 1 && tty->index == 0)
{
// Create the keyboard sweep timer and submit it
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
init_timer(&ttymz->timerKeyboard);
ttymz->timerKeyboard.data = (unsigned long)ttymz;
ttymz->timerKeyboard.function = ttymz_keyboardTimer;
#else
timer_setup(timer, (void *)ttymz_keyboardTimer, (unsigned long)ttymz);
timer->function = (void *)ttymz_keyboardTimer;
#endif
// 10 ms sweep timer.
ttymz->timerKeyboard.expires = jiffies + 1;
add_timer(&ttymz->timerKeyboard);
// Create the display periodic timer and submit it.
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
init_timer(&ttymz->timerDisplay);
ttymz->timerDisplay.data = (unsigned long)ttymz;
ttymz->timerDisplay.function = ttymz_displayTimer;
#else
timer_setup(timer, (void *)ttymz_keyboardTimer, (unsigned long)ttymz);
timer->function = (void *)ttymz_displayTimer;
#endif
// 10 ms service interval.
ttymz->timerDisplay.expires = jiffies + 1;
add_timer(&ttymz->timerDisplay);
} else
// SSD202 Framebuffer?
if(ttymz->open_count == 1 && tty->index == 1)
{
pr_info("SSD202 Framebuffer not yet implemented.\n");
ret = -EBUSY;
} else
// Control port is just opened, no associated hardware.
if(tty->index == 2)
{
// Arbiter connection?
if(ttymzCtrl.arbTask == NULL && strcmp(task->comm, ARBITER_NAME) == 0)
{
ttymzCtrl.arbTask = task;
pr_info("Sharpbiter: Registering Arbiter:%s\n", ttymzCtrl.arbTask->comm);
} else
if(ttymzCtrl.arbTask != NULL && strcmp(task->comm, ARBITER_NAME) == 0)
{
pr_info("Arbiter already registered, PID:%d\n", ttymzCtrl.arbTask->pid);
ret = -EBUSY;
}
}
mutex_unlock(&ttymz->mutex);
return(ret);
}
// Close helper method, performs the actual deallocation of resources for the open port.
//
static void do_close(t_TTYMZ *ttymz)
{
// Locals.
uint32_t idx;
struct task_struct *task = get_current();
mutex_lock(&ttymz->mutex);
if(!ttymz->open_count)
{
// Port was never opened
goto exit;
}
// Go through all the connections to find active connection.
for(idx = 0; idx < SHARPMZ_TTY_MINORS; idx++)
{
// Match the handle to find the index.
if(ttymz == ttymzConnections[idx])
{
// Active consoles, ie. host and framebuffer, close hardware and free up timers etc.
if(idx < 2)
{
// Shutdown hardware tasks to exit.
// Shut down our timers.
del_timer(&ttymz->timerKeyboard);
del_timer(&ttymz->timerDisplay);
} else
if(idx == 2)
{
// Is this the Arbiter de-registering?
if(ttymzCtrl.arbTask == task)
{
ttymzCtrl.arbTask = NULL;
pr_info("Arbiter stopped.\n");
}
// Free up the connection resources.
kfree(ttymzConnections[idx]);
ttymzConnections[idx] = NULL;
}
}
}
exit:
mutex_unlock(&ttymz->mutex);
}
// Device close.
//
// When a user space application terminates or closes the tty device driver, this function is called
// to close any open connections, memory and variables required to handle the user space application
// requests.
static void ttymz_close(struct tty_struct *tty, struct file *file)
{
// Locals.
t_TTYMZ *ttymz = tty->driver_data;
if (ttymz)
do_close(ttymz);
}
#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
static void ttymz_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
{
// Locals.
unsigned int cflag;
//PRINT_PROC_START();
cflag = tty->termios.c_cflag;
// Check that they really want us to change something
if (old_termios)
{
if ((cflag == old_termios->c_cflag) && (RELEVANT_IFLAG(tty->termios.c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag)))
{
return;
}
}
// As this is not a serial based TTY, most of the settings are ignored, they are here for reference
// and in-place if something is needed in future.
// Get the byte size
switch(cflag & CSIZE)
{
case CS5:
break;
case CS6:
break;
case CS7:
break;
default:
case CS8:
break;
}
// Determine the parity
if (cflag & PARENB)
if (cflag & PARODD)
{
;
}
else
{
;
}
else
{
;
}
// Figure out the stop bits requested
if (cflag & CSTOPB)
{
;
}
else
{
;
}
// Figure out the hardware flow control settings
if (cflag & CRTSCTS)
{
;
}
else
{
;
}
// Determine software flow control
// if we are implementing XON/XOFF, set the start and
// stop character in the device
if (I_IXOFF(tty) || I_IXON(tty))
{
//unsigned char stop_char = STOP_CHAR(tty);
//unsigned char start_char = START_CHAR(tty);
// If we are implementing INBOUND XON/XOFF
if(I_IXOFF(tty))
{
;
}
else
{
;
}
// if we are implementing OUTBOUND XON/XOFF
if(I_IXON(tty))
{
;
}
else
{
;
}
}
// Get the baud rate wanted
// baud = tty_get_baud_rate(tty));
return;
}
static int ttymz_tiocmget(struct tty_struct *tty)
{
// Locals.
t_TTYMZ *ttymz = tty->driver_data;
unsigned int result = 0;
unsigned int msr = ttymz->msr;
unsigned int mcr = ttymz->mcr;
//PRINT_PROC_START();
result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | // DTR is set
((mcr & MCR_RTS) ? TIOCM_RTS : 0) | // RTS is set
((mcr & MCR_LOOP) ? TIOCM_LOOP : 0) | // LOOP is set
((msr & MSR_CTS) ? TIOCM_CTS : 0) | // CTS is set
((msr & MSR_CD) ? TIOCM_CAR : 0) | // Carrier detect is set
((msr & MSR_RI) ? TIOCM_RI : 0) | // Ring Indicator is set
((msr & MSR_DSR) ? TIOCM_DSR : 0); // DSR is set
return result;
}
static int ttymz_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
{
// Locals.
t_TTYMZ *ttymz = tty->driver_data;
unsigned int mcr = ttymz->mcr;
//PRINT_PROC_START();
if (set & TIOCM_RTS)
mcr |= MCR_RTS;
if (set & TIOCM_DTR)
mcr |= MCR_RTS;
if (clear & TIOCM_RTS)
mcr &= ~MCR_RTS;
if (clear & TIOCM_DTR)
mcr &= ~MCR_RTS;
// Set the new MCR value in the device
ttymz->mcr = mcr;
return 0;
}
#define ttymz_ioctl ttymz_ioctl_tiocgserial
static int ttymz_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
{
// Locals.
struct serial_struct tmp;
t_TTYMZ *ttymz = tty->driver_data;
//PRINT_PROC_START();
if(cmd == TIOCGSERIAL)
{
if (!arg)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
tmp.type = ttymz->serial.type;
tmp.line = ttymz->serial.line;
tmp.port = ttymz->serial.port;
tmp.irq = ttymz->serial.irq;
tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
tmp.xmit_fifo_size = ttymz->serial.xmit_fifo_size;
tmp.baud_base = ttymz->serial.baud_base;
tmp.close_delay = 5*HZ;
tmp.closing_wait = 30*HZ;
tmp.custom_divisor = ttymz->serial.custom_divisor;
tmp.hub6 = ttymz->serial.hub6;
tmp.io_type = ttymz->serial.io_type;
if (copy_to_user((void __user *)arg, &tmp, sizeof(struct serial_struct)))
return -EFAULT;
return 0;
}
return -ENOIOCTLCMD;
}
#undef ttymz_ioctl
#define ttymz_ioctl ttymz_ioctl_tiocmiwait
static int ttymz_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
{
// Locals.
DECLARE_WAITQUEUE(wait, current);
struct async_icount cnow;
struct async_icount cprev;
t_TTYMZ *ttymz = tty->driver_data;
//PRINT_PROC_START();
if (cmd == TIOCMIWAIT)
{
cprev = ttymz->icount;
while (1)
{
add_wait_queue(&ttymz->wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
schedule();
remove_wait_queue(&ttymz->wait, &wait);
// See if a signal woke us up
if (signal_pending(current))
return -ERESTARTSYS;
cnow = ttymz->icount;
if(cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
return -EIO; // no change => error
if(((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)))
{
return 0;
}
cprev = cnow;
}
}
return -ENOIOCTLCMD;
}
#undef ttymz_ioctl
#define ttymz_ioctl ttymz_ioctl_tiocgicount
static int ttymz_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
{
// Locals.
t_TTYMZ *ttymz = tty->driver_data;
struct async_icount cnow = ttymz->icount;
struct serial_icounter_struct icount;
//PRINT_PROC_START();
if(cmd == TIOCGICOUNT)
{
icount.cts = cnow.cts;
icount.dsr = cnow.dsr;
icount.rng = cnow.rng;
icount.dcd = cnow.dcd;
icount.rx = cnow.rx;
icount.tx = cnow.tx;
icount.frame = cnow.frame;
icount.overrun = cnow.overrun;
icount.parity = cnow.parity;
icount.brk = cnow.brk;
icount.buf_overrun = cnow.buf_overrun;
if (copy_to_user((void __user *)arg, &icount, sizeof(icount)))
return -EFAULT;
return 0;
}
return -ENOIOCTLCMD;
}
#undef ttymz_ioctl
// IOCTL Method
// This method allows User Space application to control the SharpMZ TTY device driver internal functionality.
//
static int ttymz_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
{
// Locals.
//PRINT_PROC_START();
switch(cmd)
{
case TIOCGSERIAL:
return ttymz_ioctl_tiocgserial(tty, cmd, arg);
case TIOCMIWAIT:
return ttymz_ioctl_tiocmiwait(tty, cmd, arg);
case TIOCGICOUNT:
return ttymz_ioctl_tiocgicount(tty, cmd, arg);
// Fetch last hotkey. This method returns any active hotkey to the caller. Normally this is queried after receiving a SIGUSR2 signal.
case IOCTL_CMD_FETCH_HOTKEY:
if(copy_to_user((int32_t*)arg, &ttymzCtrl.hotkey, sizeof(ttymzCtrl.hotkey)))
{
pr_err("Failed to send hotkey to user space.\n");
}
return(0);
// Suspend control. This method stops all physical hardware updates of the host framebuffer and keyboard
// scan whilst maintining the functionality of the tty within the mirrored framebuffer. This mode is
// necessary if the user wishes to switch into a Z80 driver and use the host as original.
case IOCTL_CMD_SUSPEND_IO:
mzSuspendIO();
return(0);
// Resume control. This method re-initialises host hardware, updates the host framebuffer from the mirror
// (refresh) and re-enabled hardware access and keyboard scanning.
case IOCTL_CMD_RESUME_IO:
mzResumeIO();
return(0);
}
return -ENOIOCTLCMD;
}
// Window resize method.
// On the Sharp framebuffer this could be 40/80 chars wide.
// On the SSD202 framebuffer, tba.
static int ttymz_resize(struct tty_struct *tty, struct winsize *ws)
{
PRINT_PROC_START();
pr_info("Resize to:%d,%d\n", ws->ws_row, ws->ws_col);
// Check columns and setup the display according to requirement.
if(ws->ws_col == 40)
{
ws->ws_row = VC_MAX_ROWS;
} else
if(ws->ws_col == 80)
{
ws->ws_row = VC_MAX_ROWS;
} else
{
// Ignore all other values.
return -EINVAL;
}
// Setup the hardware to accommodate new column width.
mzSetDisplayWidth(ws->ws_col);
tty->winsize = *ws;
return 0;
}
//static void ttymz_remove(struct tty_driver *driver, struct tty_struct *tty)
//{
// // Locals.
//
// PRINT_PROC_START();
//}
static void ttymz_cleanup(struct tty_struct *tty)
{
// tty_port_put(tty->port);
}
static void ttymz_flush_buffer(struct tty_struct *tty)
{
// Locals.
//PRINT_PROC_START();
}
// pty_chars_in_buffer - characters currently in our tx queue
//
// Report how much we have in the transmit queue. As everything is
// instantly at the other end this is easy to implement.
//
static int ttymz_chars_in_buffer(struct tty_struct *tty)
{
return 0;
}
// The unthrottle routine is called by the line discipline to signal
// that it can receive more characters. For PTY's, the TTY_THROTTLED
// flag is always set, to force the line discipline to always call the
// unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE
// characters in the queue. This is necessary since each time this
// happens, we need to wake up any sleeping processes that could be
// (1) trying to send data to the pty, or (2) waiting in wait_until_sent()
// for the pty buffer to be drained.
//
static void ttymz_unthrottle(struct tty_struct *tty)
{
//PRINT_PROC_START();
tty_wakeup(tty->link);
set_bit(TTY_THROTTLED, &tty->flags);
}
// Structure to declare public API methods.
// Standard Linux device driver structure to declare accessible methods within the driver.
static const struct tty_operations serial_ops = {
//.install = ttymz_install,
.open = ttymz_open,
.close = ttymz_close,
.write = ttymz_write,
.write_room = ttymz_write_room,
.flush_buffer = ttymz_flush_buffer,
.chars_in_buffer = ttymz_chars_in_buffer,
.unthrottle = ttymz_unthrottle,
.set_termios = ttymz_set_termios,
.tiocmget = ttymz_tiocmget,
.tiocmset = ttymz_tiocmset,
.ioctl = ttymz_ioctl,
.cleanup = ttymz_cleanup,
.resize = ttymz_resize,
// .remove = ttymz_remove
};
// Initialisation.
// This is the entry point into the device driver when loaded into the kernel.
// The method intialises any required hardware (ie. GPIO's, SPI etc), memory.
// It also allocates the Major and Minor device numbers and sets up the device in /dev.
static int __init ttymz_init(void)
{
// Locals.
int retval;
int i;
char buf[80];
// Allocate the tty driver handles, one per potential device.
ttymzCtrl.ttymzDriver = alloc_tty_driver(SHARPMZ_TTY_MINORS);
if(!ttymzCtrl.ttymzDriver)
return -ENOMEM;
// Initialize the tty driver
ttymzCtrl.ttymzDriver->owner = THIS_MODULE;
ttymzCtrl.ttymzDriver->driver_name = DRIVER_NAME;
ttymzCtrl.ttymzDriver->name = DEVICE_NAME;
ttymzCtrl.ttymzDriver->major = SHARPMZ_TTY_MAJOR,
ttymzCtrl.ttymzDriver->type = TTY_DRIVER_TYPE_SERIAL,
ttymzCtrl.ttymzDriver->subtype = SERIAL_TYPE_NORMAL,
ttymzCtrl.ttymzDriver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV,
ttymzCtrl.ttymzDriver->init_termios = tty_std_termios;
ttymzCtrl.ttymzDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
tty_set_operations(ttymzCtrl.ttymzDriver, &serial_ops);
for (i = 0; i < SHARPMZ_TTY_MINORS; i++)
{
tty_port_init(ttymzCtrl.ttymzPort + i);
tty_port_link_device(ttymzCtrl.ttymzPort + i, ttymzCtrl.ttymzDriver, i);
}
// Register the tty driver
retval = tty_register_driver(ttymzCtrl.ttymzDriver);
if(retval)
{
pr_err("Failed to register SharpMZ tty driver");
put_tty_driver(ttymzCtrl.ttymzDriver);
return retval;
}
// Register the devices.
for (i = 0; i < SHARPMZ_TTY_MINORS; ++i)
tty_register_device(ttymzCtrl.ttymzDriver, i, NULL);
// Initialise the hardware to host interface.
z80io_init();
// Initialise the Sharp MZ interface.
mzInit();
// Sign on.
sprintf(buf, "%s %s", DRIVER_DESCRIPTION, DRIVER_VERSION); mzWriteString(0, 0, buf, -1);
sprintf(buf, "%s %s\n", DRIVER_COPYRIGHT, DRIVER_AUTHOR); mzWriteString(0, 1, buf, -1);
pr_info(DRIVER_DESCRIPTION " " DRIVER_VERSION "\n");
return retval;
}
// Exit
// This method is called when the device driver is removed from the kernel with the rmmod command.
// It is responsible for closing and freeing all allocated memory, disabling hardware and removing
// the device from the /dev directory.
static void __exit ttymz_exit(void)
{
// Locals.
t_TTYMZ *ttymz;
int idx;
// De-register the devices and driver.
for(idx = 0; idx < SHARPMZ_TTY_MINORS; ++idx)
{
tty_unregister_device(ttymzCtrl.ttymzDriver, idx);
tty_port_destroy(ttymzCtrl.ttymzPort + idx);
}
tty_unregister_driver(ttymzCtrl.ttymzDriver);
// Shut down all of the timers and free the memory.
for(idx = 0; idx < SHARPMZ_TTY_MINORS; ++idx)
{
ttymz = ttymzConnections[idx];
if (ttymz)
{
// Close the port.
while (ttymz->open_count)
do_close(ttymz);
// Shut down our timer and free the memory.
del_timer(&ttymz->timerKeyboard);
del_timer(&ttymz->timerDisplay);
kfree(ttymz);
ttymzConnections[idx] = NULL;
}
}
pr_info("ttymz: unregistered!\n");
}
module_init(ttymz_init);
module_exit(ttymz_exit);

128
software/FusionX/src/ttymz/ttymz.h vendored Normal file
View File

@@ -0,0 +1,128 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: ttymz.h
// Created: Feb 2023
// Author(s): Philip Smart
// Description: Sharp MZ TTY
// This file contains the definitions required by the linux tty device driver ttymz.c.
// This driver forms part of the FusionX developments and allows a user sitting at the
// Sharp MZ Console to access the underlying FusionX Linux SOM.
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Feb 2023 - v1.0 Initial write of the Sharp MZ tty driver software.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef TTYMZ_H
#define TTYMZ_H
// Constants.
#define DRIVER_LICENSE "GPL"
#define DRIVER_AUTHOR "Philip D Smart"
#define DRIVER_DESCRIPTION "Sharp MZ TTY Driver"
#define DRIVER_VERSION "v1.01"
#define DRIVER_VERSION_DATE "Mar 2023"
#define DRIVER_COPYRIGHT "(C) 2018-2023"
#define DEVICE_NAME "ttymz"
#define DRIVER_NAME "SharpMZ_tty"
#define DEBUG_ENABLED 0 // 0 = disabled, 1 .. debug level.
#define ARBITER_NAME "sharpbiter"
// Fake UART values
#define MCR_DTR 0x01
#define MCR_RTS 0x02
#define MCR_LOOP 0x04
#define MSR_CTS 0x08
#define MSR_CD 0x10
#define MSR_RI 0x20
#define MSR_DSR 0x40
// IOCTL commands. Passed from user space using the IOCTL method to command the driver to perform an action.
#define IOCTL_CMD_FETCH_HOTKEY _IOW('f', 'f', int32_t *)
#define IOCTL_CMD_SUSPEND_IO _IOW('s', 's', int32_t *)
#define IOCTL_CMD_RESUME_IO _IOW('r', 'r', int32_t *)
#define SHARPMZ_TTY_MAJOR 240 // Experimental range
#define SHARPMZ_TTY_MINORS 3 // Assign 2 devices, 0) Sharp VRAM, 1) SigmaStar SSD202 Framebuffer, 2) Control.
// Macros.
#define from_timer(var, callback_timer, timer_fieldname) container_of(callback_timer, typeof(*var), timer_fieldname)
#define PRINT_PROC_START() do { pr_info("Start: %s\n", __func__); } while (0)
#define PRINT_PROC_EXIT() do { pr_info("Finish: %s\n", __func__); } while (0)
#define sendSignal(__task__, _signal_) { struct siginfo sigInfo;\
if(__task__ != NULL)\
{\
memset(&sigInfo, 0, sizeof(struct siginfo));\
sigInfo.si_signo = _signal_;\
sigInfo.si_code = SI_QUEUE;\
sigInfo.si_int = 1;\
if(send_sig_info(_signal_, &sigInfo, __task__) < 0)\
{\
pr_info("Error: Failed to send signal:%02x to:%s\n", _signal_, __task__->comm);\
}\
}\
}
#define resetZ80() {\
sendSignal(Z80Ctrl->ioTask, SIGUSR1); \
setupMemory(Z80Ctrl->defaultPageMode);\
z80_instant_reset(&Z80CPU);\
}
// TTY control structure, per port.
typedef struct {
struct tty_struct *tty; // pointer to the tty for this device
int open_count; // number of times this port has been opened
struct mutex mutex; // locks this structure
struct timer_list timerKeyboard; // Keyboard sweep timer.
struct timer_list timerDisplay; // Display service timer.
// for tiocmget and tiocmset functions
int msr; // MSR shadow
int mcr; // MCR shadow
// for ioctl
struct serial_struct serial;
wait_queue_head_t wait;
struct async_icount icount;
} t_TTYMZ;
// Driver control variables.
typedef struct {
struct tty_driver *ttymzDriver;
struct tty_port ttymzPort[SHARPMZ_TTY_MINORS];
struct task_struct *arbTask;
int32_t hotkey;
} t_TTYMZCtrl;
#if(DEBUG_ENABLED != 0)
struct debug {
uint8_t level;
};
#endif
struct ioctlCmd {
int32_t cmd;
union {
#if(DEBUG_ENABLED != 0)
struct debug debug;
#endif
};
};
// Prototypes.
#endif

View File

@@ -7,9 +7,13 @@
// This file contains the methods used in interfacing the SOM to the Z80 socket
// and host hardware via a CPLD.
// Credits:
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Oct 2022 - Initial write of the z80 kernel driver software.
// History: Oct 2022 v1.0 - Initial write of the z80 kernel driver software.
// Jan 2023 v1.1 - Numerous new tries at increasing throughput to the CPLD failed.
// Maximum read throughput of an 8bit byte due to the SSD202 GPIO
// structure is approx 2MB/s - or 512K/s for a needed 32bit word.
// Write is slower as you have to clock the data so sticking with SPI.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -59,7 +63,6 @@
//-------------------------------------------------------------------------------------------------------------------------------
// Initialise the SOM hardware used to communicate with the z80 socket and host hardware.
// The SOM interfaces to a CPLD which provides voltage level translation and also encapsulates the Z80 timing cycles as recreating
// them within the SOM is much more tricky.
@@ -184,7 +187,7 @@ int z80io_init(void)
inline uint8_t z80io_PRL_Read8(uint8_t dataFlag)
{
// Locals.
uint8_t result = 0;
volatile uint8_t result = 0;
// Byte according to flag.
if(dataFlag)
@@ -199,10 +202,31 @@ inline uint8_t z80io_PRL_Read8(uint8_t dataFlag)
return(result);
}
inline uint8_t z80io_PRL_Read(void)
{
// Locals.
volatile uint8_t result = 0;
volatile uint32_t b7, b6, b5, b4, b3, b2, b1, b0;
// Read the input registers and set value accordingly. Quicker to read registers and then apply shift/logical operators. The I/O Bus is very slow!
b7 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_7_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_7_ADDR & 1)));
b6 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_6_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_6_ADDR & 1)));
b5 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_5_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_5_ADDR & 1)));
b4 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_4_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_4_ADDR & 1)));
b3 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_3_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_3_ADDR & 1)));
b2 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_2_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_2_ADDR & 1)));
b1 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_1_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_1_ADDR & 1)));
b0 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_0_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_0_ADDR & 1)));
result = (b7 & 0x1) << 7 | (b6 & 0x1) << 6 | (b5 & 0x1) << 5 | (b4 & 0x1) << 4 | (b3 & 0x1) << 3 | (b2 & 0x1) << 2 | (b1 & 0x1) << 1 | (b0 & 0x1);
// Return 16bit value read from CPLD.
return(result);
}
inline uint16_t z80io_PRL_Read16(void)
{
// Locals.
uint16_t result = 0;
volatile uint16_t result = 0;
// Low byte first.
CLEAR_CPLD_HIGH_BYTE();
@@ -407,7 +431,7 @@ uint8_t z80io_SPI_Send32(uint32_t txData, uint32_t *rxData)
//--------------------------------------------------------
// Test Methods.
//--------------------------------------------------------
#ifdef INCLUDE_TEST_METHODS
#if defined(INCLUDE_TEST_METHODS) && INCLUDE_TEST_METHODS == 1
#include "z80io_test.c"
#else
uint8_t z80io_Z80_TestMemory(void)

View File

@@ -7,9 +7,13 @@
// This file contains the declarations used in interfacing the SOM to the Z80 socket
// and host hardware via a CPLD.
// Credits:
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Oct 2022 - Initial write of the z80 kernel driver software.
// History: Oct 2022 v1.0 - Initial write of the z80 kernel driver software.
// Jan 2023 v1.1 - Numerous new tries at increasing throughput to the CPLD failed.
// Maximum read throughput of an 8bit byte due to the SSD202 GPIO
// structure is approx 2MB/s - or 512K/s for a needed 32bit word.
// Write is slower as you have to clock the data so sticking with SPI.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -35,7 +39,7 @@
#endif
// Definitions to control compilation.
#define INCLUDE_TEST_METHODS 1
#define INCLUDE_TEST_METHODS 0
// CPLD Commands.
#define CPLD_CMD_FETCH_ADDR 0x10
@@ -78,6 +82,14 @@
#define CPLD_CMD_READIO_ADDR_P5 0x35
#define CPLD_CMD_READIO_ADDR_P6 0x36
#define CPLD_CMD_READIO_ADDR_P7 0x37
#define CPLD_CMD_READIO_WRITE_ADDR 0x38
#define CPLD_CMD_READIO_WRITE_ADDR_P1 0x39
#define CPLD_CMD_READIO_WRITE_ADDR_P2 0x3A
#define CPLD_CMD_READIO_WRITE_ADDR_P3 0x3B
#define CPLD_CMD_READIO_WRITE_ADDR_P4 0x3C
#define CPLD_CMD_READIO_WRITE_ADDR_P5 0x3D
#define CPLD_CMD_READIO_WRITE_ADDR_P6 0x3E
#define CPLD_CMD_READIO_WRITE_ADDR_P7 0x3F
#define CPLD_CMD_HALT 0x50
#define CPLD_CMD_REFRESH 0x51
#define CPLD_CMD_SET_SIGROUP1 0xF0
@@ -103,10 +115,10 @@
#define PAD_SPIO_3 PAD_GPIO11
#define PAD_Z80IO_HIGH_BYTE PAD_SAR_GPIO2 // Byte requiured, 0 = Low Byte, 1 = High Byte.
#define PAD_Z80IO_READY PAD_GPIO12
#define PAD_Z80IO_LTSTATE PAD_PM_IRIN // IRIN
#define PAD_Z80IO_LTSTATE PAD_UART0_RX // GPIO47
#define PAD_Z80IO_BUSRQ PAD_GPIO13
#define PAD_Z80IO_BUSACK PAD_GPIO14
#define PAD_Z80IO_INT PAD_UART0_RX // GPIO47
#define PAD_Z80IO_INT PAD_PM_IRIN // IRIN
#define PAD_Z80IO_NMI PAD_UART0_TX // GPIO48
#define PAD_Z80IO_WAIT PAD_HSYNC_OUT // GPIO85
#define PAD_Z80IO_RESET PAD_VSYNC_OUT // GPIO86
@@ -127,10 +139,10 @@
#define PAD_SPIO_3_ADDR 0x103C16
#define PAD_Z80IO_HIGH_BYTE_ADDR 0x1425
#define PAD_Z80IO_READY_ADDR 0x103C18
#define PAD_Z80IO_LTSTATE_ADDR 0xF28 // IRIN
#define PAD_Z80IO_LTSTATE_ADDR 0x103C30 // GPIO47
#define PAD_Z80IO_BUSRQ_ADDR 0x103C1A
#define PAD_Z80IO_BUSACK_ADDR 0x103C1C
#define PAD_Z80IO_INT_ADDR 0x103C30 // GPIO47
#define PAD_Z80IO_INT_ADDR 0xF28 // IRIN
#define PAD_Z80IO_NMI_ADDR 0x103C32 // GPIO48
#define PAD_Z80IO_WAIT_ADDR 0x103C80 // GPIO85
#define PAD_Z80IO_RESET_ADDR 0x103C82 // GPIO86
@@ -380,8 +392,10 @@
#define CPLD_READY() (MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1)
#define CPLD_RESET() (MHal_RIU_REG(PAD_Z80IO_RESET_ADDR) & 0x1)
#define CPLD_LAST_TSTATE() (MHal_RIU_REG(PAD_Z80IO_LTSTATE_ADDR) & 0x4)
#define SPI_SEND8(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
#define CPLD_Z80_INT() (MHal_RIU_REG(PAD_Z80IO_INT_ADDR) & 0x4)
#define CPLD_Z80_NMI() (MHal_RIU_REG(PAD_Z80IO_NMI_ADDR) & 0x4)
#define SPI_SEND_8(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d_); \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 1); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0);\
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
@@ -390,9 +404,18 @@
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE);\
}
#define SPI_SEND_I_8(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d_); \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 1); \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE);\
}
#define SPI_SEND16(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 2); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0);\
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
@@ -400,10 +423,9 @@
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
}
#define SPI_SEND32(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)((_d_) >> 16)); \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4); \
#define SPI_SEND_16(_d1_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 2); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d1_); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0);\
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
@@ -411,6 +433,62 @@
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
}
#define SPI_SEND_P_16(_d1_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 2); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d1_); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) != 0);\
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
}
#define SPI_SET_FRAME_SIZE() { MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4); \
}
#define SPI_SEND32(_d_) { uint32_t timeout = MAX_CHECK_CNT*2; \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)((_d_) >> 16)); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0) { if(--timeout == 0) break; };\
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
}
#define SPI_SEND_32(_d1_, _d2_) { uint32_t timeout = MAX_CHECK_CNT*2; \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d2_); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)_d1_); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0) { if(--timeout == 0) break; };\
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
}
#define SPI_SEND_I_32(_d1_, _d2_) { uint32_t timeout = MAX_CHECK_CNT*2; \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d2_); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)_d1_); \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
}
#define SPI_SEND_48(_d1_, _d2_, _d3_) { uint32_t timeout = MAX_CHECK_CNT*2; \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 6); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d3_); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)_d2_); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+2, (uint16_t)_d1_); \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0) { if(--timeout == 0) break; };\
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
}
// read 2 byte
#define MSPI_READ(_reg_) READ_WORD(gMspBaseAddr + ((_reg_)<<2))
@@ -434,7 +512,7 @@
#define MOVDMA_WRITE(_reg_, _val_) WRITE_WORD(gMOVDMAAddr + ((_reg_)<<2), (_val_));
#define _HAL_MSPI_ClearDone() MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET,MSPI_CLEAR_DONE)
#define MAX_CHECK_CNT 2000
#define MAX_CHECK_CNT 5000
#define MSPI_READ_INDEX 0x0
#define MSPI_WRITE_INDEX 0x1
@@ -453,6 +531,7 @@ uint8_t z80io_SPI_Send32(uint32_t txData, uint32_t *rxData);
uint8_t z80io_PRL_Send8(uint8_t txData);
uint8_t z680io_PRL_Send16(uint16_t txData);
#endif
uint8_t z80io_PRL_Read(void);
uint8_t z80io_PRL_Read8(uint8_t dataFlag);
uint16_t z80io_PRL_Read16(void);
uint8_t z80io_SPI_Test(void);

85
software/FusionX/src/z80drv/Makefile vendored Normal file
View File

@@ -0,0 +1,85 @@
#MODEL := MZ2000
#MODEL := MZ700
#MODEL := MZ80A
#MODEL := PCW8XXX
#MODEL := PCW9XXX
KERNEL := $(PWD)/../../../linux/kernel
FUSIONX := $(PWD)/../..
CROSS := arm-linux-gnueabihf-
ccflags-y = -O2 -I${src}/Zeta/API -I${src}/Z80/API -I${KERNEL}/drivers/sstar/include -I${KERNEL}/drivers/sstar/include/infinity2m -I${KERNEL}/drivers/sstar/gpio/infinity2m -D__KERNEL_DRIVER__ -DTARGET_HOST_$(MODEL)=1
CTRLINC = -IZeta/API -IZ80/API -DTARGET_HOST_$(MODEL)=1
obj-m += z80drv.o
z80drv-objs += src/z80driver.o Z80.o src/z80io.o src/z80menu.o # emumz.o sharpmz.o osd.o
z80drv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/gpio_table.o
z80drv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/mhal_gpio.o
z80drv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/mhal_pinmux.o
z80drv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/padmux_tables.o
all:
@echo "Specify target host, ie. make <host>"
@echo "Supported hosts: MZ80A, MZ700, MZ2000, PCW8XXX, PCW9XXX"
MZ80A: MODEL_MZ80A
MZ700: MODEL_MZ700
MZ2000: MODEL_MZ2000
PCW8XXX: MODEL_PCW8XXX
PCW9XXX: MODEL_PCW9XXX
MODEL_MZ80A:
$(MAKE) MODEL=MZ80A BUILD_MZ80A
MODEL_MZ700:
$(MAKE) MODEL=MZ700 BUILD_MZ700
MODEL_MZ2000:
$(MAKE) MODEL=MZ2000 BUILD_MZ2000
MODEL_PCW8XXX:
$(MAKE) MODEL=PCW8XXX BUILD_PCW8XXX
MODEL_PCW9XXX:
$(MAKE) MODEL=PCW8XXX BUILD_PCW9XXX
BUILD_MZ80A: sharpbiter k64fcpu kmod z80ctrl
BUILD_MZ700: sharpbiter k64fcpu kmod z80ctrl
BUILD_MZ2000: sharpbiter k64fcpu kmod z80ctrl
BUILD_PCW8XXX: kmod z80ctrl
BUILD_PCW9XXX: kmod z80ctrl
sharpbiter:
@echo ""
@echo "Build Sharp MZ Arbiter for host: $(MODEL)"
$(CROSS)gcc $(CTRLINC) src/sharpbiter.c -o sharpbiter
k64fcpu:
@echo ""
@echo "Build K64F Daemon for host: $(MODEL)"
$(CROSS)gcc $(CTRLINC) src/k64fcpu.c -o k64fcpu
kmod:
@echo ""
@echo "Build driver for host: $(MODEL)"
make -C $(KERNEL) ARCH=arm CROSS_COMPILE=$(CROSS) M="$(PWD)" modules
z80ctrl:
@echo ""
@echo "Build z80ctrl tool for host: $(MODEL)"
$(CROSS)gcc $(CTRLINC) src/z80ctrl.c -o z80ctrl
install:
@echo "Copy kernel driver..."
@cp z80drv.ko $(FUSIONX)/modules/
@echo "Copy z80ctrl app..."
@cp z80ctrl $(FUSIONX)/bin/
@if [ -f sharpbiter ]; then\
echo "Copy sharpbiter app...";\
cp sharpbiter $(FUSIONX)/bin/;\
fi
@if [ -f k64fcpu ]; then\
echo "Copy k64fcpu app...";\
cp k64fcpu $(FUSIONX)/bin/;\
fi
clean:
make -C $(KERNEL) M=$(PWD) clean
@rm -f sharpbiter k64fcpu z80ctrl

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,489 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: sharpbiter.c
// Created: Oct 2022
// Author(s): Philip Smart
// Description: Sharp Host Arbiter
// This daemon application is responsible for switching the FusionX between modes via
// host keyboard hotkeys. It allows the host to assume a persona based on user
// requirements.
// Currently, the following persona's can be invoked:
// 1. Original host mode (ie. the host behaves as original, no extensions).
// 2. Original + Rom Filing System. Virtual RFS is installed and the RFS monitor invoked.
// 3. Original + TZFS. Virtual tranZPUter SW is installed and the TZFS monitor invoked.
// 4. Linux. Host will run as a smart terminal front to the FusionX Linux OS.
//
// The daemon listens for signals sent by the current active process. The signal will
// indicate required persona and this daemon will invoke it accordingly.
//
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Feb 2023 v1.0 - Initial write.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <unistd.h>
#include <dirent.h>
#include <ctype.h>
#include <stdarg.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <sys/select.h>
#include <termios.h>
#include <time.h>
#include <Z/constants/pointer.h>
#include <Z/macros/member.h>
#include <Z/macros/array.h>
#include <Z80.h>
#include "z80driver.h"
#define VERSION "1.00"
#define AUTHOR "P.D.Smart"
#define COPYRIGHT "(c) 2018-23"
// Getopt_long is buggy so we use optparse.
#define OPTPARSE_IMPLEMENTATION
#define OPTPARSE_API static
#include "optparse.h"
// IOCTL commands. Passed from user space using the IOCTL method to command the driver to perform an action.
#define IOCTL_CMD_FETCH_HOTKEY _IOW('f', 'f', int32_t *)
#define IOCTL_CMD_SUSPEND_IO _IOW('s', 's', int32_t *)
#define IOCTL_CMD_RESUME_IO _IOW('r', 'r', int32_t *)
// Device driver name.
#define Z80_DEVICE_FILENAME "/dev/z80drv"
#define TTY_DEVICE_FILENAME "/dev/ttymz2" // The Sharp MZ TTY is accessed via port 2, port 0 = host tty, 1 = SSD202 framebuffer tty.
// Structure to maintain all the control and management variables of the arbiter.
//
typedef struct {
int fdZ80; // Handle to the Z80 kernel driver.
int fdTTY; // Handle to the TTY kernel driver.
uint8_t hotkey; // New or last hotkey received.
uint8_t newHotkey; // Flag to indicate a hotkey has arrived.
uint8_t runControl; // Run control for the daemon, 1 = run, 0 = terminate.
} t_ArbiterControl;
// Global scope variables.
//
static t_ArbiterControl arbCtrl;
// Shared memory between this process and the Z80 driver.
static t_Z80Ctrl *Z80Ctrl = NULL;
static uint8_t *Z80RAM = NULL;
static uint8_t *Z80ROM = NULL;
// Millisecond delay routine.
void delay(int ms_delay)
{
usleep(1000 * ms_delay);
}
// Method to reset the Z80 CPU.
//
void reqResetZ80(void)
{
// Locals.
//
struct ioctlCmd ioctlCmd;
// Send command to driver to reset Z80.
ioctlCmd.cmd = IOCTL_CMD_Z80_RESET;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
}
// Method to start the Z80 CPU.
//
void startZ80(void)
{
// Locals.
//
struct ioctlCmd ioctlCmd;
// Send command to driver to reset Z80.
ioctlCmd.cmd = IOCTL_CMD_Z80_START;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
}
// Method to stop the Z80 CPU.
//
void stopZ80(void)
{
// Locals.
//
struct ioctlCmd ioctlCmd;
// Send command to driver to reset Z80.
ioctlCmd.cmd = IOCTL_CMD_Z80_STOP;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
}
// Handler for the SIGUSR1 signal used by the Z80 Driver when a hotkey is detected.
//
void z80Request(int signalNo)
{
// Locals.
//printf("Received SIGUSR1 from Z80 Driver\n");
// If an existing hotkey has not been processed, wait.
if(arbCtrl.newHotkey)
{
usleep(1000);
}
arbCtrl.hotkey = Z80Ctrl->keyportHotKey;
arbCtrl.newHotkey = 1;
return;
}
// Handler for the SIGUSR2 signal used by the TTY Driver when a hotkey is detected.
//
void ttyRequest(int signalNo)
{
// Locals.
int32_t result;
//printf("Received SIGUSR2 from TTY Driver\n");
// Send command to TTY driver to fetch hotkey.
ioctl(arbCtrl.fdTTY, IOCTL_CMD_FETCH_HOTKEY, &result);
// If an existing hotkey has not been processed, wait.
if(arbCtrl.newHotkey)
{
usleep(1000);
}
arbCtrl.hotkey = (uint8_t)result;
arbCtrl.newHotkey = 1;
return;
}
// Handler for the HUP, INT, QUIT or TERM signals. On receipt, start a shutdown request.
void shutdownRequest(int signalNo)
{
// Locals.
// Terminate signals flag the request by clearing runControl.
if(signalNo == SIGHUP || signalNo == SIGINT || signalNo == SIGQUIT || signalNo == SIGTERM)
{
printf("Terminate request.\n");
arbCtrl.newHotkey = 0;
arbCtrl.runControl = 0;
}
return;
}
// Output usage screen. So mamy commands you do need to be prompted!!
void showArgs(char *progName, struct optparse *options)
{
printf("%s %s %s %s\n\n", progName, VERSION, COPYRIGHT, AUTHOR);
printf("Synopsis:\n");
printf("%s --help # This help screen.\n", progName);
return;
}
// This is a daemon process, process arguments, initialise logic and enter a loop waiting for signals to arrive.
// The signals indicate the active process has detected a hotkey combination and this daemon needs to process it
// to invoke the required FusionX persona.
int main(int argc, char *argv[])
{
uint32_t hexData = 0;
int opt = 0;
int verboseFlag = 0;
int32_t result;
struct ioctlCmd ioctlCmd;
// Define parameters to be processed.
struct optparse options;
static struct optparse_long long_options[] =
{
{"help", 'h', OPTPARSE_NONE},
{"verbose", 'v', OPTPARSE_NONE},
{0}
};
// Parse the command line options.
//
optparse_init(&options, argv);
while((opt = optparse_long(&options, long_options, NULL)) != -1)
{
switch(opt)
{
// Hex data.
case 'd':
sscanf(options.optarg, "0x%08x", &hexData);
printf("Hex data:%08x\n", hexData);
break;
// Verbose mode.
case 'v':
verboseFlag = 1;
break;
// Command help needed.
case 'h':
showArgs(argv[0], &options);
return(1);
// Unrecognised, show synopsis.
case '?':
showArgs(argv[0], &options);
printf("%s: %s\n", argv[0], options.errmsg);
return(1);
}
}
// Open the z80drv driver and attach to its shared memory, basically the Z80 control structure which includes the virtual Z80 memory.
arbCtrl.fdZ80 = open(Z80_DEVICE_FILENAME, O_RDWR|O_NDELAY);
if(arbCtrl.fdZ80 >= 0)
{
Z80Ctrl = (t_Z80Ctrl *)mmap(0, sizeof(t_Z80Ctrl), PROT_READ | PROT_WRITE, MAP_SHARED, arbCtrl.fdZ80, 0);
if(Z80Ctrl == (void *)-1)
{
printf("Failed to attach to the Z80 Control structure, cannot continue, exiting....\n");
close(arbCtrl.fdZ80);
exit(1);
}
Z80RAM = (uint8_t *)mmap(0, Z80_VIRTUAL_RAM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, arbCtrl.fdZ80, 0);
if(Z80RAM == (void *)-1)
{
printf("Failed to attach to the Z80 RAM, cannot continue, exiting....\n");
close(arbCtrl.fdZ80);
exit(1);
}
Z80ROM = (uint8_t *)mmap(0, Z80_VIRTUAL_ROM_SIZE+0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, arbCtrl.fdZ80, 0);
if(Z80ROM == (void *)-1)
{
printf("Failed to attach to the Z80 ROM, cannot continue, exitting....\n");
close(arbCtrl.fdZ80);
exit(1);
}
} else
{
printf("Failed to open the Z80 Driver, exiting...\n");
exit(1);
}
arbCtrl.fdTTY = open(TTY_DEVICE_FILENAME, O_RDWR|O_NDELAY);
if(arbCtrl.fdTTY >= 0)
{
printf("Opened device:%s\n", TTY_DEVICE_FILENAME);
} else
{
printf("Failed to open the TTY Driver, exiting...\n");
exit(1);
}
// Register the request handler for processing signals from the z80drv driver.
signal(SIGUSR1, z80Request);
// Register the request handler for processing signals from the ttymz driver.
signal(SIGUSR2, ttyRequest);
// Register close down handlers.
signal(SIGHUP, shutdownRequest);
signal(SIGINT, shutdownRequest);
signal(SIGQUIT, shutdownRequest);
signal(SIGTERM, shutdownRequest);
// Enter a loop, process requests as the come in and terminate if requested by signals.
arbCtrl.runControl = 1;
while(arbCtrl.runControl)
{
if(arbCtrl.newHotkey)
{
printf("New hotkey:%02x\n", arbCtrl.hotkey);
switch(arbCtrl.hotkey)
{
case HOTKEY_ORIGINAL:
// Disable TTY I/O.
ioctl(arbCtrl.fdTTY, IOCTL_CMD_SUSPEND_IO, &result);
// Stop the Z80.
stopZ80();
// Remove drivers. Remove all because an external event could have changed last configured driver.
//
ioctlCmd.cmd = IOCTL_CMD_DEL_DEVICE;
#if(TARGET_HOST_MZ80A == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ80A;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ700 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#endif
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS80;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS40;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
ioctlCmd.vdev.device = VIRTUAL_DEVICE_TZPU;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
// Add in the required driver.
ioctlCmd.cmd = IOCTL_CMD_ADD_DEVICE;
#if(TARGET_HOST_MZ80A == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ80A;
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
#elif(TARGET_HOST_MZ700 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
#endif
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
// Reset and start the Z80.
delay(500);
reqResetZ80();
break;
case HOTKEY_RFS80:
case HOTKEY_RFS40:
// Disable TTY I/O.
ioctl(arbCtrl.fdTTY, IOCTL_CMD_SUSPEND_IO, &result);
// Stop the Z80.
stopZ80();
// Remove drivers. Remove all because an external event could have changed last configured driver.
//
ioctlCmd.cmd = IOCTL_CMD_DEL_DEVICE;
#if(TARGET_HOST_MZ80A == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ80A;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ700 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#endif
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS80;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS40;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
ioctlCmd.vdev.device = VIRTUAL_DEVICE_TZPU;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
// Add in the required driver.
ioctlCmd.cmd = IOCTL_CMD_ADD_DEVICE;
ioctlCmd.vdev.device = (arbCtrl.hotkey == HOTKEY_RFS80) ? VIRTUAL_DEVICE_RFS80 : VIRTUAL_DEVICE_RFS40;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
// Reset and start the Z80.
delay(500);
reqResetZ80();
break;
case HOTKEY_TZFS:
// Disable TTY I/O.
ioctl(arbCtrl.fdTTY, IOCTL_CMD_SUSPEND_IO, &result);
// Stop the Z80.
stopZ80();
// Remove drivers. Remove all because an external event could have changed last configured driver.
//
ioctlCmd.cmd = IOCTL_CMD_DEL_DEVICE;
#if(TARGET_HOST_MZ80A == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ80A;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ700 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#endif
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS80;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS40;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
ioctlCmd.vdev.device = VIRTUAL_DEVICE_TZPU;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
// Add in the required driver.
ioctlCmd.cmd = IOCTL_CMD_ADD_DEVICE;
ioctlCmd.vdev.device = VIRTUAL_DEVICE_TZPU;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
case HOTKEY_LINUX:
// Stop the Z80.
ioctlCmd.cmd = IOCTL_CMD_Z80_STOP;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
// Remove drivers. Remove all because an external event could have changed last configured driver.
//
ioctlCmd.cmd = IOCTL_CMD_DEL_DEVICE;
#if(TARGET_HOST_MZ80A == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ80A;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ2000 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#elif(TARGET_HOST_MZ700 == 1)
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#endif
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS80;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS40;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
ioctlCmd.vdev.device = VIRTUAL_DEVICE_TZPU;
ioctl(arbCtrl.fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
// Enable TTY I/O.
ioctl(arbCtrl.fdTTY, IOCTL_CMD_RESUME_IO, &result);
break;
default:
break;
}
arbCtrl.newHotkey = 0;
}
usleep(1000);
}
// Unmap shared memory and close the device.
munmap(Z80Ctrl, sizeof(t_Z80Ctrl));
close(arbCtrl.fdZ80);
close(arbCtrl.fdTTY);
return(0);
}
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

748
software/FusionX/src/z80drv/src/tzpu.h vendored Executable file
View File

@@ -0,0 +1,748 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: tzpu.h
// Created: May 2020
// Author(s): Philip Smart
// Description: The TranZPUter library.
// This file is copied from the original zSoft tranZPUter library header file and
// modified for the FusionX tranZPUter SW driver. It is used by the Z80 driver and the
// user space daemon.
// Hardware references have been removed as the K64F is a virtual process rather
// than a physical MPU.
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: May 2020 - Initial write of the TranZPUter software.
// Jul 2020 - Updates to accommodate v2.1 of the tranZPUter board.
// Sep 2020 - Updates to accommodate v2.2 of the tranZPUter board.
// May 2021 - Changes to use 512K-1Mbyte Z80 Static RAM, build time configurable.
// Feb 2023 - Adaptation of zSoft tranzputer.h for the FusionX tranZPUter SW driver.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef TZPU_H
#define TZPU_H
#ifdef __cplusplus
extern "C" {
#endif
// Configurable constants.
//
#define REFRESH_BYTE_COUNT 8 // This constant controls the number of bytes read/written to the z80 bus before a refresh cycle is needed.
#define RFSH_BYTE_CNT 256 // Number of bytes we can write before needing a full refresh for the DRAM.
#define HOST_MON_TEST_VECTOR 0x4 // Address in the host monitor to test to identify host type.
#if (TARGET_HOST_MZ80A == 1)
#define OS_BASE_DIR "/apps/FusionX/host/MZ-80A/" // Linux base directory where all the files are stored. On a real tranZPUter this would be the SD card root dir.
#elif (TARGET_HOST_MZ700 == 1)
#define OS_BASE_DIR "/apps/FusionX/host/MZ-700/"
#elif (TARGET_HOST_MZ2000 == 1)
#define OS_BASE_DIR "/apps/FusionX/host/MZ-2000/"
#endif
#define TZFS_AUTOBOOT_FLAG OS_BASE_DIR "/TZFSBOOT.FLG" // Filename used as a flag, if this file exists in the base directory then TZFS is booted automatically.
#define TZ_MAX_Z80_MEM 0x100000 // Maximum Z80 memory available on the tranZPUter board.
// tranZPUter Memory Modes - select one of the 32 possible memory models using these constants.
//
#define TZMM_ORIG 0x00 // Original Sharp MZ80A mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
#define TZMM_BOOT 0x01 // Original mode but E800-EFFF is mapped to tranZPUter RAM so TZFS can be booted.
#define TZMM_TZFS 0x02 // TZFS main memory configuration. all memory is in tranZPUter RAM, E800-FFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected.
#define TZMM_TZFS2 0x03 // TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 1.
#define TZMM_TZFS3 0x04 // TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 2.
#define TZMM_TZFS4 0x05 // TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 3.
#define TZMM_CPM 0x06 // CPM main memory configuration, all memory on the tranZPUter board, 64K block 4 selected. Special case for F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
#define TZMM_CPM2 0x07 // CPM main memory configuration, F000-FFFF are on the tranZPUter board in block 4, 0040-CFFF and E800-EFFF are in block 5, mainboard for D000-DFFF (video), E000-E800 (Memory control) selected.
// Special case for 0000:003F (interrupt vectors) which resides in block 4, F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
#define TZMM_COMPAT 0x08 // Original mode but with main DRAM in Bank 0 to allow bootstrapping of programs from other machines such as the MZ700.
#define TZMM_HOSTACCESS 0x09 // Mode to allow code running in Bank 0, address E800:FFFF to access host memory. Monitor ROM 0000-0FFF and Main DRAM 0x1000-0xD000, video and memory mapped I/O are on the host machine, User/Floppy ROM E800-FFFF are in tranZPUter memory.
#define TZMM_MZ700_0 0x0a // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the mainboard.
#define TZMM_MZ700_1 0x0b // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
#define TZMM_MZ700_2 0x0c // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
#define TZMM_MZ700_3 0x0d // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
#define TZMM_MZ700_4 0x0e // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
#define TZMM_MZ800 0x0f // MZ800 Mode - Host is an MZ-800 and mode provides for MZ-700/MZ-800 decoding per original machine.
#define TZMM_MZ2000 0x10 // MZ2000 Mode - Running on MZ2000 hardware, configuration set according to runtime configuration registers.
#define TZMM_FPGA 0x15 // Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked.
#define TZMM_TZPUM 0x16 // Everything is on mainboard, no access to tranZPUter memory.
#define TZMM_TZPU 0x17 // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory. K64F drives A18-A16 allowing full access to RAM.
//#define TZMM_TZPU0 0x18 // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
//#define TZMM_TZPU1 0x19 // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 1 is selected.
//#define TZMM_TZPU2 0x1A // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 2 is selected.
//#define TZMM_TZPU3 0x1B // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 3 is selected.
//#define TZMM_TZPU4 0x1C // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 4 is selected.
//#define TZMM_TZPU5 0x1D // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 5 is selected.
//#define TZMM_TZPU6 0x1E // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 6 is selected.
//#define TZMM_TZPU7 0x1F // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 7 is selected.
// IO addresses on the tranZPUter or mainboard.
//
#define IO_TZ_CTRLLATCH 0x60 // Control latch which specifies the Memory Model/mode.
#define IO_TZ_SETXMHZ 0x62 // Switch to alternate CPU frequency provided by K64F.
#define IO_TZ_SET2MHZ 0x64 // Switch to system CPU frequency.
#define IO_TZ_CLKSELRD 0x66 // Read the status of the clock select, ie. which clock is connected to the CPU.
#define IO_TZ_SVCREQ 0x68 // Service request from the Z80 to be provided by the K64F.
#define IO_TZ_SYSREQ 0x6A // System request from the Z80 to be provided by the K64F.
#define IO_TZ_CPLDCMD 0x6B // Version 2.1 CPLD command register.
#define IO_TZ_CPLDSTATUS 0x6B // Version 2.1 CPLD status register.
#define IO_TZ_CPUCFG 0x6C // Version 2.2 CPU configuration register.
#define IO_TZ_CPUSTATUS 0x6C // Version 2.2 CPU runtime status register.
#define IO_TZ_CPUINFO 0x6D // Version 2.2 CPU information register.
#define IO_TZ_CPLDCFG 0x6E // Version 2.1 CPLD configuration register.
#define IO_TZ_CPLDINFO 0x6F // Version 2.1 CPLD version information register.
#define IO_TZ_PALSLCTOFF 0xA3 // set the palette slot Off position to be adjusted.
#define IO_TZ_PALSLCTON 0xA4 // set the palette slot On position to be adjusted.
#define IO_TZ_PALSETRED 0xA5 // set the red palette value according to the PALETTE_PARAM_SEL address.
#define IO_TZ_PALSETGREEN 0xA6 // set the green palette value according to the PALETTE_PARAM_SEL address.
#define IO_TZ_PALSETBLUE 0xA7 // set the blue palette value according to the PALETTE_PARAM_SEL address.
#define IO_TZ_OSDMNU_SZX 0xA8 // Get OSD Menu Horizontal Size (X).
#define IO_TZ_OSDMNU_SZY 0xA9 // Get OSD Menu Vertical Size (Y).
#define IO_TZ_OSDHDR_SZX 0xAA // Get OSD Status Header Horizontal Size (X).
#define IO_TZ_OSDHDR_SZY 0xAB // Get OSD Status Header Vertical Size (Y).
#define IO_TZ_OSDFTR_SZX 0xAC // Get OSD Status Footer Horizontal Size (X).
#define IO_TZ_OSDFTR_SZY 0xAD // Get OSD Status Footer Vertical Size (Y).
#define IO_TZ_PALETTE 0xB0 // Sets the palette. The Video Module supports 4 bit per colour output but there is only enough RAM for 1 bit per colour so the pallette is used to change the colours output.
// Bits [7:0] defines the pallete number. This indexes a lookup table which contains the required 4bit output per 1bit input.
#define IO_TZ_GPUPARAM 0xB2 // Set parameters. Store parameters in a long word to be used by the graphics command processor.
// The parameter word is 128 bit and each write to the parameter word shifts left by 8 bits and adds the new byte at bits 7:0.
#define IO_TZ_GPUCMD 0xB3 // Set the graphics processor unit commands.
// Bits [5:0] - 0 = Reset parameters.
// 1 = Clear to val. Start Location (16 bit), End Location (16 bit), Red Filter, Green Filter, Blue Filter
#define IO_TZ_VMCTRL 0xB8 // Video Module control register. [2:0] - 000 (default) = MZ80A, 001 = MZ-700, 010 = MZ800, 011 = MZ80B, 100 = MZ80K, 101 = MZ80C, 110 = MZ1200, 111 = MZ2000. [3] = 0 - 40 col, 1 - 80 col.
#define IO_TZ_VMGRMODE 0xB9 // Video Module graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR), 5=GRAM Output Enable, 4 = VRAM Output Enable, 3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect), 1/0=Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used).
#define IO_TZ_VMREDMASK 0xBA // Video Module Red bit mask (1 bit = 1 pixel, 8 pixels per byte).
#define IO_TZ_VMGREENMASK 0xBB // Video Module Green bit mask (1 bit = 1 pixel, 8 pixels per byte).
#define IO_TZ_VMBLUEMASK 0xBC // Video Module Blue bit mask (1 bit = 1 pixel, 8 pixels per byte).
#define IO_TZ_VMPAGE 0xBD // Video Module memory page register. [1:0] switches in 1 16Kb page (3 pages) of graphics ram to C000 - FFFF. Bits [1:0] = page, 00 = off, 01 = Red, 10 = Green, 11 = Blue. This overrides all MZ700/MZ80B page switching functions. [7] 0 - normal, 1 - switches in CGROM for upload at D000:DFFF.
#define IO_TZ_VMVGATTR 0xBE // Select VGA Border colour and attributes. Bit 2 = Red, 1 = Green, 0 = Blue, 4:3 = VGA Mode, 00 = Off, 01 = 640x480, 10 = 800x600, 11 = 50Hz Internal
#define IO_TZ_VMVGAMODE 0xBF // Select VGA Output mode, ie. Internal, 640x480 etc. Bits [3:0] specify required mode. Undefined default to internal standard frequency.
#define IO_TZ_GDGWF 0xCC // MZ-800 write format register
#define IO_TZ_GDGRF 0xCD // MZ-800 read format register
#define IO_TZ_GDCMD 0xCE // MZ-800 CRTC Mode register
#define IO_TZ_GDCCTRL 0xCF // MZ-800 CRTC control register
#define IO_TZ_MMIO0 0xE0 // MZ-700/MZ-800 Memory management selection ports.
#define IO_TZ_MMIO1 0xE1 // ""
#define IO_TZ_MMIO2 0xE2 // ""
#define IO_TZ_MMIO3 0xE3 // ""
#define IO_TZ_MMIO4 0xE4 // ""
#define IO_TZ_MMIO5 0xE5 // ""
#define IO_TZ_MMIO6 0xE6 // ""
#define IO_TZ_MMIO7 0xE7 // MZ-700/MZ-800 Memory management selection ports.
#define IO_TZ_PPIA 0xE0 // MZ80B/MZ2000 8255 PPI Port A
#define IO_TZ_PPIB 0xE1 // MZ80B/MZ2000 8255 PPI Port B
#define IO_TZ_PPIC 0xE2 // MZ80B/MZ2000 8255 PPI Port C
#define IO_TZ_PPICTL 0xE3 // MZ80B/MZ2000 8255 PPI Control Register
#define IO_TZ_PIT0 0xE4 // MZ80B/MZ2000 8253 PIT Timer 0
#define IO_TZ_PIT1 0xE5 // MZ80B/MZ2000 8253 PIT Timer 1
#define IO_TZ_PIT2 0xE6 // MZ80B/MZ2000 8253 PIT Timer 2
#define IO_TZ_PITCTL 0xE7 // MZ80B/MZ2000 8253 PIT Control Register
#define IO_TZ_PIOA 0xE8 // MZ80B/MZ2000 Z80 PIO Port A
#define IO_TZ_PIOCTLA 0xE9 // MZ80B/MZ2000 Z80 PIO Port A Control Register
#define IO_TZ_PIOB 0xEA // MZ80B/MZ2000 Z80 PIO Port B
#define IO_TZ_PIOCTLB 0xEB // MZ80B/MZ2000 Z80 PIO Port B Control Register
#define IO_TZ_SYSCTRL 0xF0 // System board control register. [2:0] - 000 MZ80A Mode, 2MHz CPU/Bus, 001 MZ80B Mode, 4MHz CPU/Bus, 010 MZ700 Mode, 3.54MHz CPU/Bus.
#define IO_TZ_GRAMMODE 0xF4 // MZ80B Graphics mode. Bit 0 = 0, Write to Graphics RAM I, Bit 0 = 1, Write to Graphics RAM II. Bit 1 = 1, blend Graphics RAM I output on display, Bit 2 = 1, blend Graphics RAM II output on display.
//#define IO_TZ_GRAMOPT 0xF4 // MZ80B/MZ2000 GRAM configuration option.
#define IO_TZ_CRTGRPHPRIO 0xF5 // MZ2000 Graphics priority register, character or a graphics colour has front display priority.
#define IO_TZ_CRTGRPHSEL 0xF6 // MZ2000 Graphics output select on CRT or external CRT
#define IO_TZ_GRAMCOLRSEL 0xF7 // MZ2000 Graphics RAM colour bank select.
// Addresses on the tranZPUter board.
//
#define SRAM_BANK0_ADDR 0x00000 // Address of the 1st 64K RAM bank in the SRAM chip.
#define SRAM_BANK1_ADDR 0x10000 // ""
#define SRAM_BANK2_ADDR 0x20000 // ""
#define SRAM_BANK3_ADDR 0x30000 // ""
#define SRAM_BANK4_ADDR 0x40000 // ""
#define SRAM_BANK5_ADDR 0x50000 // ""
#define SRAM_BANK6_ADDR 0x60000 // ""
#define SRAM_BANK7_ADDR 0x70000 // ""
#define SRAM_BANK8_ADDR 0x80000 // ""
#define SRAM_BANK9_ADDR 0x90000 // ""
#define SRAM_BANKA_ADDR 0xA0000 // ""
#define SRAM_BANKB_ADDR 0xB0000 // ""
#define SRAM_BANKC_ADDR 0xC0000 // ""
#define SRAM_BANKD_ADDR 0xD0000 // ""
#define SRAM_BANKE_ADDR 0xE0000 // ""
#define SRAM_BANKF_ADDR 0xF0000 // Address of the 16th 64K RAM bank in the SRAM chip.
// IO register constants.
//
#define CPUMODE_SET_Z80 0x00 // Set the CPU to the hard Z80.
#define CPUMODE_SET_T80 0x01 // Set the CPU to the soft T80.
#define CPUMODE_SET_ZPU_EVO 0x02 // Set the CPU to the soft ZPU Evolution.
#define CPUMODE_SET_EMU_MZ 0x04 //
#define CPUMODE_SET_BBB 0x08 // Place holder for a future soft CPU.
#define CPUMODE_SET_CCC 0x10 // Place holder for a future soft CPU.
#define CPUMODE_SET_DDD 0x20 // Place holder for a future soft CPU.
#define CPUMODE_IS_Z80 0x00 // Status value to indicate if the hard Z80 available.
#define CPUMODE_IS_T80 0x01 // Status value to indicate if the soft T80 available.
#define CPUMODE_IS_ZPU_EVO 0x02 // Status value to indicate if the soft ZPU Evolution available.
#define CPUMODE_IS_EMU_MZ 0x04 // Status value to indicate if the Sharp MZ Series Emulation is available.
#define CPUMODE_IS_BBB 0x08 // Place holder to indicate if a future soft CPU is available.
#define CPUMODE_IS_CCC 0x10 // Place holder to indicate if a future soft CPU is available.
#define CPUMODE_IS_DDD 0x20 // Place holder to indicate if a future soft CPU is available.
#define CPUMODE_CLK_EN 0x40 // Toggle the soft CPU clock, 1 = enable, 0 = disable.
#define CPUMODE_RESET_CPU 0x80 // Reset the soft CPU. Active high, when high the CPU is held in RESET, when low the CPU runs.
#define CPUMODE_IS_SOFT_AVAIL 0x040 // Marker to indicate if the underlying FPGA can support soft CPU's.
#define CPUMODE_IS_SOFT_MASK 0x03F // Mask to filter out the Soft CPU availability flags.
// CPLD Configuration constants.
#define HWMODE_MZ80K 0x00 // Hardware mode = MZ80K
#define HWMODE_MZ80C 0x01 // Hardware mode = MZ80C
#define HWMODE_MZ1200 0x02 // Hardware mode = MZ1200
#define HWMODE_MZ80A 0x03 // Hardware mode = MZ80A
#define HWMODE_MZ700 0x04 // Hardware mode = MZ700
#define HWMODE_MZ800 0x05 // Hardware mode = MZ800
#define HWMODE_MZ80B 0x06 // Hardware mode = MZ80B
#define HWMODE_MZ2000 0x07 // Hardware mode = MZ2000
#define MODE_VIDEO_MODULE_ENABLED 0x08 // Hardware enable (bit 3 = 1) or disable of the Video Module on the newer version, the one below will be removed.
#define MODE_VIDEO_MODULE_DISABLED 0x00 // Hardware enable (bit 3 = 0) or disable of the Video Module.
#define MODE_PRESERVE_CONFIG 0x80 // Preserve hardware configuration on RESET.
#define CPLD_HAS_FPGA_VIDEO 0x00 // Flag to indicate if this device supports enhanced video.
#define CPLD_VERSION 0x01 // Version of the CPLD which is being emulated. Version 1 was the original version.
// CPLD Command Instruction constants.
#define CPLD_RESET_HOST 1 // CPLD level command to reset the host system.
#define CPLD_HOLD_HOST_BUS 2 // CPLD command to hold the host bus.
#define CPLD_RELEASE_HOST_BUS 3 // CPLD command to release the host bus.
// Video Module control bits.
#define SYSMODE_MZ80A 0x00 // System board mode MZ80A, 2MHz CPU/Bus.
#define SYSMODE_MZ80B 0x01 // System board mode MZ80B, 4MHz CPU/Bus.
#define SYSMODE_MZ700 0x02 // System board mode MZ700, 3.54MHz CPU/Bus.
#define VMMODE_MASK 0xF0 // Mask to mask out video mode.
#define VMMODE_MZ80K 0x00 // Video mode = MZ80K
#define VMMODE_MZ80C 0x01 // Video mode = MZ80C
#define VMMODE_MZ1200 0x02 // Video mode = MZ1200
#define VMMODE_MZ80A 0x03 // Video mode = MZ80A
#define VMMODE_MZ700 0x04 // Video mode = MZ700
#define VMMODE_MZ800 0x05 // Video mode = MZ800
#define VMMODE_MZ1500 0x06 // Video mode = MZ1500
#define VMMODE_MZ80B 0x07 // Video mode = MZ80B
#define VMMODE_MZ2000 0x08 // Video mode = MZ2000
#define VMMODE_MZ2200 0x09 // Video mode = MZ2200
#define VMMODE_MZ2500 0x0A // Video mode = MZ2500
#define VMMODE_80CHAR 0x10 // Enable 80 character display.
#define VMMODE_80CHAR_MASK 0xEF // Mask to filter out display width control bit.
#define VMMODE_COLOUR 0x20 // Enable colour display.
#define VMMODE_COLOUR_MASK 0xDF // Mask to filter out colour control bit.
#define VMMODE_PCGRAM 0x40 // Enable PCG RAM.
#define VMMODE_VGA_MASK 0xF0 // Mask to filter out the VGA output mode bits.
#define VMMODE_VGA_OFF 0x00 // Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
#define VMMODE_VGA_INT 0x00 // Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
#define VMMODE_VGA_INT50 0x01 // Set VGA mode off, external monitor is driven by standard internal 50Hz signals.
#define VMMODE_VGA_640x480 0x02 // Set external monitor to VGA 640x480 @ 60Hz mode.
#define VMMODE_VGA_800x600 0x03 // Set external monitor to VGA 800x600 @ 60Hz mode.
// VGA mode border control constants.
//
#define VMBORDER_BLACK 0x00 // VGA has a black border.
#define VMBORDER_BLUE 0x01 // VGA has a blue border.
#define VMBORDER_RED 0x02 // VGA has a red border.
#define VMBORDER_PURPLE 0x03 // VGA has a purple border.
#define VMBORDER_GREEN 0x04 // VGA has a green border.
#define VMBORDER_CYAN 0x05 // VGA has a cyan border.
#define VMBORDER_YELLOW 0x06 // VGA has a yellow border.
#define VMBORDER_WHITE 0x07 // VGA has a white border.
#define VMBORDER_MASK 0xF8 // Mask to filter out current border setting.
// Sharp MZ colour attributes.
#define VMATTR_FG_BLACK 0x00 // Foreground black character attribute.
#define VMATTR_FG_BLUE 0x10 // Foreground blue character attribute.
#define VMATTR_FG_RED 0x20 // Foreground red character attribute.
#define VMATTR_FG_PURPLE 0x30 // Foreground purple character attribute.
#define VMATTR_FG_GREEN 0x40 // Foreground green character attribute.
#define VMATTR_FG_CYAN 0x50 // Foreground cyan character attribute.
#define VMATTR_FG_YELLOW 0x60 // Foreground yellow character attribute.
#define VMATTR_FG_WHITE 0x70 // Foreground white character attribute.
#define VMATTR_FG_MASKOUT 0x8F // Mask to filter out foreground attribute.
#define VMATTR_FG_MASKIN 0x70 // Mask to filter out foreground attribute.
#define VMATTR_BG_BLACK 0x00 // Background black character attribute.
#define VMATTR_BG_BLUE 0x01 // Background blue character attribute.
#define VMATTR_BG_RED 0x02 // Background red character attribute.
#define VMATTR_BG_PURPLE 0x03 // Background purple character attribute.
#define VMATTR_BG_GREEN 0x04 // Background green character attribute.
#define VMATTR_BG_CYAN 0x05 // Background cyan character attribute.
#define VMATTR_BG_YELLOW 0x06 // Background yellow character attribute.
#define VMATTR_BG_WHITE 0x07 // Background white character attribute.
#define VMATTR_BG_MASKOUT 0xF8 // Mask to filter out background attribute.
#define VMATTR_BG_MASKIN 0x07 // Mask to filter out background attribute.
// Sharp MZ constants.
//
#define MZ_MROM_ADDR 0x00000 // Monitor ROM start address.
#define MZ_800_MROM_ADDR 0x70000 // MZ-800 Monitor ROM address.
#define MZ_800_CGROM_ADDR 0x71000 // MZ-800 CGROM address during reset when it is loaded into the PCG.
#define MZ_800_IPL_ADDR 0x7E000 // Address of the 9Z_504M IPL BIOS.
#define MZ_800_IOCS_ADDR 0x7F400 // Address of the MZ-800 common IOCS bios.
#define MZ_MROM_STACK_ADDR 0x01000 // Monitor ROM start stack address.
#define MZ_MROM_STACK_SIZE 0x000EF // Monitor ROM stack size.
#define MZ_UROM_ADDR 0x0E800 // User ROM start address.
#define MZ_FULLRAM_START_ADDR 0x01200 // Start of full memory area available for bank switching.
#define MZ_FULLRAM_SIZE 0xD000 - 0x1200 // Size of full memory area.
#define MZ_BANKRAM_ADDR 0x0F000 // Floppy API address which is used in TZFS as the paged RAM for additional functionality.
#define MZ_CMT_ADDR 0x010F0 // Address of the CMT (tape) header record.
#define MZ_CMT_DEFAULT_LOAD_ADDR 0x01200 // The default load address for a CMT, anything below this is normally illegal.
#define MZ_VID_RAM_ADDR 0x0D000 // Start of Video RAM
#define MZ_VID_RAM_SIZE 2048 // Size of Video RAM.
#define MZ_VID_MAX_COL 40 // Maximum column for the host display
#define MZ_VID_MAX_ROW 25 // Maximum row for the host display
#define MZ_VID_DFLT_BYTE 0x00 // Default character (SPACE) for video RAM.
#define MZ_ATTR_RAM_ADDR 0xD800 // On machines with the upgrade, the start of the Attribute RAM.
#define MZ_ATTR_RAM_SIZE 2048 // Size of the attribute RAM.
#define MZ_ATTR_DFLT_BYTE 0x07 // Default colour (White on Black) for the attribute.
#define MZ_SCROL_BASE 0xE200 // Base address of the hardware scroll registers.
#define MZ_SCROL_END 0xE2FF // End address of the hardware scroll registers.
#define MZ_MEMORY_SWAP 0xE00C // Address when read swaps the memory from 0000-0FFF -> C000-CFFF
#define MZ_MEMORY_RESET 0xE010 // Address when read resets the memory to the default location 0000-0FFF.
#define MZ_CRT_NORMAL 0xE014 // Address when read sets the CRT to normal display mode.
#define MZ_CRT_INVERSE 0xE018 // Address when read sets the CRT to inverted display mode.
#define MZ_80A_CPU_FREQ 2000000 // CPU Speed of the Sharp MZ-80A
#define MZ_700_CPU_FREQ 3580000 // CPU Speed of the Sharp MZ-700
#define MZ_80B_CPU_FREQ 4000000 // CPU Speed of the Sharp MZ-80B
#define MZ_2000_CPU_FREQ 4000000 // CPU Speed of the Sharp MZ-2000
#define MZ_800_CPU_FREQ 3580000 // CPU Speed of the Sharp MZ-800
// Service request constants.
//
#define TZSVC_CMD_STRUCT_ADDR_TZFS 0x0ED80 // Address of the command structure within TZFS - exists in 64K Block 0.
#define TZSVC_CMD_STRUCT_ADDR_CPM 0x4F560 // Address of the command structure within CP/M - exists in 64K Block 4.
#define TZSVC_CMD_STRUCT_ADDR_MZ700 0x6FD80 // Address of the command structure within MZ700 compatible programs - exists in 64K Block 6.
#define TZSVC_CMD_STRUCT_ADDR_ZOS 0x11FD80 // 0x7FD80 // Address of the command structure for zOS use, exists in shared memory rather than FPGA. Spans top of block 6 and all of block 7.
#define TZSVC_CMD_STRUCT_ADDR_MZ2000_NST 0x6FD80 // Address of the command structure within MZ2000 compatible programs during normal state - exists in 64K Block 1.
#define TZSVC_CMD_STRUCT_ADDR_MZ2000_IPL 0x07D80 // Address of the command structure within MZ2000 compatible programs during IPL state - exists in 64K Block 0.
#define TZSVC_CMD_STRUCT_SIZE 0x280 // Size of the inter z80/K64 service command memory.
#define TZSVC_CMD_SIZE (sizeof(t_svcControl)-TZSVC_SECTOR_SIZE)
#define TZVC_MAX_CMPCT_DIRENT_BLOCK TZSVC_SECTOR_SIZE/TZSVC_CMPHDR_SIZE // Maximum number of directory entries per sector.
#define TZSVC_MAX_DIR_ENTRIES 255 // Maximum number of files in one directory, any more than this will be ignored.
#define TZSVC_CMPHDR_SIZE 32 // Compacted header size, contains everything except the comment field, padded out to 32bytes.
#define MZF_FILLER_LEN 8 // Filler to pad a compacted header entry to a power of 2 length.
#define TZVC_MAX_DIRENT_BLOCK TZSVC_SECTOR_SIZE/MZF_HEADER_SIZE // Maximum number of directory entries per sector.
#define TZSVC_CMD_READDIR 0x01 // Service command to open a directory and return the first block of entries.
#define TZSVC_CMD_NEXTDIR 0x02 // Service command to return the next block of an open directory.
#define TZSVC_CMD_READFILE 0x03 // Service command to open a file and return the first block.
#define TZSVC_CMD_NEXTREADFILE 0x04 // Service command to return the next block of an open file.
#define TZSVC_CMD_WRITEFILE 0x05 // Service command to create a file and save the first block.
#define TZSVC_CMD_NEXTWRITEFILE 0x06 // Service command to write the next block to the open file.
#define TZSVC_CMD_CLOSE 0x07 // Service command to close any open file or directory.
#define TZSVC_CMD_LOADFILE 0x08 // Service command to load a file directly into tranZPUter memory.
#define TZSVC_CMD_SAVEFILE 0x09 // Service command to save a file directly from tranZPUter memory.
#define TZSVC_CMD_ERASEFILE 0x0a // Service command to erase a file on the SD card.
#define TZSVC_CMD_CHANGEDIR 0x0b // Service command to change active directory on the SD card.
#define TZSVC_CMD_LOAD40ABIOS 0x20 // Service command requesting that the 40 column version of the SA1510 BIOS is loaded.
#define TZSVC_CMD_LOAD80ABIOS 0x21 // Service command requesting that the 80 column version of the SA1510 BIOS is loaded.
#define TZSVC_CMD_LOAD700BIOS40 0x22 // Service command requesting that the MZ700 1Z-013A 40 column BIOS is loaded.
#define TZSVC_CMD_LOAD700BIOS80 0x23 // Service command requesting that the MZ700 1Z-013A 80 column patched BIOS is loaded.
#define TZSVC_CMD_LOAD80BIPL 0x24 // Service command requesting the MZ-80B IPL is loaded.
#define TZSVC_CMD_LOAD800BIOS 0x25 // Service command requesting that the MZ800 9Z-504M BIOS is loaded.
#define TZSVC_CMD_LOAD2000IPL 0x26 // Service command requesting the MZ-2000 IPL is loaded.
#define TZSVC_CMD_LOADTZFS 0x2F // Service command requesting the loading of TZFS. This service is for machines which normally dont have a monitor BIOS. ie. MZ-80B/MZ-2000 and manually request TZFS.
#define TZSVC_CMD_LOADBDOS 0x30 // Service command to reload CPM BDOS+CCP.
#define TZSVC_CMD_ADDSDDRIVE 0x31 // Service command to attach a CPM disk to a drive number.
#define TZSVC_CMD_READSDDRIVE 0x32 // Service command to read an attached SD file as a CPM disk drive.
#define TZSVC_CMD_WRITESDDRIVE 0x33 // Service command to write to a CPM disk drive which is an attached SD file.
#define TZSVC_CMD_CPU_BASEFREQ 0x40 // Service command to switch to the mainboard frequency.
#define TZSVC_CMD_CPU_ALTFREQ 0x41 // Service command to switch to the alternate frequency provided by the K64F.
#define TZSVC_CMD_CPU_CHGFREQ 0x42 // Service command to set the alternate frequency in hertz.
#define TZSVC_CMD_CPU_SETZ80 0x50 // Service command to switch to the external Z80 hard cpu.
#define TZSVC_CMD_CPU_SETT80 0x51 // Service command to switch to the internal T80 soft cpu.
#define TZSVC_CMD_CPU_SETZPUEVO 0x52 // Service command to switch to the internal ZPU Evolution cpu.
#define TZSVC_CMD_EMU_SETMZ80K 0x53 // Service command to switch to the internal Sharp MZ Series Emulation of the MZ80K.
#define TZSVC_CMD_EMU_SETMZ80C 0x54 // "" "" "" MZ80C.
#define TZSVC_CMD_EMU_SETMZ1200 0x55 // "" "" "" MZ1200.
#define TZSVC_CMD_EMU_SETMZ80A 0x56 // "" "" "" MZ80A.
#define TZSVC_CMD_EMU_SETMZ700 0x57 // "" "" "" MZ700.
#define TZSVC_CMD_EMU_SETMZ800 0x58 // "" "" "" MZ800.
#define TZSVC_CMD_EMU_SETMZ1500 0x59 // "" "" "" MZ1500.
#define TZSVC_CMD_EMU_SETMZ80B 0x5A // "" "" "" MZ80B.
#define TZSVC_CMD_EMU_SETMZ2000 0x5B // "" "" "" MZ2000.
#define TZSVC_CMD_EMU_SETMZ2200 0x5C // "" "" "" MZ2200.
#define TZSVC_CMD_EMU_SETMZ2500 0x5D // "" "" "" MZ2500.
#define TZSVC_CMD_SD_DISKINIT 0x60 // Service command to initialise and provide raw access to the underlying SD card.
#define TZSVC_CMD_SD_READSECTOR 0x61 // Service command to provide raw read access to the underlying SD card.
#define TZSVC_CMD_SD_WRITESECTOR 0x62 // Service command to provide raw write access to the underlying SD card.
#define TZSVC_CMD_EXIT 0x7F // Service command to terminate TZFS and restart the machine in original mode.
#define TZSVC_DEFAULT_TZFS_DIR "TZFS" // Default directory where TZFS files are stored.
#define TZSVC_DEFAULT_CPM_DIR "CPM" // Default directory where CPM files are stored.
#define TZSVC_DEFAULT_MZF_DIR "MZF" // Default directory where MZF files are stored.
#define TZSVC_DEFAULT_CAS_DIR "CAS" // Default directory where BASIC CASsette files are stored.
#define TZSVC_DEFAULT_BAS_DIR "BAS" // Default directory where BASIC text files are stored.
#define TZSVC_DEFAULT_MZF_EXT "MZF" // Default file extension for MZF files.
#define TZSVC_DEFAULT_CAS_EXT "CAS" // Default file extension for CASsette files.
#define TZSVC_DEFAULT_BAS_EXT "BAS" // Default file extension for BASic script files stored in readable text.
#define TZSVC_DEFAULT_WILDCARD "*" // Default wildcard file matching.
#define TZSVC_RESULT_OFFSET 0x01 // Offset into structure of the result byte.
#define TZSVC_DIRNAME_SIZE 20 // Limit is size of FAT32 directory name.
#define TZSVC_WILDCARD_SIZE 20 // Very basic pattern matching so small size.
#define TZSVC_FILENAME_SIZE MZF_FILENAME_LEN // Length of a Sharp MZF filename.
#define TZSVC_LONG_FNAME_SIZE (sizeof(t_svcCmpDirEnt) - 1) // Length of a standard filename to fit inside a directory entry.
#define TZSVC_LONG_FMT_FNAME_SIZE 20 // Length of a standard filename formatted in a directory listing.
#define TZSVC_SECTOR_SIZE 512 // SD Card sector buffer size.
#define TZSVC_STATUS_OK 0x00 // Flag to indicate the K64F processing completed successfully.
#define TZSVC_STATUS_FILE_ERROR 0x01 // Flag to indicate a file or directory error.
#define TZSVC_STATUS_BAD_CMD 0x02 // Flag to indicate a bad service command was requested.
#define TZSVC_STATUS_BAD_REQ 0x03 // Flag to indicate a bad request was made, the service status request flag was not set.
#define TZSVC_STATUS_REQUEST 0xFE // Flag to indicate Z80 has posted a request.
#define TZSVC_STATUS_PROCESSING 0xFF // Flag to indicate the K64F is processing a command.
#define TZSVC_OPEN 0x00 // Service request to open a directory or file.
#define TZSVC_NEXT 0x01 // Service request to return the next directory block or file block or write the next file block.
#define TZSVC_CLOSE 0x02 // Service request to close open dir/file.
// ROM file paths.
#define MZ_ROM_SP1002 "SP1002.rom" // Original MZ-80K ROM
#define MZ_ROM_SA1510_40C "SA1510.rom" // Original 40 character Monitor ROM.
#define MZ_ROM_SA1510_80C "SA1510-8.rom" // Original Monitor ROM patched for 80 character screen mode.
#define MZ_ROM_1Z_013A_40C "1Z-013A.rom" // Original 40 character Monitor ROM for the Sharp MZ700.
#define MZ_ROM_1Z_013A_80C "1Z-013A-8.rom" // Original Monitor ROM patched for the Sharp MZ700 patched for 80 column mode.
#define MZ_ROM_1Z_013A_KM_40C "1Z-013A-KM.rom" // Original 40 character Monitor ROM for the Sharp MZ700 with keyboard remapped for the MZ80A.
#define MZ_ROM_1Z_013A_KM_80C "1Z-013A-KM-8.rom" // Original Monitor ROM patched for the Sharp MZ700 with keyboard remapped for the MZ80A and patched for 80 column mode.
#define MZ_ROM_1Z_013A_2000 "1Z-013A-2000.rom" // Original 40 character Monitor ROM for the Sharp MZ700 modified to run on an MZ-2000.
#define MZ_ROM_9Z_504M_COMBINED "MZ800_IPL.rom" // Original MZ-800 BIOS which comprises the 1Z_013B BIOS, 9Z_504M IPL, CGROM and IOCS.
#define MZ_ROM_9Z_504M "MZ800_9Z_504M.rom" // Modified MZ-800 9Z_504M IPL to contain a select TZFS option.
#define MZ_ROM_1Z_013B "MZ800_1Z_013B.rom" // Original MZ-800 1Z_013B MZ-700 compatible BIOS.
#define MZ_ROM_800_CGROM "MZ800_CGROM.ori" // Original MZ-800 Character Generator ROM.
#define MZ_ROM_800_IOCS "MZ800_IOCS.rom" // Original MZ-800 common IOCS bios.
#define MZ_ROM_MZ80B_IPL "MZ80B_IPL.rom" // Original IPL ROM for the Sharp MZ-80B.
#define MZ_ROM_MZ2000_IPL "MZ2000_IPL.rom" // Original IPL ROM for the Sharp MZ-2000.
#define MZ_ROM_MZ2000_IPL_TZPU "MZ2000_IPL_TZPU.rom" // Modified IPL ROM for the tranZPUter running on the Sharp MZ-2000.
#define MZ_ROM_MZ2000_CGROM "MZ2000_CGROM.rom" // MZ-2000 CGROM.
#define MZ_ROM_TZFS "tzfs.rom" // tranZPUter Filing System ROM.
// CP/M constants.
//
#define CPM_MAX_DRIVES 16 // Maximum number of drives in CP/M.
#define CPM_SD_DRIVES_DIR TZSVC_DEFAULT_CPM_DIR "/SDC16M/RAW" // Default directory where CPM SD disk drive images are stored.
#define CPM_DRIVE_TMPL "CPMDSK%02u.RAW" // Template for CPM disk drives stored on the SD card.
#define CPM_SECTORS_PER_TRACK 32 // Number of sectors in a track on the virtual CPM disk.
#define CPM_TRACKS_PER_DISK 1024 // Number of tracks on a disk.
// Constants for the Sharp MZ80A MZF file format.
#define MZF_HEADER_SIZE 128 // Size of the MZF header.
#define MZF_ATTRIBUTE 0x00 // Code Type, 01 = Machine Code.
#define MZF_FILENAME 0x01 // Title/Name (17 bytes).
#define MZF_FILENAME_LEN 17 // Length of the filename, it is not NULL terminated, generally a CR can be taken as terminator but not guaranteed.
#define MZF_FILESIZE 0x12 // Size of program.
#define MZF_LOADADDR 0x14 // Load address of program.
#define MZF_EXECADDR 0x16 // Exec address of program.
#define MZF_COMMENT 0x18 // Comment, used for details of the file or startup code.
#define MZF_COMMENT_LEN 104 // Length of the comment field.
#define CMT_TYPE_OBJCD 0x001 // MZF contains a binary object.
#define CMT_TYPE_BTX1CD 0x002 // MZF contains a BASIC program.
#define CMT_TYPE_BTX2CD 0x005 // MZF contains a BASIC program.
#define CMT_TYPE_TZOBJCD0 0x0F8 // MZF contains a TZFS binary object for page 0.
#define CMT_TYPE_TZOBJCD1 0x0F9
#define CMT_TYPE_TZOBJCD2 0x0FA
#define CMT_TYPE_TZOBJCD3 0x0FB
#define CMT_TYPE_TZOBJCD4 0x0FC
#define CMT_TYPE_TZOBJCD5 0x0FD
#define CMT_TYPE_TZOBJCD6 0x0FE
#define CMT_TYPE_TZOBJCD7 0x0FF // MZF contains a TZFS binary object for page 7.
// Constants for other handled file formats.
//
#define CAS_HEADER_SIZE 256 // Size of the CASsette header.
// Possible targets the K64F can read from/write to.
enum TARGETS {
MAINBOARD = 0,
TRANZPUTER = 1
};
// Possible machine hardware types the tranZPUter is functioning within.
//
enum MACHINE_HW_TYPES {
HW_MZ80K = HWMODE_MZ80K, // Host hardware = MZ-80K.
HW_MZ80C = HWMODE_MZ80C, // Host hardware = MZ-80C.
HW_MZ1200 = HWMODE_MZ1200, // Host hardware = MZ-1200.
HW_MZ80A = HWMODE_MZ80A, // Host hardware = MZ-80A.
HW_MZ700 = HWMODE_MZ700, // Host hardware = MZ-700.
HW_MZ800 = HWMODE_MZ800, // Host hardware = MZ-800.
HW_MZ80B = HWMODE_MZ80B, // Host hardware = MZ-80B.
HW_MZ2000 = HWMODE_MZ2000, // Host hardware = MZ-2000.
HW_UNKNOWN = 0xFF // Host hardware unknown, fault or CPLD misconfiguration.
};
// Groups to which the machines belong. This is a lineage route of the Sharp machines.
//
enum MACHINE_GROUP {
GROUP_MZ80K = 0, // Machines in the MZ80K group, ie. MZ80K/C/1200/80A
GROUP_MZ700 = 1, // Machines in the MZ700 group, ie. MZ700/800/1500
GROUP_MZ80B = 2 // Machines in the MZ80B group, ie. MZ80B/2000/2200/2500
};
// Types of file which have handlers and can be processed.
//
enum FILE_TYPE {
MZF = 0, // Sharp MZF tape image files.
MZFHDR = 1, // Sharp MZF Header from file only.
CAS = 2, // BASIC CASsette image files.
BAS = 3, // BASic ASCII text script files.
ALL = 10, // All files to be considered.
ALLFMT = 11 // Special case for directory listings, all files but truncated and formatted.
};
// File function return code (FRESULT) - From FatFS.
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
// Following are only required for the user space daemon which emulates the Cortex-M4 on the tranZPUter SW
#ifndef __KERNEL_DRIVER__
// Structure to define a Sharp MZ80A MZF directory structure. This header appears at the beginning of every Sharp MZ80A tape (and more recently archived/emulator) images.
//
typedef struct __attribute__((__packed__)) {
uint8_t attr; // MZF attribute describing the file.
uint8_t fileName[MZF_FILENAME_LEN]; // Each directory entry is the size of an MZF filename.
uint16_t fileSize; // Size of file.
uint16_t loadAddr; // Load address for the file.
uint16_t execAddr; // Execution address where the Z80 starts processing.
uint8_t comment[MZF_COMMENT_LEN]; // Text comment field but often contains a startup machine code program.
} t_svcDirEnt;
// Structure to define a compacted Sharp MZ80A MZF directory structure (no comment) for use in directory listings.
// This header appears at the beginning of every Sharp MZ80A tape (and more recently archived/emulator) images.
//
typedef struct __attribute__((__packed__)) {
uint8_t attr; // MZF attribute describing the file.
uint8_t fileName[MZF_FILENAME_LEN]; // Each directory entry is the size of an MZF filename.
uint16_t fileSize; // Size of file.
uint16_t loadAddr; // Load address for the file.
uint16_t execAddr; // Execution address where the Z80 starts processing.
uint8_t filler[MZF_FILLER_LEN]; // Filler to pad to a power of 2 length.
} t_svcCmpDirEnt;
// Structure to hold the map betwen an SD filename and the Sharp file it contains. The file is an MZF format file with a 128 byte header
// and this header contains the name understood on the Sharp MZ80A.
//
typedef struct __attribute__((__packed__)) {
uint8_t *sdFileName; // Name of file on the SD card.
t_svcCmpDirEnt mzfHeader; // Compact Sharp header data of this file.
} t_sharpToSDMap;
// Structure to define the control information for a CP/M disk drive.
//
typedef struct {
uint8_t *fileName; // FQFN of the CPM disk image file.
uint32_t lastTrack; // Track of last successful operation.
uint32_t lastSector; // Sector of last successful operation.
FILE *File; // Opened file handle of the CPM disk image.
} t_cpmDrive;
// Structure to define which CP/M drives are added to the system, mapping a number from CP/M into a record containing the details of the file on the SD card.
//
typedef struct {
t_cpmDrive *drive[CPM_MAX_DRIVES]; // 1:1 map of CP/M drive number to an actual file on the SD card.
} t_cpmDriveMap;
// Structure to hold a map of an entire directory of files on the SD card and their associated Sharp MZ0A filename.
typedef struct __attribute__((__packed__)) {
uint8_t valid; // Is this mapping valid?
uint8_t entries; // Number of entries in cache.
uint8_t type; // Type of file being cached.
char directory[TZSVC_DIRNAME_SIZE]; // Directory this mapping is associated with.
union {
t_sharpToSDMap *mzfFile[TZSVC_MAX_DIR_ENTRIES]; // File mapping of SD file to its Sharp MZ80A name.
uint8_t *sdFileName[TZSVC_MAX_DIR_ENTRIES]; // No mapping for SD filenames, just the file name.
};
} t_dirMap;
// Structure to maintain all MZ700 hardware control information in order to emulate the machine.
//
typedef struct {
uint32_t config; // Compacted control register, 31:19 = reserved, 18 = Inhibit mode, 17 = Upper D000:FFFF is RAM (=1), 16 = Lower 0000:0FFF is RAM (=1), 15:8 = old memory mode, 7:0 = current memory mode.
//uint8_t memoryMode; // The memory mode the MZ700 is currently running under, this is determined by the memory control commands from the MZ700.
//uint8_t lockMemoryMode; // The preserved memory mode when entering the locked state.
//uint8_t inhibit; // The inhibit flag, blocks the upper 0xD000:0xFFFF region from being accessed, affects the memoryMode temporarily.
//uint8_t update; // Update flag, indicates to the ISR that a memory mode update is needed.
//uint8_t b0000; // Block 0000:0FFF mode.
//uint8_t bD000; // Block D000:FFFF mode.
} t_mz700;
// Structure to maintain all MZ-80B hardware control information in order to emulate the machine as near as possible.
typedef struct {
uint32_t config; // Compacted control register, 31:19 = reserved, 18 = Inhibit mode, 17 = Upper D000:FFFF is RAM (=1), 16 = Lower 0000:0FFF is RAM (=1), 15:8 = old memory mode, 7:0 = current memory mode.
} t_mz80b;
// Structure to maintain all the control and management variables of the Z80 and underlying hardware so that the state of run is well known by any called method.
//
typedef struct {
#if !defined(__APP__) || defined(__TZFLUPD__)
uint32_t svcControlAddr; // Address of the service control record within the Z80 static RAM bank.
uint8_t refreshAddr; // Refresh address for times when the K64F must issue refresh cycles on the Z80 bus.
uint8_t disableRefresh; // Disable refresh if the mainboard DRAM isnt being used.
enum MACHINE_HW_TYPES hostType; // The underlying host machine, 0 = Sharp MZ-80A, 1 = MZ-700, 2 = MZ-80B
uint8_t iplMode; // Flag to indicate if the host is in IPL (boot) or run mode. Applicable on the MZ-2000/MZ-80B only.
uint8_t blockResetActions; // Flag to request reset actions are blocked on the next detected reset. This is useful on startup or when loading a monitor ROM set different to the default.
t_mz700 mz700; // MZ700 emulation control to detect IO commands and adjust the memory map accordingly.
t_mz80b mz80b; // MZ-80B emulation control to detect IO commands and adjust the memory map and I/O forwarding accordingly.
uint8_t resetEvent; // A Z80_RESET event occurred, probably user pressing RESET button.
uint32_t freqMultiplier; // Multipler to be applied to CPU frequency.
int fdZ80; // Handle to the Z80 kernel.
#endif
} t_z80Control;
// Structure to maintain higher level OS control and management variables typically used for TZFS and CPM.
//
typedef struct {
uint8_t tzAutoBoot; // Autoboot the tranZPUter into TZFS mode.
t_dirMap dirMap; // Directory map of SD filenames to Sharp MZ80A filenames.
t_cpmDriveMap cpmDriveMap; // Map of file number to an open SD disk file to be used as a CPM drive.
uint8_t *lastFile; // Last file loaded - typically used for CPM to reload itself.
} t_osControl;
// Structure to contain inter CPU communications memory for command service processing and results.
// Typically the z80 places a command into the structure in it's memory space and asserts an I/O request,
// the K64F detects the request and reads the lower portion of the struct from z80 memory space,
// determines the command and then either reads the remainder or writes to the remainder. This struct
// exists in both the z80 and K64F domains and data is sync'd between them as needed.
//
typedef struct __attribute__((__packed__)) {
uint8_t cmd; // Command request.
uint8_t result; // Result code. 0xFE - set by Z80, command available, 0xFE - set by K64F, command ack and processing. 0x00-0xF0 = cmd complete and result of processing.
union {
uint8_t dirSector; // Virtual directory sector number.
uint8_t fileSector; // Sector within open file to read/write.
uint8_t vDriveNo; // Virtual or physical SD card drive number.
};
union {
struct {
uint16_t trackNo; // For virtual drives with track and sector this is the track number
uint16_t sectorNo; // For virtual drives with track and sector this is the sector number. NB For LBA access, this is 32bit and overwrites fileNo/fileType which arent used during raw SD access.
};
uint32_t sectorLBA; // For LBA access, this is 32bit and used during raw SD access.
struct {
uint8_t memTarget; // Target memory for operation, 0 = tranZPUter, 1 = mainboard.
uint8_t spare1; // Unused variable.
uint16_t spare2; // Unused variable.
};
};
uint8_t fileNo; // File number of a file within the last directory listing to open/update.
uint8_t fileType; // Type of file being processed.
union {
uint16_t loadAddr; // Load address for ROM/File images which need to be dynamic.
uint16_t saveAddr; // Save address for ROM/File images which need to be dynamic.
uint16_t cpuFreq; // CPU Frequency in KHz - used for setting of the alternate CPU clock frequency.
};
union {
uint16_t loadSize; // Size for ROM/File to be loaded.
uint16_t saveSize; // Size for ROM/File to be saved.
};
uint8_t directory[TZSVC_DIRNAME_SIZE]; // Directory in which to look for a file. If no directory is given default to MZF.
uint8_t filename[TZSVC_FILENAME_SIZE]; // File to open or create.
uint8_t wildcard[TZSVC_WILDCARD_SIZE]; // A basic wildcard pattern match filter to be applied to a directory search.
uint8_t sector[TZSVC_SECTOR_SIZE]; // Sector buffer generally for disk read/write.
} t_svcControl;
// Structure to define all the directory entries which are packed into a single SD sector which is used between the Z80<->K64F.
//
typedef struct __attribute__((__packed__)) {
t_svcDirEnt dirEnt[TZVC_MAX_DIRENT_BLOCK]; // Fixed number of directory entries per sector/block.
} t_svcDirBlock;
// Structure to hold compacted directory entries which are packed into a single SD sector which is used between the Z80<->K64F.
//
typedef struct __attribute__((__packed__)) {
t_svcCmpDirEnt dirEnt[TZVC_MAX_CMPCT_DIRENT_BLOCK];// Fixed number of compacted directory entries per sector/block.
} t_svcCmpDirBlock;
// Mapping table from Sharp MZ80A Ascii to real Ascii.
//
typedef struct {
uint8_t asciiCode;
} t_asciiMap;
// Mapping table from Ascii to Sharp MZ display code.
//
typedef struct {
uint8_t dispCode;
} t_dispCodeMap;
// Prototypes.
//
void reqResetZ80(uint8_t);
void startZ80(uint8_t memoryMode);
void stopZ80(uint8_t memoryMode);
uint32_t setZ80CPUFrequency(float, uint8_t);
uint8_t copyFromZ80(uint8_t *, uint32_t, uint32_t, enum TARGETS);
uint8_t copyToZ80(uint32_t, uint8_t *, uint32_t, enum TARGETS);
uint8_t writeZ80Memory(uint32_t, uint8_t, enum TARGETS);
uint8_t readZ80Memory(uint32_t);
void fillZ80Memory(uint32_t, uint32_t, uint8_t, enum TARGETS);
FRESULT loadZ80Memory(const char *, uint32_t, uint32_t, uint32_t, uint32_t *, enum TARGETS);
FRESULT saveZ80Memory(const char *, uint32_t, uint32_t, t_svcDirEnt *, enum TARGETS);
FRESULT loadMZFZ80Memory(const char *, uint32_t, uint32_t *, uint8_t, enum TARGETS);
int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryType, uint32_t memwidth, uint32_t dispaddr, uint8_t dispwidth);
// Getter/Setter methods!
void convertSharpFilenameToAscii(char *, char *, uint8_t);
void convertToFAT32FileNameFormat(char *);
// tranZPUter OS i/f methods.
uint8_t setZ80SvcStatus(uint8_t);
void svcSetDefaults(enum FILE_TYPE);
uint8_t svcReadDir(uint8_t, enum FILE_TYPE);
uint8_t svcFindFile(char *, char *, uint8_t, enum FILE_TYPE);
uint8_t svcReadDirCache(uint8_t, enum FILE_TYPE);
uint8_t svcFindFileCache(char *, char *, uint8_t, enum FILE_TYPE);
uint8_t svcCacheDir(const char *, enum FILE_TYPE, uint8_t);
uint8_t svcReadFile(uint8_t, enum FILE_TYPE);
uint8_t svcWriteFile(uint8_t, enum FILE_TYPE);
uint8_t svcLoadFile(enum FILE_TYPE);
uint8_t svcSaveFile(enum FILE_TYPE);
uint8_t svcEraseFile(enum FILE_TYPE);
uint8_t svcAddCPMDrive(void);
uint8_t svcReadCPMDrive(void);
uint8_t svcWriteCPMDrive(void);
uint32_t getServiceAddr(void);
void processServiceRequest(void);
uint8_t loadBIOS(const char *, uint32_t);
FRESULT loadTZFS(char *, uint32_t);
void loadTranZPUterDefaultROMS(uint8_t);
uint8_t testTZFSAutoBoot(void);
#endif // __KERNEL_DRIVER__
#ifdef __cplusplus
}
#endif
#endif // TZPU_H

View File

@@ -12,10 +12,11 @@
//
// Credits: Zilog Z80 CPU Emulator v0.2 written by Manuel Sainz de Baranda y Goñi
// The Z80 CPU Emulator is the heart of the Z80 device driver.
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
// (c) 1999-2022 Manuel Sainz de Baranda y Goñi
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
// (c) 1999-2023 Manuel Sainz de Baranda y Goñi
//
// History: Oct 2022 - Initial write of the z80 kernel driver software.
// History: Oct 2022 v1.0 - v1.Initial write of the z80 kernel driver software.
// Feb 2023 v1.1 - Extended to allow Rom upload for RFS and other drivers.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -53,9 +54,9 @@
#include <Z80.h>
#include "z80driver.h"
#define VERSION "1.0"
#define VERSION "1.1"
#define AUTHOR "P.D.Smart"
#define COPYRIGHT "(c) 2018-22"
#define COPYRIGHT "(c) 2018-23"
// Getopt_long is buggy so we use optparse.
#define OPTPARSE_IMPLEMENTATION
@@ -111,14 +112,23 @@ enum CTRL_COMMANDS {
Z80_CMD_VIRTUAL_RAM = 7,
Z80_CMD_DUMP_MEMORY = 8,
Z80_CMD_MEMORY_TEST = 9,
CPLD_CMD_SEND_CMD = 10,
CPLD_CMD_SPI_TEST = 11,
CPLD_CMD_PRL_TEST = 12
Z80_CMD_ADD_DEVICE = 10,
Z80_CMD_DEL_DEVICE = 11,
CPLD_CMD_SEND_CMD = 12,
CPLD_CMD_SPI_TEST = 13,
CPLD_CMD_PRL_TEST = 14,
#if(DEBUG_ENABLED != 0)
Z80_CMD_DEBUG = 15,
#endif
};
// Shared memory between this process and the Z80 driver.
static t_Z80Ctrl *Z80Ctrl = NULL;
static t_Z80Ctrl *Z80Ctrl = NULL;
static uint8_t *Z80RAM = NULL;
static uint8_t *Z80ROM = NULL;
static uint32_t *Z80PAGE[MEMORY_MODES];
static uint8_t memoryPage = 0;
// Method to obtain and return the output screen width.
//
@@ -187,7 +197,7 @@ void delay(int number_of_seconds)
// Function to dump out a given section of memory via the UART.
//
int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryFlag, uint32_t memwidth, uint32_t dispaddr, uint8_t dispwidth)
int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryType, uint32_t memwidth, uint32_t dispaddr, uint8_t dispwidth)
{
uint8_t displayWidth = dispwidth;;
uint32_t pnt = memaddr;
@@ -199,10 +209,17 @@ int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryFlag, uint32_t
int result = -1;
char c = 0;
// Sanity check. memoryFlag == 0 required kernel driver to dump so we exit as it cannot be performed here.
if(memoryFlag == 0)
// Sanity check. memoryType == 0 required kernel driver to dump so we exit as it cannot be performed here.
if(memoryType == 0)
return(-1);
// Make sure the memory page is valid if we are dumping them out.
if(memoryType == 3 && Z80PAGE[memoryPage] == NULL)
{
printf("Page %d is not allocated.\n", memoryPage);
return(-1);
}
// Reconfigure terminal to allow non-blocking key input.
//
set_conio_terminal_mode();
@@ -237,7 +254,10 @@ int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryFlag, uint32_t
{
case 16:
if(pnt+i < endAddr)
printf("%04X", memoryFlag == 1 ? (uint16_t)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (uint16_t)Z80Ctrl->page[pnt+i] : (uint16_t)Z80Ctrl->iopage[pnt+i]);
printf("%04X", memoryType == 1 ? (uint16_t)Z80RAM[pnt+i] :
memoryType == 2 ? (uint16_t)Z80ROM[pnt+i] :
memoryType == 3 ? (uint16_t)*(*(Z80PAGE + memoryPage) + (pnt+i)) :
(uint16_t)Z80Ctrl->iopage[pnt+i]);
else
printf(" ");
i++;
@@ -245,7 +265,10 @@ int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryFlag, uint32_t
case 32:
if(pnt+i < endAddr)
printf("%08lX", memoryFlag == 1 ? (uint32_t)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (uint32_t)Z80Ctrl->page[pnt+i] : (uint32_t)Z80Ctrl->iopage[pnt+i]);
printf("%08lX", memoryType == 1 ? (uint32_t)Z80RAM[pnt+i] :
memoryType == 2 ? (uint32_t)Z80ROM[pnt+i] :
memoryType == 3 ? (uint32_t)*(*(Z80PAGE + memoryPage) + (pnt+i)) :
(uint32_t)Z80Ctrl->iopage[pnt+i]);
else
printf(" ");
i++;
@@ -254,7 +277,10 @@ int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryFlag, uint32_t
case 8:
default:
if(pnt+i < endAddr)
printf("%02X", memoryFlag == 1 ? (uint8_t)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (uint8_t)Z80Ctrl->page[pnt+i] : (uint8_t)Z80Ctrl->iopage[pnt+i]);
printf("%02X", memoryType == 1 ? (uint8_t)Z80RAM[pnt+i] :
memoryType == 2 ? (uint8_t)Z80ROM[pnt+i] :
memoryType == 3 ? (uint8_t)*(*(Z80PAGE + memoryPage) + (pnt+i)) :
(uint8_t)Z80Ctrl->iopage[pnt+i]);
else
printf(" ");
i++;
@@ -269,7 +295,9 @@ int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryFlag, uint32_t
// print single ascii char
for (i=0; i < displayWidth; i++)
{
c = memoryFlag == 1 ? (char)Z80Ctrl->memory[pnt+i] : memoryFlag == 2 ? (char)Z80Ctrl->page[pnt+i] : (char)Z80Ctrl->iopage[pnt+i];
c = memoryType == 1 ? (char)Z80RAM[pnt+i] : memoryType == 2 ? (char)Z80ROM[pnt+i] :
memoryType == 3 ? (char)*(*(Z80PAGE + (uint32_t)memoryPage) + (pnt+i)) :
(char)Z80Ctrl->iopage[pnt+i];
if ((pnt+i < endAddr) && (c >= ' ') && (c <= '~'))
fputc((char)c, stdout);
else
@@ -315,67 +343,187 @@ memoryDumpExit:
// Method to load a program or data file into the Z80 memory. First load into Virtual memory and then trigger a sync to bring Host RAM in line.
//
int z80load(int fdZ80, char *fileName)
int z80load(int fdZ80, char *fileName, uint32_t memLoadAddr, long fileOffset, long fileLen, uint8_t memoryType, uint8_t isMZF)
{
// Locals.
struct ioctlCmd ioctlCmd;
int ret = 0;
int result = 0;
long fileSize;
t_svcDirEnt mzfHeader;
FILE *ptr;
// Sanity check.
if(isMZF == 0 && (fileOffset == -1 && fileLen != -1 || fileOffset != -1 && fileLen == -1))
{
printf("Error: Both --offset and --len are required, dont specify to use entire file.\n");
result = 1;
}
if(result == 0)
{
// Open the file and read directly into the Virtual memory via the share.
ptr = fopen(fileName, "rb");
if(ptr)
{
// Get size of file for sanity checks.
fseek(ptr, 0, SEEK_END);
fileSize = ftell(ptr);
fseek(ptr, 0, SEEK_SET);
// Sanity checks.
if(isMZF == 0)
{
fileSize = (fileLen == -1 ? fileSize : fileLen);
if((memoryType == 1 && (memLoadAddr+fileSize) > Z80_VIRTUAL_RAM_SIZE) || (memoryType == 2 && (memLoadAddr+fileSize) > Z80_VIRTUAL_ROM_SIZE))
{
printf("Error: Binary file out of memory bounds (Size=%ld, Load=%08x)\n", fileSize, memLoadAddr);
result = 1;
}
} else
{
// First the header.
fread((uint8_t *)&mzfHeader, MZF_HEADER_SIZE, 1, ptr);
if((mzfHeader.loadAddr + mzfHeader.fileSize) > Z80_VIRTUAL_RAM_SIZE)
{
printf("Error: MZF file out of RAM bounds (Size=%ld, Load=%08x)\n", fileSize, memLoadAddr);
result = 1;
}
}
}
else
{
printf("Couldnt open file:%s\n", fileName);
result = 1;
}
}
// No file errors, read contents into Z80 memory.
if(result == 0)
{
// Pause the Z80.
//
ioctlCmd.cmd = IOCTL_CMD_Z80_PAUSE;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
if(isMZF == 0)
{
// Position file if offset provided.
if(fileOffset != -1) fseek(ptr, fileOffset, SEEK_SET);
// Now read in the data.
switch(memoryType)
{
case 0:
break;
case 2:
fread(&Z80ROM[memLoadAddr], fileSize, 1, ptr);
break;
case 3:
fread(&Z80Ctrl->page[memLoadAddr], fileSize, 1, ptr);
break;
case 4:
fread(&Z80Ctrl->iopage[memLoadAddr], fileSize, 1, ptr);
break;
case 1:
default:
fread(&Z80RAM[memLoadAddr], fileSize, 1, ptr);
break;
}
printf("Loaded %s, Size:%08x, Addr:%08x, memoryType:%d\n", fileName, fileSize, memLoadAddr, memoryType);
}
else
{
#if(TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ80A)
if(mzfHeader.loadAddr > 0x1000)
{
#endif
// Copy in the header.
memcpy((uint8_t *)&Z80RAM[MZ_CMT_ADDR], (uint8_t *)&mzfHeader, MZF_HEADER_SIZE);
// Now read in the data.
fread(&Z80RAM[mzfHeader.loadAddr], mzfHeader.fileSize, 1, ptr);
printf("Loaded %s, Size:%04x, Addr:%04x, Exec:%04x\n", fileName, mzfHeader.fileSize, mzfHeader.loadAddr, mzfHeader.execAddr);
#if(TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ80A)
}
#endif
// Sync the loaded image from Virtual memory to hard memory.
ioctlCmd.cmd = IOCTL_CMD_SYNC_TO_HOST_RAM;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#if(TARGET_HOST_MZ2000 == 1)
// Set PC to 2 (NST) which switches to RUN mode and executes at 0000H
ioctlCmd.z80.pc = 2;
#endif
#if(TARGET_HOST_MZ700 == 1 || TARGET_HOST_MZ80A)
// MZ-700 or MZ-80A just use the MZF header exec address.
ioctlCmd.z80.pc = mzfHeader.execAddr;
#endif
// Set PC to required setting ready for run.
ioctlCmd.cmd = IOCTL_CMD_SETPC;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
// Resume Z80 processing.
//
ioctlCmd.cmd = IOCTL_CMD_Z80_CONTINUE;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
}
}
return(result);
}
// Method to save FusionX memory to a local file.
//
int z80save(int fdZ80, char *fileName, long addr, long size, uint8_t memoryType)
{
// Locals.
struct ioctlCmd ioctlCmd;
int result = 0;
t_svcDirEnt mzfHeader;
// Pause the Z80.
//
ioctlCmd.cmd = IOCTL_CMD_Z80_PAUSE;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
// Open the file and read directly into the Virtual memory via the share.
//ioctlCmd.cmd = IOCTL_CMD_Z80_PAUSE;
//ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
// Open the file and write directly into the file from the shared memory segment.
FILE *ptr;
ptr = fopen(fileName, "rb");
ptr = fopen(fileName, "wb");
if(ptr)
{
// First the header.
fread((uint8_t *)&mzfHeader, MZF_HEADER_SIZE, 1, ptr);
#if(TARGET_HOST_MZ700 == 1)
if(mzfHeader.loadAddr > 0x1000)
switch(memoryType)
{
#endif
// Copy in the header.
memcpy((uint8_t *)&Z80Ctrl->memory[MZ_CMT_ADDR], (uint8_t *)&mzfHeader, MZF_HEADER_SIZE);
case 0:
break;
// Now read in the data.
fread(&Z80Ctrl->memory[mzfHeader.loadAddr], mzfHeader.fileSize, 1, ptr);
printf("Loaded %s, Size:%04x, Addr:%04x, Exec:%04x\n", fileName, mzfHeader.fileSize, mzfHeader.loadAddr, mzfHeader.execAddr);
#if(TARGET_HOST_MZ700 == 1)
case 2:
fwrite(&Z80ROM[addr], size, 1, ptr);
break;
case 3:
fwrite(&Z80Ctrl->page[addr], size, 1, ptr);
break;
case 4:
fwrite(&Z80Ctrl->iopage[addr], size, 1, ptr);
break;
case 1:
default:
fwrite(&Z80RAM[addr], size, 1, ptr);
break;
}
#endif
}
fclose(ptr);
// Sync the loaded image from Virtual memory to hard memory.
ioctlCmd.cmd = IOCTL_CMD_SYNC_TO_HOST_RAM;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
#if(TARGET_HOST_MZ2000 == 1)
// Set PC to 2 (NST) which switches to RUN mode and executes at 0000H
ioctlCmd.z80.pc = 2;
#endif
#if(TARGET_HOST_MZ700 == 1)
// MZ-700 just use the MZF header exec address.
ioctlCmd.z80.pc = mzfHeader.execAddr;
#endif
// Set PC to required setting ready for run.
ioctlCmd.cmd = IOCTL_CMD_SETPC;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
// Resume Z80 processing.
//
ioctlCmd.cmd = IOCTL_CMD_Z80_CONTINUE;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
}
else
printf("Couldnt open file\n");
return ret;
}
return(result);
}
// Method to request basic Z80 operations.
//
@@ -384,7 +532,7 @@ int ctrlCmd(int fdZ80, enum CTRL_COMMANDS cmd, long param1, long param2, long pa
// Locals.
struct ioctlCmd ioctlCmd;
uint32_t idx;
int ret = 0;
int result = 0;
switch(cmd)
{
@@ -422,7 +570,7 @@ int ctrlCmd(int fdZ80, enum CTRL_COMMANDS cmd, long param1, long param2, long pa
if(idx == 256)
{
printf("Speed factor is illegal. It must be a multiple value of the original CPU clock, ie. 1x, 2x, 4x etc\n");
ret = -1;
result = -1;
} else
{
// Use IOCTL to request Z80 cpu freq change.
@@ -431,6 +579,79 @@ int ctrlCmd(int fdZ80, enum CTRL_COMMANDS cmd, long param1, long param2, long pa
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
}
break;
case Z80_CMD_ADD_DEVICE:
ioctlCmd.vdev.device = VIRTUAL_DEVICE_NONE;
if(strcasecmp((char *)param1, "RFS") == 0 || strcasecmp((char *)param1, "RFS80") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS80;
}
if(strcasecmp((char *)param1, "RFS40") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS40;
}
else if(strcasecmp((char *)param1, "TZPU") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_TZPU;
}
else if(strcasecmp((char *)param1, "MZ80A") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ80A;
}
else if(strcasecmp((char *)param1, "MZ700") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
}
else if(strcasecmp((char *)param1, "MZ2000") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
}
else if(strcasecmp((char *)param1, "PCW") == 0)
{
printf("Add device:%s\n", (char *)param1);
ioctlCmd.vdev.device = VIRTUAL_DEVICE_PCW;
}
if(ioctlCmd.vdev.device != VIRTUAL_DEVICE_NONE)
{
ioctlCmd.cmd = IOCTL_CMD_ADD_DEVICE;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
}
break;
case Z80_CMD_DEL_DEVICE:
ioctlCmd.vdev.device = VIRTUAL_DEVICE_NONE;
if(strcasecmp((char *)param1, "RFS") == 0 || strcasecmp((char *)param1, "RFS80") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS80;
}
else if(strcasecmp((char *)param1, "RFS40") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_RFS40;
}
else if(strcasecmp((char *)param1, "TZPU") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_TZPU;
}
else if(strcasecmp((char *)param1, "MZ80A") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ80A;
}
else if(strcasecmp((char *)param1, "MZ700") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ700;
}
else if(strcasecmp((char *)param1, "MZ2000") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_MZ2000;
}
else if(strcasecmp((char *)param1, "PCW") == 0)
{
ioctlCmd.vdev.device = VIRTUAL_DEVICE_PCW;
}
if(ioctlCmd.vdev.device != VIRTUAL_DEVICE_NONE)
{
ioctlCmd.cmd = IOCTL_CMD_DEL_DEVICE;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
}
break;
case CPLD_CMD_SEND_CMD:
// Build up the IOCTL command to request the given data is sent to the CPLD.
ioctlCmd.cmd = IOCTL_CMD_CPLD_CMD;
@@ -441,7 +662,7 @@ int ctrlCmd(int fdZ80, enum CTRL_COMMANDS cmd, long param1, long param2, long pa
// If virtual memory, we can dump it via the shared memory segment.
if((uint8_t)param1)
{
memoryDump((uint32_t)param2, (uint32_t)param3, (uint8_t)param1, (uint8_t)param1 == 2 || (uint8_t)param1 == 3 ? 32 : 8, (uint32_t)param2, 0);
memoryDump((uint32_t)param2, (uint32_t)param3, (uint8_t)param1, (uint8_t)param1 == 3 || (uint8_t)param1 == 4 ? 32 : 8, (uint32_t)param2, 0);
} else
{
// Build an IOCTL command to get the driver to dump the memory.
@@ -462,6 +683,14 @@ int ctrlCmd(int fdZ80, enum CTRL_COMMANDS cmd, long param1, long param2, long pa
ioctlCmd.cmd = IOCTL_CMD_USE_VIRTUAL_RAM;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
#if(DEBUG_ENABLED != 0)
case Z80_CMD_DEBUG:
// Send command to enable/disable debugging output.
ioctlCmd.cmd = IOCTL_CMD_DEBUG;
ioctlCmd.debug.level = (uint8_t)param1;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
#endif
case Z80_CMD_MEMORY_TEST:
// Send command to test the SPI.
ioctlCmd.cmd = IOCTL_CMD_Z80_MEMTEST;
@@ -480,11 +709,11 @@ int ctrlCmd(int fdZ80, enum CTRL_COMMANDS cmd, long param1, long param2, long pa
default:
printf("Command not supported!\n");
ret = -1;
result = -1;
break;
}
return ret;
return(result);
}
// Method to perform some simple tests on the Z80 emulator.
@@ -493,7 +722,7 @@ int z80test(int fdZ80)
{
// Locals.
struct ioctlCmd ioctlCmd;
int ret = 0;
int result = 0;
// Stop the Z80.
//
@@ -505,7 +734,7 @@ printf("Send STOP\n");
ptr = fopen("/customer/mz700.rom", "rb");
if(ptr)
{
fread(&Z80Ctrl->memory, 65536, 1, ptr);
fread(&Z80RAM, 65536, 1, ptr);
} else printf("Couldnt open file\n");
// Configure the Z80.
@@ -530,7 +759,7 @@ printf("Send STOP\n");
memoryDump(0, 65536, 1, 8, 0, 0);
out:
return ret;
return(result);
}
// Output usage screen. So mamy commands you do need to be prompted!!
@@ -538,23 +767,31 @@ void showArgs(char *progName, struct optparse *options)
{
printf("%s %s %s %s\n\n", progName, VERSION, COPYRIGHT, AUTHOR);
printf("Synopsis:\n");
printf("%s --help # This help screen.\n", progName);
printf(" --cmd <command> = RESET # Reset the Z80\n");
printf(" = STOP # Stop and power off the Z80\n");
printf(" = START # Power on and start the Z80\n");
printf(" = PAUSE # Pause running Z80\n");
printf(" = CONTINUE # Continue Z80 execution\n");
printf(" = HOSTRAM # Use HOST DRAM\n");
printf(" = VIRTRAM # Use Virtual RAM\n");
printf(" = SPEED --speed <1, 2, 4, 8, 16, 32, 64, 128> # In Virtual RAM mode, set CPU speed to base clock x factor.\n");
printf(" = LOADMZF --file <mzf filename> # Load MZF file into memory.\n");
printf(" = DUMP --addr <24bit addr> --end <24bit addr> [--size <24bit>]--virtual <0 - Host RAM, 1 = Virtual RAM, 2 = PageTable, 3 = IOPageTable>\n");
printf(" = CPLDCMD --data <32bit command> # Send adhoc 32bit command to CPLD.\n");
printf(" = Z80TEST # Perform various debugging tests\n");
printf(" = SPITEST # Perform SPI testing\n");
printf(" = PRLTEST # Perform Parallel Bus testing\n");
printf(" = Z80MEMTEST # Perform HOST memory tests.\n");
printf(" --<cmd> # Some commands can be abbreviated.\n");
printf("%s --help # This help screen.\n", progName);
printf(" --cmd <command> = RESET # Reset the Z80\n");
printf(" = STOP # Stop and power off the Z80\n");
printf(" = START # Power on and start the Z80\n");
printf(" = PAUSE # Pause running Z80\n");
printf(" = CONTINUE # Continue Z80 execution\n");
printf(" = HOSTRAM # Use HOST DRAM\n");
printf(" = VIRTRAM # Use Virtual RAM\n");
printf(" = ADDDEV --device <RFS40, RFS80, TZPU> # Add a virtual device into the Z80 configuration.\n");
printf(" = DELDEV --device <RFS40, RFS80, TZPU> # Remove a virtual device from the Z80 configuration.\n");
printf(" = SPEED --mult <1, 2, 4, 8, 16, 32, 64, 128> # In Virtual RAM mode, set CPU speed to base clock x factor.\n");
printf(" = LOADMZF --file <mzf filename> # Load MZF file into RAM.\n");
printf(" # Load contents of binary file into memory at address. default = 0x000000.\n");
printf(" = LOADMEM --file <binary filename> --addr <24 bit addr> --type <0 - Host RAM, 1 = Virtual RAM, 2 = Virtual ROM> [--offset <offset> --len <length>]\n");
printf(" = SAVE --file <filename> --addr <24bit addr> --end <24bit addr> [--size <24bit>] --type <0 - Host RAM, 1 = Virtual RAM, 2 = Virtual ROM, 3 = PageTable, 4 = IOPageTable>\n");
printf(" = DUMP --addr <24bit addr> --end <24bit addr> [--size <24bit>] --type <0 - Host RAM, 1 = Virtual RAM, 2 = Virtual ROM, 3 = MemoryPageTable, 4 = IOPageTable> [--memorypage <0..41>]\n");
printf(" = CPLDCMD --data <32bit command> # Send adhoc 32bit command to CPLD.\n");
#if(DEBUG_ENABLED != 0)
printf(" = DEBUG --level <level> # 0 = off, 1..15 debug level, 15 is very verbose.\n");
#endif
printf(" = Z80TEST # Perform various debugging tests\n");
printf(" = SPITEST # Perform SPI testing\n");
printf(" = PRLTEST # Perform Parallel Bus testing\n");
printf(" = Z80MEMTEST # Perform HOST memory tests.\n");
printf(" --<cmd> # Some commands can be abbreviated, ie. --start.\n");
}
@@ -564,14 +801,21 @@ int main(int argc, char *argv[])
char buff[64];
char cmd[64] = { 0 };
char fileName[256] = { 0 };
char devName[32] = { 0 };
int idx;
int opt;
uint32_t hexData = 0;
long speedMultiplier = 1;
long startAddr = 0x0000;
long endAddr = 0x1000;
int virtualMemory = 0;
long fileOffset = -1;
long fileLen = -1;
#if(DEBUG_ENABLED != 0)
int debugLevel = 0;
#endif
int helpFlag = 0;
int verboseFlag = 0;
uint8_t memoryType = 0;
// Define parameters to be processed.
struct optparse options;
@@ -581,21 +825,33 @@ int main(int argc, char *argv[])
{"cmd", 'c', OPTPARSE_REQUIRED},
{"file", 'f', OPTPARSE_REQUIRED},
{"data", 'd', OPTPARSE_REQUIRED},
{"speed", 'S', OPTPARSE_REQUIRED},
{"virtual", 'V', OPTPARSE_REQUIRED},
{"mult", 'S', OPTPARSE_REQUIRED},
{"type", 'T', OPTPARSE_REQUIRED},
{"addr", 'a', OPTPARSE_REQUIRED},
{"end", 'e', OPTPARSE_REQUIRED},
{"size", 's', OPTPARSE_REQUIRED},
{"device", 'D', OPTPARSE_REQUIRED},
{"offset", 'O', OPTPARSE_REQUIRED},
{"len", 'L', OPTPARSE_REQUIRED},
{"memorypage", 'm', OPTPARSE_REQUIRED},
#if(DEBUG_ENABLED != 0)
{"level", 'l', OPTPARSE_REQUIRED},
#endif
{"verbose", 'v', OPTPARSE_NONE},
{"save", '0', OPTPARSE_NONE},
{"dump", '1', OPTPARSE_NONE},
{"loadmzf", '2', OPTPARSE_NONE},
{"reset", '3', OPTPARSE_NONE},
{"stop", '4', OPTPARSE_NONE},
{"start", '5', OPTPARSE_NONE},
{"pause", '6', OPTPARSE_NONE},
{"continue", '7', OPTPARSE_NONE},
{"speed", '8', OPTPARSE_NONE},
{"cpldcmd", '9', OPTPARSE_NONE},
{"loadrom", '3', OPTPARSE_NONE},
{"reset", '4', OPTPARSE_NONE},
{"stop", '5', OPTPARSE_NONE},
{"start", '6', OPTPARSE_NONE},
{"pause", '7', OPTPARSE_NONE},
{"continue", '8', OPTPARSE_NONE},
{"speed", '9', OPTPARSE_NONE},
{"cpldcmd", '+', OPTPARSE_NONE},
{"debug", 'x', OPTPARSE_NONE},
{"adddev", '-', OPTPARSE_NONE},
{"deldev", ':', OPTPARSE_NONE},
{0}
};
@@ -636,23 +892,56 @@ int main(int argc, char *argv[])
endAddr = startAddr + strtol(options.optarg, NULL, 0);
//printf("End Addr:%04x\n", endAddr);
break;
// Virtual memory flag, 0 = host, 1 = virtual memory, 2 = page table, 3 = iopage table.
case 'V':
virtualMemory = atoi(options.optarg);
// File offset.
case 'O':
fileOffset = strtol(options.optarg, NULL, 0);
//printf("File Offset:%04x\n", fileOffset);
break;
// Length.
case 'L':
fileLen = strtol(options.optarg, NULL, 0);
//printf("File Len:%04x\n", fileLen);
break;
// Memory type flag, 0 = host, 1 = virtual RAM, 2 = virtual ROM, 3 = page table, 4 = iopage table.
case 'T':
memoryType = atoi(options.optarg);
break;
// Memory Page - which page, in the page table, to view.
case 'm':
memoryPage = atoi(options.optarg);
//printf("Memory Page:%02x\n", memoryPage);
break;
#if(DEBUG_ENABLED != 0)
// Debug level, 0 = off, 1..15 debug level, 15 is very verbose.
case 'l':
debugLevel = atoi(options.optarg);
break;
#endif
// Filename.
case 'f':
strcpy(fileName, options.optarg);
break;
// Device name.
case 'D':
strcpy(devName, options.optarg);
break;
// Command to execute.
case 'c':
strcpy(cmd, options.optarg);
break;
// Quick command flags.
case '0':
strcpy(cmd, "SAVE");
break;
case '1':
strcpy(cmd, "DUMP");
break;
@@ -660,26 +949,40 @@ int main(int argc, char *argv[])
strcpy(cmd, "LOADMZF");
break;
case '3':
strcpy(cmd, "RESET");
strcpy(cmd, "LOADMEM");
break;
case '4':
strcpy(cmd, "STOP");
strcpy(cmd, "RESET");
break;
case '5':
strcpy(cmd, "START");
strcpy(cmd, "STOP");
break;
case '6':
strcpy(cmd, "PAUSE");
strcpy(cmd, "START");
break;
case '7':
strcpy(cmd, "CONTINUE");
strcpy(cmd, "PAUSE");
break;
case '8':
strcpy(cmd, "SPEED");
strcpy(cmd, "CONTINUE");
break;
case '9':
strcpy(cmd, "SPEED");
break;
case '+':
strcpy(cmd, "CPLDCMD");
break;
case '-':
strcpy(cmd, "ADDDEV");
break;
case ':':
strcpy(cmd, "DELDEV");
break;
#if(DEBUG_ENABLED != 0)
case 'x':
strcpy(cmd, "DEBUG");
break;
#endif
// Verbose mode.
case 'v':
@@ -689,7 +992,6 @@ int main(int argc, char *argv[])
// Command help needed.
case 'h':
helpFlag = 1;
showArgs(argv[0], &options);
break;
// Unrecognised, show synopsis.
@@ -705,22 +1007,48 @@ int main(int argc, char *argv[])
if(fdZ80 >= 0)
{
Z80Ctrl = (t_Z80Ctrl *)mmap(0, sizeof(t_Z80Ctrl), PROT_READ | PROT_WRITE, MAP_SHARED, fdZ80, 0);
if(Z80Ctrl == (void *)-1)
{
printf("Failed to attach to the Z80 Control structure, cannot continue, exitting....\n");
printf("Failed to attach to the Z80 Control structure, cannot continue, exiting....\n");
close(fdZ80);
exit(1);
}
Z80RAM = (uint8_t *)mmap(0, Z80_VIRTUAL_RAM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fdZ80, 0);
if(Z80RAM == (void *)-1)
{
printf("Failed to attach to the Z80 RAM, cannot continue, exiting....\n");
close(fdZ80);
exit(1);
}
Z80ROM = (uint8_t *)mmap(0, Z80_VIRTUAL_ROM_SIZE+0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fdZ80, 0);
if(Z80ROM == (void *)-1)
{
printf("Failed to attach to the Z80 ROM, cannot continue, exitting....\n");
close(fdZ80);
exit(1);
}
// Loop through all the memory mapping pages, each page specifies a 64K mapping block, all memory accesses go through this map.
for(idx=0; idx < MEMORY_MODES; idx++)
{
// Try and bind the page, if it doesnt exist, then the pointer will be NULL so it wont be used.
Z80PAGE[idx] = (uint32_t *)mmap(0, ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + (0x1000*(idx+1))), PROT_READ | PROT_WRITE, MAP_SHARED, fdZ80, 0);
if(Z80PAGE[idx] == (void *)-1) Z80PAGE[idx] = NULL;
}
} else
{
printf("Failed to open the Z80 Driver, exitting...\n");
printf("Failed to open the Z80 Driver, exiting...\n");
exit(1);
}
// Basic string to method mapping. Started off with just 1 or two but has grown, may need a table!
if(strcasecmp(cmd, "LOADMZF") == 0)
{
z80load(fdZ80, fileName);
z80load(fdZ80, fileName, 0, -1, -1, 1, 1);
} else
if(strcasecmp(cmd, "LOADMEM") == 0)
{
z80load(fdZ80, fileName, startAddr, fileOffset, fileLen, memoryType, 0);
} else
if(strcasecmp(cmd, "RESET") == 0)
{
@@ -748,7 +1076,11 @@ int main(int argc, char *argv[])
} else
if(strcasecmp(cmd, "DUMP") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_DUMP_MEMORY, virtualMemory, startAddr, (endAddr - startAddr));
ctrlCmd(fdZ80, Z80_CMD_DUMP_MEMORY, memoryType, startAddr, (endAddr - startAddr));
} else
if(strcasecmp(cmd, "SAVE") == 0)
{
z80save(fdZ80, fileName, startAddr, (endAddr - startAddr), memoryType);
} else
if(strcasecmp(cmd, "HOSTRAM") == 0)
{
@@ -758,10 +1090,24 @@ int main(int argc, char *argv[])
{
ctrlCmd(fdZ80, Z80_CMD_VIRTUAL_RAM, 0, 0, 0);
} else
if(strcasecmp(cmd, "ADDDEV") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_ADD_DEVICE, (long)&devName, 0, 0);
} else
if(strcasecmp(cmd, "DELDEV") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_DEL_DEVICE, (long)&devName, 0, 0);
} else
if(strcasecmp(cmd, "CPLDCMD") == 0)
{
ctrlCmd(fdZ80, CPLD_CMD_SEND_CMD, hexData, 0, 0);
} else
#if(DEBUG_ENABLED != 0)
if(strcasecmp(cmd, "DEBUG") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_DEBUG, (long)debugLevel, 0, 0);
} else
#endif
// Test methods, if the code is built-in to the driver.
if(strcasecmp(cmd, "Z80TEST") == 0)
@@ -783,7 +1129,8 @@ int main(int argc, char *argv[])
else
{
showArgs(argv[0], &options);
printf("No command given, nothing done!\n");
if(helpFlag == 0)
printf("No command given, nothing done!\n");
}
// Unmap shared memory and close the device.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,750 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: z80driver.h
// Created: Oct 2022
// Author(s): Philip Smart
// Description: Z80 Driver
// This file contains the declarations used in the z80drv device driver.
//
// Credits: Zilog Z80 CPU Emulator v0.2 written by Manuel Sainz de Baranda y Goñi
// The Z80 CPU Emulator is the heart of this driver and in all ways, is compatible with
// the original Z80.
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
// (c) 1999-2023 Manuel Sainz de Baranda y Goñi
//
// History: Oct 2022 - v1.0 Initial write of the z80 kernel driver software.
// Jan 2023 - v1.1 Added MZ-2000/MZ-80A modes.
// Feb 2023 - v1.2 Added RFS virtual driver.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef Z80DRIVER_H
#define Z80DRIVER_H
// Build time target. Overrides if compile time definition given.
#if defined(TARGET_HOST_MZ700)
#define TARGET_HOST_MZ700 1
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_MZ80A 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_MZ2000)
#define TARGET_HOST_MZ2000 1
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ80A 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_MZ80A)
#define TARGET_HOST_MZ80A 1
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_PCW 0
#elif defined(TARGET_HOST_PCW8XXX) || defined(TARGET_HOST_PCW9XXX)
#define TARGET_HOST_PCW 1
#define TARGET_HOST_MZ2000 0
#define TARGET_HOST_MZ700 0
#define TARGET_HOST_MZ80A 0
#else
#define TARGET_HOST_MZ700 0 // Target compilation for an MZ700
#define TARGET_HOST_MZ2000 0 // MZ2000
#define TARGET_HOST_MZ80A 0 // MZ80A
#define TARGET_HOST_PCW 0 // Amstrad PCW8XXX/9XXX
#endif
// Constants.
#define DRIVER_LICENSE "GPL"
#define DRIVER_AUTHOR "Philip D Smart"
#define DRIVER_DESCRIPTION "Z80 CPU Emulator and Hardware Interface Driver"
#define DRIVER_VERSION "v1.4"
#define DRIVER_VERSION_DATE "Apr 2023"
#define DRIVER_COPYRIGHT "(C) 2018-2023"
#define Z80_VIRTUAL_ROM_SIZE (65536 * 32) // Sized to maximum Kernel contiguous allocation size, 2M which is 4x512K ROMS.
#define Z80_VIRTUAL_RAM_SIZE (65536 * 32) // Sized to maximum Kernel contiguous allocation size, 2M.
#define Z80_MEMORY_PAGE_SIZE 16
#define MAX_SCREEN_WIDTH 132 // Maximum terminal screen width for memory dump output.
#define MAX_VIRTUAL_DEVICES 5 // Maximum number of allowed virtual devices.
#define DEVICE_NAME "z80drv"
#define CLASS_NAME "mogu"
#define IO_PROCESSOR_NAME "k64fcpu" // Name of the I/O processor user space application.
#define ARBITER_NAME "sharpbiter" // Name of the Sharp MZ Arbiter process user space application.
#define DEBUG_ENABLED 0 // 0 = disabled, 1 = z80driver, 2 = k64fcpu, 3 = both.
// Memory and IO page types. Used to create a memory page which maps type of address space to real address space on host or virtual memory.
#define MEMORY_TYPE_VIRTUAL_MASK 0x00FFFFFF
#define MEMORY_TYPE_REAL_MASK 0x0000FFFF
#define IO_TYPE_MASK 0x0000FFFF
#define MEMORY_TYPE_INHIBIT 0x00000000
#define MEMORY_TYPE_PHYSICAL_RAM 0x80000000
#define MEMORY_TYPE_PHYSICAL_ROM 0x40000000
#define MEMORY_TYPE_PHYSICAL_VRAM 0x20000000
#define MEMORY_TYPE_PHYSICAL_HW 0x10000000
#define MEMORY_TYPE_VIRTUAL_RAM 0x08000000
#define MEMORY_TYPE_VIRTUAL_ROM 0x04000000
#define MEMORY_TYPE_VIRTUAL_RAM_RO 0x02000000
#define MEMORY_TYPE_VIRTUAL_HW 0x01000000
#define MEMORY_TYPE_PHYSICAL_RAM_WT MEMORY_TYPE_PHYSICAL_RAM | MEMORY_TYPE_VIRTUAL_RAM
#define IO_TYPE_PHYSICAL_HW 0x80000000
#define IO_TYPE_VIRTUAL_HW 0x40000000
// Hotkeys handled.
#define HOTKEY_ORIGINAL 0xE8
#define HOTKEY_RFS40 0xE9
#define HOTKEY_RFS80 0xEA
#define HOTKEY_TZFS 0xEB
#define HOTKEY_LINUX 0xEC
//*********************************************************************************************
// Delay periods for the various hosts, which need adding to the primary opcode fetch in
// order to govern the virtual Z80 to a known speed. The timings are only used within
// virtual memory, if an opcode is being fetched from physical memory will self govern to the
// host speed.
// NB. As of v1.0 FusionX hardware, unless a method is forthcoming due to the low speed of the
// SSD202 CPU GPIO access (72MHz bus speed, 1x72MHz per bit, in theory 2.2M 32bit words per
// second, in practice 2MBytes per second! This is a shortcoming of the SSD202 CPU, others,
// such as the NXP K64FX512 Cortex-M4 has 32bit registers where a single access can write
// /read/toggle/clear 32bits and the bus is operating at 85MHz! If SigmaStar release an updated
// CPU, or another compatible system becomes available, v1.1 of the FusionX hardware will be
// created in order to allow full speed program execution within host memory.
// NBB: Actual Z80 transactions run at full speed, it is just the period from completion
// of 1 cycle to the next taking too much time in the SSD202 to setup. Workarounds using
// lookahead and queue techniques have been adopted to ensure I/O timing for things such as
// floppy drives functions as per the original host.
//*********************************************************************************************
// Approximate governor delays to regulate emulated CPU speed.
// MZ-700
#if(TARGET_HOST_MZ700 == 1)
#if(DEBUG_ENABLED > 0)
#define INSTRUCTION_DELAY_ROM_3_54MHZ 253
#define INSTRUCTION_DELAY_ROM_7MHZ 126
#define INSTRUCTION_DELAY_ROM_14MHZ 63
#define INSTRUCTION_DELAY_ROM_28MHZ 32
#define INSTRUCTION_DELAY_ROM_56MHZ 16
#define INSTRUCTION_DELAY_ROM_112MHZ 8
#define INSTRUCTION_DELAY_ROM_224MHZ 4
#define INSTRUCTION_DELAY_ROM_448MHZ 1
#define INSTRUCTION_DELAY_RAM_3_54MHZ 253
#define INSTRUCTION_DELAY_RAM_7MHZ 126
#define INSTRUCTION_DELAY_RAM_14MHZ 63
#define INSTRUCTION_DELAY_RAM_28MHZ 32
#define INSTRUCTION_DELAY_RAM_56MHZ 16
#define INSTRUCTION_DELAY_RAM_112MHZ 8
#define INSTRUCTION_DELAY_RAM_224MHZ 4
#define INSTRUCTION_DELAY_RAM_448MHZ 1
#endif
#if(DEBUG_ENABLED == 0)
#define INSTRUCTION_DELAY_ROM_3_54MHZ 253
#define INSTRUCTION_DELAY_ROM_7MHZ 126
#define INSTRUCTION_DELAY_ROM_14MHZ 63
#define INSTRUCTION_DELAY_ROM_28MHZ 32
#define INSTRUCTION_DELAY_ROM_56MHZ 16
#define INSTRUCTION_DELAY_ROM_112MHZ 8
#define INSTRUCTION_DELAY_ROM_224MHZ 4
#define INSTRUCTION_DELAY_ROM_448MHZ 1
#define INSTRUCTION_DELAY_RAM_3_54MHZ 253
#define INSTRUCTION_DELAY_RAM_7MHZ 126
#define INSTRUCTION_DELAY_RAM_14MHZ 63
#define INSTRUCTION_DELAY_RAM_28MHZ 32
#define INSTRUCTION_DELAY_RAM_56MHZ 16
#define INSTRUCTION_DELAY_RAM_112MHZ 8
#define INSTRUCTION_DELAY_RAM_224MHZ 4
#define INSTRUCTION_DELAY_RAM_448MHZ 1
#endif
#define INSTRUCTION_EQUIV_FREQ_3_54MHZ 3540000
#define INSTRUCTION_EQUIV_FREQ_7MHZ 7000000
#define INSTRUCTION_EQUIV_FREQ_14MHZ 14000000
#define INSTRUCTION_EQUIV_FREQ_28MHZ 28000000
#define INSTRUCTION_EQUIV_FREQ_56MHZ 56000000
#define INSTRUCTION_EQUIV_FREQ_112MHZ 112000000
#define INSTRUCTION_EQUIV_FREQ_224MHZ 224000000
#define INSTRUCTION_EQUIV_FREQ_448MHZ 448000000
#define INSTRUCTION_GOVERNOR_IO_SKIP 10
enum Z80_INSTRUCTION_DELAY {
ROM_DELAY_NORMAL = INSTRUCTION_DELAY_ROM_3_54MHZ,
ROM_DELAY_X2 = INSTRUCTION_DELAY_ROM_7MHZ,
ROM_DELAY_X4 = INSTRUCTION_DELAY_ROM_14MHZ,
ROM_DELAY_X8 = INSTRUCTION_DELAY_ROM_28MHZ,
ROM_DELAY_X16 = INSTRUCTION_DELAY_ROM_56MHZ,
ROM_DELAY_X32 = INSTRUCTION_DELAY_ROM_112MHZ,
ROM_DELAY_X64 = INSTRUCTION_DELAY_ROM_224MHZ,
ROM_DELAY_X128 = INSTRUCTION_DELAY_ROM_448MHZ,
RAM_DELAY_NORMAL = INSTRUCTION_DELAY_RAM_3_54MHZ,
RAM_DELAY_X2 = INSTRUCTION_DELAY_RAM_7MHZ,
RAM_DELAY_X4 = INSTRUCTION_DELAY_RAM_14MHZ,
RAM_DELAY_X8 = INSTRUCTION_DELAY_RAM_28MHZ,
RAM_DELAY_X16 = INSTRUCTION_DELAY_RAM_56MHZ,
RAM_DELAY_X32 = INSTRUCTION_DELAY_RAM_112MHZ,
RAM_DELAY_X64 = INSTRUCTION_DELAY_RAM_224MHZ,
RAM_DELAY_X128 = INSTRUCTION_DELAY_RAM_448MHZ,
CPU_FREQUENCY_NORMAL = INSTRUCTION_EQUIV_FREQ_3_54MHZ,
CPU_FREQUENCY_X2 = INSTRUCTION_EQUIV_FREQ_7MHZ,
CPU_FREQUENCY_X4 = INSTRUCTION_EQUIV_FREQ_14MHZ,
CPU_FREQUENCY_X8 = INSTRUCTION_EQUIV_FREQ_28MHZ,
CPU_FREQUENCY_X16 = INSTRUCTION_EQUIV_FREQ_56MHZ,
CPU_FREQUENCY_X32 = INSTRUCTION_EQUIV_FREQ_112MHZ,
CPU_FREQUENCY_X64 = INSTRUCTION_EQUIV_FREQ_224MHZ,
CPU_FREQUENCY_X128 = INSTRUCTION_EQUIV_FREQ_448MHZ,
};
#endif
// MZ-2000
#if(TARGET_HOST_MZ2000 == 1)
#if(DEBUG_ENABLED > 0)
#define INSTRUCTION_DELAY_ROM_4MHZ 213
#define INSTRUCTION_DELAY_ROM_8MHZ 109
#define INSTRUCTION_DELAY_ROM_16MHZ 54
#define INSTRUCTION_DELAY_ROM_32MHZ 27
#define INSTRUCTION_DELAY_ROM_64MHZ 14
#define INSTRUCTION_DELAY_ROM_128MHZ 7
#define INSTRUCTION_DELAY_ROM_256MHZ 3
#define INSTRUCTION_DELAY_ROM_512MHZ 1
#define INSTRUCTION_DELAY_RAM_4MHZ 212
#define INSTRUCTION_DELAY_RAM_8MHZ 106
#define INSTRUCTION_DELAY_RAM_16MHZ 53
#define INSTRUCTION_DELAY_RAM_32MHZ 26
#define INSTRUCTION_DELAY_RAM_64MHZ 13
#define INSTRUCTION_DELAY_RAM_128MHZ 7
#define INSTRUCTION_DELAY_RAM_256MHZ 3
#define INSTRUCTION_DELAY_RAM_512MHZ 1
#endif
#if(DEBUG_ENABLED == 0)
#define INSTRUCTION_DELAY_ROM_4MHZ 295
#define INSTRUCTION_DELAY_ROM_8MHZ 148
#define INSTRUCTION_DELAY_ROM_16MHZ 74
#define INSTRUCTION_DELAY_ROM_32MHZ 37
#define INSTRUCTION_DELAY_ROM_64MHZ 19
#define INSTRUCTION_DELAY_ROM_128MHZ 10
#define INSTRUCTION_DELAY_ROM_256MHZ 5
#define INSTRUCTION_DELAY_ROM_512MHZ 3
#define INSTRUCTION_DELAY_RAM_4MHZ 240 // These values are smaller than the ROM as Rom has 1 wait state added per cycle.
#define INSTRUCTION_DELAY_RAM_8MHZ 148
#define INSTRUCTION_DELAY_RAM_16MHZ 74
#define INSTRUCTION_DELAY_RAM_32MHZ 37
#define INSTRUCTION_DELAY_RAM_64MHZ 19
#define INSTRUCTION_DELAY_RAM_128MHZ 10
#define INSTRUCTION_DELAY_RAM_256MHZ 5
#define INSTRUCTION_DELAY_RAM_512MHZ 3
#endif
#define INSTRUCTION_EQUIV_FREQ_4MHZ 4000000
#define INSTRUCTION_EQUIV_FREQ_8MHZ 8000000
#define INSTRUCTION_EQUIV_FREQ_16MHZ 16000000
#define INSTRUCTION_EQUIV_FREQ_32MHZ 32000000
#define INSTRUCTION_EQUIV_FREQ_64MHZ 64000000
#define INSTRUCTION_EQUIV_FREQ_128MHZ 128000000
#define INSTRUCTION_EQUIV_FREQ_256MHZ 256000000
#define INSTRUCTION_EQUIV_FREQ_512MHZ 512000000
#define INSTRUCTION_GOVERNOR_IO_SKIP 4
enum Z80_INSTRUCTION_DELAY {
ROM_DELAY_NORMAL = INSTRUCTION_DELAY_ROM_4MHZ,
ROM_DELAY_X2 = INSTRUCTION_DELAY_ROM_8MHZ,
ROM_DELAY_X4 = INSTRUCTION_DELAY_ROM_16MHZ,
ROM_DELAY_X8 = INSTRUCTION_DELAY_ROM_32MHZ,
ROM_DELAY_X16 = INSTRUCTION_DELAY_ROM_64MHZ,
ROM_DELAY_X32 = INSTRUCTION_DELAY_ROM_128MHZ,
ROM_DELAY_X64 = INSTRUCTION_DELAY_ROM_256MHZ,
ROM_DELAY_X128 = INSTRUCTION_DELAY_ROM_512MHZ,
RAM_DELAY_NORMAL = INSTRUCTION_DELAY_RAM_4MHZ,
RAM_DELAY_X2 = INSTRUCTION_DELAY_RAM_8MHZ,
RAM_DELAY_X4 = INSTRUCTION_DELAY_RAM_16MHZ,
RAM_DELAY_X8 = INSTRUCTION_DELAY_RAM_32MHZ,
RAM_DELAY_X16 = INSTRUCTION_DELAY_RAM_64MHZ,
RAM_DELAY_X32 = INSTRUCTION_DELAY_RAM_128MHZ,
RAM_DELAY_X64 = INSTRUCTION_DELAY_RAM_256MHZ,
RAM_DELAY_X128 = INSTRUCTION_DELAY_RAM_512MHZ,
CPU_FREQUENCY_NORMAL = INSTRUCTION_EQUIV_FREQ_4MHZ,
CPU_FREQUENCY_X2 = INSTRUCTION_EQUIV_FREQ_8MHZ,
CPU_FREQUENCY_X4 = INSTRUCTION_EQUIV_FREQ_16MHZ,
CPU_FREQUENCY_X8 = INSTRUCTION_EQUIV_FREQ_32MHZ,
CPU_FREQUENCY_X16 = INSTRUCTION_EQUIV_FREQ_64MHZ,
CPU_FREQUENCY_X32 = INSTRUCTION_EQUIV_FREQ_128MHZ,
CPU_FREQUENCY_X64 = INSTRUCTION_EQUIV_FREQ_256MHZ,
CPU_FREQUENCY_X128 = INSTRUCTION_EQUIV_FREQ_512MHZ,
};
#endif
// MZ-80A - These values are dependent on the CPU Freq of the SSD202. Values are for 1.2GHz, in brackets for 1.0GHz
// The reason for having 2 sets of delays is due to original coding where ROM memory required less instructions
// than RAM. Also depending upon build slight differences need to be catered for, ie. when including debug logic
// there are extra instructions to process during the fetch cycle.
#if(TARGET_HOST_MZ80A == 1)
#if(DEBUG_ENABLED > 0)
#define INSTRUCTION_DELAY_ROM_2MHZ 427 // (420)
#define INSTRUCTION_DELAY_ROM_4MHZ 218
#define INSTRUCTION_DELAY_ROM_8MHZ 109
#define INSTRUCTION_DELAY_ROM_16MHZ 54
#define INSTRUCTION_DELAY_ROM_32MHZ 27
#define INSTRUCTION_DELAY_ROM_64MHZ 14
#define INSTRUCTION_DELAY_ROM_128MHZ 7
#define INSTRUCTION_DELAY_ROM_256MHZ 3
#define INSTRUCTION_DELAY_RAM_2MHZ 425
#define INSTRUCTION_DELAY_RAM_4MHZ 212
#define INSTRUCTION_DELAY_RAM_8MHZ 106
#define INSTRUCTION_DELAY_RAM_16MHZ 53
#define INSTRUCTION_DELAY_RAM_32MHZ 26
#define INSTRUCTION_DELAY_RAM_64MHZ 13
#define INSTRUCTION_DELAY_RAM_128MHZ 7
#define INSTRUCTION_DELAY_RAM_256MHZ 0
#endif
#if(DEBUG_ENABLED == 0)
#define INSTRUCTION_DELAY_ROM_2MHZ 429 // (420)
#define INSTRUCTION_DELAY_ROM_4MHZ 218
#define INSTRUCTION_DELAY_ROM_8MHZ 109
#define INSTRUCTION_DELAY_ROM_16MHZ 54
#define INSTRUCTION_DELAY_ROM_32MHZ 27
#define INSTRUCTION_DELAY_ROM_64MHZ 14
#define INSTRUCTION_DELAY_ROM_128MHZ 7
#define INSTRUCTION_DELAY_ROM_256MHZ 3
#define INSTRUCTION_DELAY_RAM_2MHZ 425
#define INSTRUCTION_DELAY_RAM_4MHZ 210
#define INSTRUCTION_DELAY_RAM_8MHZ 105
#define INSTRUCTION_DELAY_RAM_16MHZ 52
#define INSTRUCTION_DELAY_RAM_32MHZ 26
#define INSTRUCTION_DELAY_RAM_64MHZ 13
#define INSTRUCTION_DELAY_RAM_128MHZ 7
#define INSTRUCTION_DELAY_RAM_256MHZ 0
#endif
#define INSTRUCTION_EQUIV_FREQ_2MHZ 2000000
#define INSTRUCTION_EQUIV_FREQ_4MHZ 4000000
#define INSTRUCTION_EQUIV_FREQ_8MHZ 8000000
#define INSTRUCTION_EQUIV_FREQ_16MHZ 16000000
#define INSTRUCTION_EQUIV_FREQ_32MHZ 32000000
#define INSTRUCTION_EQUIV_FREQ_64MHZ 64000000
#define INSTRUCTION_EQUIV_FREQ_128MHZ 128000000
#define INSTRUCTION_EQUIV_FREQ_256MHZ 256000000
#define INSTRUCTION_GOVERNOR_IO_SKIP 2
// Table of governor delays to be used to control run frequency,
enum Z80_INSTRUCTION_DELAY {
ROM_DELAY_NORMAL = INSTRUCTION_DELAY_ROM_2MHZ,
ROM_DELAY_X2 = INSTRUCTION_DELAY_ROM_4MHZ,
ROM_DELAY_X4 = INSTRUCTION_DELAY_ROM_8MHZ,
ROM_DELAY_X8 = INSTRUCTION_DELAY_ROM_16MHZ,
ROM_DELAY_X16 = INSTRUCTION_DELAY_ROM_32MHZ,
ROM_DELAY_X32 = INSTRUCTION_DELAY_ROM_64MHZ,
ROM_DELAY_X64 = INSTRUCTION_DELAY_ROM_128MHZ,
ROM_DELAY_X128 = INSTRUCTION_DELAY_ROM_256MHZ,
RAM_DELAY_NORMAL = INSTRUCTION_DELAY_RAM_2MHZ,
RAM_DELAY_X2 = INSTRUCTION_DELAY_RAM_4MHZ,
RAM_DELAY_X4 = INSTRUCTION_DELAY_RAM_8MHZ,
RAM_DELAY_X8 = INSTRUCTION_DELAY_RAM_16MHZ,
RAM_DELAY_X16 = INSTRUCTION_DELAY_RAM_32MHZ,
RAM_DELAY_X32 = INSTRUCTION_DELAY_RAM_64MHZ,
RAM_DELAY_X64 = INSTRUCTION_DELAY_RAM_128MHZ,
RAM_DELAY_X128 = INSTRUCTION_DELAY_RAM_256MHZ,
CPU_FREQUENCY_NORMAL = INSTRUCTION_EQUIV_FREQ_2MHZ,
CPU_FREQUENCY_X2 = INSTRUCTION_EQUIV_FREQ_4MHZ,
CPU_FREQUENCY_X4 = INSTRUCTION_EQUIV_FREQ_8MHZ,
CPU_FREQUENCY_X8 = INSTRUCTION_EQUIV_FREQ_16MHZ,
CPU_FREQUENCY_X16 = INSTRUCTION_EQUIV_FREQ_32MHZ,
CPU_FREQUENCY_X32 = INSTRUCTION_EQUIV_FREQ_64MHZ,
CPU_FREQUENCY_X64 = INSTRUCTION_EQUIV_FREQ_128MHZ,
CPU_FREQUENCY_X128 = INSTRUCTION_EQUIV_FREQ_256MHZ,
};
#endif
// Amstrad PCW-8256
#if(TARGET_HOST_PCW == 1)
#if(DEBUG_ENABLED > 0)
#define INSTRUCTION_DELAY_ROM_4MHZ 295
#define INSTRUCTION_DELAY_ROM_8MHZ 148
#define INSTRUCTION_DELAY_ROM_16MHZ 74
#define INSTRUCTION_DELAY_ROM_32MHZ 37
#define INSTRUCTION_DELAY_ROM_64MHZ 19
#define INSTRUCTION_DELAY_ROM_128MHZ 10
#define INSTRUCTION_DELAY_ROM_256MHZ 5
#define INSTRUCTION_DELAY_ROM_512MHZ 3
#define INSTRUCTION_DELAY_RAM_4MHZ 240
#define INSTRUCTION_DELAY_RAM_8MHZ 148
#define INSTRUCTION_DELAY_RAM_16MHZ 74
#define INSTRUCTION_DELAY_RAM_32MHZ 37
#define INSTRUCTION_DELAY_RAM_64MHZ 19
#define INSTRUCTION_DELAY_RAM_128MHZ 10
#define INSTRUCTION_DELAY_RAM_256MHZ 5
#define INSTRUCTION_DELAY_RAM_512MHZ 3
#endif
#if(DEBUG_ENABLED == 0)
#define INSTRUCTION_DELAY_ROM_4MHZ 295
#define INSTRUCTION_DELAY_ROM_8MHZ 148
#define INSTRUCTION_DELAY_ROM_16MHZ 74
#define INSTRUCTION_DELAY_ROM_32MHZ 37
#define INSTRUCTION_DELAY_ROM_64MHZ 19
#define INSTRUCTION_DELAY_ROM_128MHZ 10
#define INSTRUCTION_DELAY_ROM_256MHZ 5
#define INSTRUCTION_DELAY_ROM_512MHZ 3
#define INSTRUCTION_DELAY_RAM_4MHZ 240
#define INSTRUCTION_DELAY_RAM_8MHZ 148
#define INSTRUCTION_DELAY_RAM_16MHZ 74
#define INSTRUCTION_DELAY_RAM_32MHZ 37
#define INSTRUCTION_DELAY_RAM_64MHZ 19
#define INSTRUCTION_DELAY_RAM_128MHZ 10
#define INSTRUCTION_DELAY_RAM_256MHZ 5
#define INSTRUCTION_DELAY_RAM_512MHZ 3
#endif
#define INSTRUCTION_EQUIV_FREQ_4MHZ 4000000
#define INSTRUCTION_EQUIV_FREQ_8MHZ 8000000
#define INSTRUCTION_EQUIV_FREQ_16MHZ 16000000
#define INSTRUCTION_EQUIV_FREQ_32MHZ 32000000
#define INSTRUCTION_EQUIV_FREQ_64MHZ 64000000
#define INSTRUCTION_EQUIV_FREQ_128MHZ 128000000
#define INSTRUCTION_EQUIV_FREQ_256MHZ 256000000
#define INSTRUCTION_EQUIV_FREQ_512MHZ 512000000
#define INSTRUCTION_GOVERNOR_IO_SKIP 5
enum Z80_INSTRUCTION_DELAY {
ROM_DELAY_NORMAL = INSTRUCTION_DELAY_ROM_4MHZ,
ROM_DELAY_X2 = INSTRUCTION_DELAY_ROM_8MHZ,
ROM_DELAY_X4 = INSTRUCTION_DELAY_ROM_16MHZ,
ROM_DELAY_X8 = INSTRUCTION_DELAY_ROM_32MHZ,
ROM_DELAY_X16 = INSTRUCTION_DELAY_ROM_64MHZ,
ROM_DELAY_X32 = INSTRUCTION_DELAY_ROM_128MHZ,
ROM_DELAY_X64 = INSTRUCTION_DELAY_ROM_256MHZ,
ROM_DELAY_X128 = INSTRUCTION_DELAY_ROM_512MHZ,
RAM_DELAY_NORMAL = INSTRUCTION_DELAY_RAM_4MHZ,
RAM_DELAY_X2 = INSTRUCTION_DELAY_RAM_8MHZ,
RAM_DELAY_X4 = INSTRUCTION_DELAY_RAM_16MHZ,
RAM_DELAY_X8 = INSTRUCTION_DELAY_RAM_32MHZ,
RAM_DELAY_X16 = INSTRUCTION_DELAY_RAM_64MHZ,
RAM_DELAY_X32 = INSTRUCTION_DELAY_RAM_128MHZ,
RAM_DELAY_X64 = INSTRUCTION_DELAY_RAM_256MHZ,
RAM_DELAY_X128 = INSTRUCTION_DELAY_RAM_512MHZ,
CPU_FREQUENCY_NORMAL = INSTRUCTION_EQUIV_FREQ_4MHZ,
CPU_FREQUENCY_X2 = INSTRUCTION_EQUIV_FREQ_8MHZ,
CPU_FREQUENCY_X4 = INSTRUCTION_EQUIV_FREQ_16MHZ,
CPU_FREQUENCY_X8 = INSTRUCTION_EQUIV_FREQ_32MHZ,
CPU_FREQUENCY_X16 = INSTRUCTION_EQUIV_FREQ_64MHZ,
CPU_FREQUENCY_X32 = INSTRUCTION_EQUIV_FREQ_128MHZ,
CPU_FREQUENCY_X64 = INSTRUCTION_EQUIV_FREQ_256MHZ,
CPU_FREQUENCY_X128 = INSTRUCTION_EQUIV_FREQ_512MHZ,
};
#endif
// IOCTL commands. Passed from user space using the IOCTL method to command the driver to perform an action.
#define IOCTL_CMD_Z80_STOP 's'
#define IOCTL_CMD_Z80_START 'S'
#define IOCTL_CMD_Z80_PAUSE 'P'
#define IOCTL_CMD_Z80_RESET 'R'
#define IOCTL_CMD_Z80_CONTINUE 'C'
#define IOCTL_CMD_USE_HOST_RAM 'x'
#define IOCTL_CMD_USE_VIRTUAL_RAM 'X'
#define IOCTL_CMD_DUMP_MEMORY 'M'
#define IOCTL_CMD_Z80_CPU_FREQ 'F'
#define IOCTL_CMD_ADD_DEVICE 'A'
#define IOCTL_CMD_DEL_DEVICE 'D'
#define IOCTL_CMD_CPLD_CMD 'z'
#define IOCTL_CMD_SEND _IOW('c', 'c', int32_t *)
#define IOCTL_CMD_SETPC _IOW('p', 'p', int32_t *)
#define IOCTL_CMD_SYNC_TO_HOST_RAM 'V'
#define IOCTL_CMD_DEBUG 'd'
#define IOCTL_CMD_SPI_TEST '1'
#define IOCTL_CMD_PRL_TEST '2'
#define IOCTL_CMD_Z80_MEMTEST '3'
// Chip Select map MZ80K-MZ700.
//
// 0000 - 0FFF = CS_ROMni : R/W : MZ80K/A/700 = Monitor ROM or RAM (MZ80A rom swap)
// 1000 - CFFF = CS_RAMni : R/W : MZ80K/A/700 = RAM
// C000 - CFFF = CS_ROMni : R/W : MZ80A = Monitor ROM (MZ80A rom swap)
// D000 - D7FF = CS_VRAMni : R/W : MZ80K/A/700 = VRAM
// D800 - DFFF = CS_VRAMni : R/W : MZ700 = Colour VRAM (MZ700)
// E000 - E003 = CS_8255n : R/W : MZ80K/A/700 = 8255
// E004 - E007 = CS_8254n : R/W : MZ80K/A/700 = 8254
// E008 - E00B = CS_LS367n : R/W : MZ80K/A/700 = LS367
// E00C - E00F = CS_ESWPn : R : MZ80A = Memory Swap (MZ80A)
// E010 - E013 = CS_ESWPn : R : MZ80A = Reset Memory Swap (MZ80A)
// E014 = CS_E5n : R/W : MZ80A/700 = Normal CRT display (in Video Controller)
// E015 = CS_E6n : R/W : MZ80A/700 = Reverse CRT display (in Video Controller)
// E200 - E2FF = : R/W : MZ80A/700 = VRAM roll up/roll down.
// E800 - EFFF = : R/W : MZ80K/A/700 = User ROM socket or DD Eprom (MZ700)
// F000 - F7FF = : R/W : MZ80K/A/700 = Floppy Disk interface.
// F800 - FFFF = : R/W : MZ80K/A/700 = Floppy Disk interface.
//
// Chip Select map MZ800
//
// FC - FF = CS_PIOn : R/W : MZ800/MZ1500 = Z80 PIO Printer Interface
// F2 = CS_PSG0n : W : MZ800/MZ1500 = Programable Sound Generator, MZ-800 = Mono, MZ-1500 = Left Channel
// F3 = CS_PSG1n : W : MZ1500 = Programable Sound Generator, MZ-1500 = Right Channel
// E9 = CS_PSG(X)n: W : MZ1500 = Simultaneous write to both PSG's.
// F0 - F1 = CS_JOYSTK : R : MZ800 = Joystick 1 and 2
// CC = CS_GWF : W : MZ800 = CRTC GWF Write format Register
// CD = CS_GRF : W : MZ800 = CRTC GRF Read format Register
// CE = CS_GDMD : W : MZ800 = CRTC GDMD Mode Register
// CF = CS_GCRTC : W : MZ800 = CRTC GCRTC Control Register
// D4 - D7 = CS
// D000 - DFFF
// MZ700/MZ800 memory mode switch?
//
// MZ-700 MZ-800
// |0000:0FFF|1000:1FFF|1000:CFFF|C000:CFFF|D000:FFFF |0000:7FFF|1000:1FFF|2000:7FFF|8000:BFFF|C000:CFFF|C000:DFFF|E000:FFFF
// -------------------------------------------------- ----------------------------------------------------------------------
// OUT 0xE0 = |DRAM | | | | |DRAM | | | | | |
// OUT 0xE1 = | | | | |DRAM | | | | | | |DRAM
// OUT 0xE2 = |MONITOR | | | | |MONITOR | | | | | |
// OUT 0xE3 = | | | | |Memory Mapped I/O | | | | | | |Upper MONITOR ROM
// OUT 0xE4 = |MONITOR | |DRAM | |Memory Mapped I/O |MONITOR |CGROM |DRAM |VRAM | |DRAM |Upper MONITOR ROM
// OUT 0xE5 = | | | | |Inhibit | | | | | | |Inhibit
// OUT 0xE6 = | | | | |<return> | | | | | | |<return>
// IN 0xE0 = | |CGROM* | |VRAM* | | |CGROM | |VRAM | | |
// IN 0xE1 = | |DRAM | |DRAM | | |<return> | |DRAM | | |
//
// <return> = Return to the state prior to the complimentary command being invoked.
// * = MZ-800 host only.
// Macros to lookup and test to see if a given memory block or IO byte is of a given type. Also macros to read/write to the memory block and IO byte.
// The memory page arrays dont check for allocation due to speed, it is assumed a memory mode page has been allocated and defined prior to the memoryMode
// variable being set to that page.
#define MEMORY_MODES 32 // Maximum number of different memory modes.
#define MEMORY_PAGE_SIZE 0x10000 // Total size of directly addressable memory.
#define MEMORY_BLOCK_GRANULARITY 0x1 // Any change update MEMORY_BLOCK_SHIFT and mask in MEMORY_BLOCK_MASK
#define MEMORY_BLOCK_SHIFT 0
#define MEMORY_BLOCK_SLOTS (MEMORY_PAGE_SIZE / MEMORY_BLOCK_GRANULARITY)
#define MEMORY_BLOCK_MASK (MEMORY_PAGE_SIZE - MEMORY_BLOCK_GRANULARITY)
#define IO_PAGE_SIZE 0x10000 // Total size of directly addressable I/O.
#define IO_BLOCK_GRANULARITY 0x1 // Any change update MEMORY_BLOCK_SHIFT and mask in MEMORY_BLOCK_MASK
#define IO_BLOCK_SHIFT 0
#define IO_BLOCK_SLOTS (IO_PAGE_SIZE / IO_BLOCK_GRANULARITY)
#define IO_BLOCK_MASK (IO_PAGE_SIZE - IO_BLOCK_GRANULARITY)
//#define getPageData(a) (Z80Ctrl->page[(a & 0xFFFF) >> MEMORY_BLOCK_SHIFT])
//#define getIOPageData(a) (Z80Ctrl->iopage[(a & 0xFFFF])
#define getPageData(a) (*(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + ((a & MEMORY_BLOCK_MASK) >> MEMORY_BLOCK_SHIFT)))
#define getIOPageData(a) (Z80Ctrl->iopage[(a & IO_BLOCK_MASK])
#define getPageType(a, mask) (getPageData(a) & mask)
#define getPageAddr(a, mask) ((getPageData(a) & mask) + (a & (MEMORY_BLOCK_GRANULARITY-1)))
#define getIOPageType(a, mask) (getIOPageData(a) & mask)
#define getIOPageAddr(a, mask) (getIOPageData(a) & mask)
//#define realAddress(a) (Z80Ctrl->page[getPageAddr(a, MEMORY_TYPE_REAL_MASK)])
#define realAddress(a) (*(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + (getPageAddr(a, MEMORY_TYPE_REAL_MASK))))
#define realPort(a) (Z80Ctrl->iopage[a & IO_BLOCK_MASK] & IO_TYPE_MASK)
#define isPhysicalRAM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_RAM))
#define isPhysicalVRAM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_VRAM))
#define isPhysicalROM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_ROM))
#define isPhysicalMemory(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_ROM | MEMORY_TYPE_PHYSICAL_RAM | MEMORY_TYPE_PHYSICAL_VRAM))])
#define isPhysicalHW(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_HW))
#define isPhysical(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_HW | MEMORY_TYPE_PHYSICAL_ROM | MEMORY_TYPE_PHYSICAL_RAM | MEMORY_TYPE_PHYSICAL_VRAM)))
#define isPhysicalIO(a) (Z80Ctrl->iopage[a & IO_BLOCK_MASK] & IO_TYPE_PHYSICAL_HW)
#define isVirtualRAM(a) (getPageType(a, (MEMORY_TYPE_VIRTUAL_RAM | MEMORY_TYPE_VIRTUAL_RAM_RO)))
#define isVirtualRO(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_RAM_RO))
#define isVirtualRW(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_RAM))
#define isVirtualROM(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_ROM))
#define isVirtualMemory(a) (getPageType(a, (MEMORY_TYPE_VIRTUAL_ROM | MEMORY_TYPE_VIRTUAL_RAM | MEMORY_TYPE_VIRTUAL_RAM_RO)))
#define isVirtualHW(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_HW))
#define isVirtualIO(a) (Z80Ctrl->iopage[a & IO_BLOCK_MASK] & IO_TYPE_VIRTUAL_HW)
#define isVirtual(a) (getPageType(a, (MEMORY_TYPE_VIRTUAL_ROM | MEMORY_TYPE_VIRTUAL_RAM | MEMORY_TYPE_VIRTUAL_RAM_RO | MEMORY_TYPE_VIRTUAL_HW)))
#define isVirtualDevice(a, d) (Z80Ctrl->iopage[a & IO_BLOCK_MASK] & d)
#define isHW(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_HW | MEMORY_TYPE_VIRTUAL_HW)))
#define readVirtualRAM(a) (Z80Ctrl->ram[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ])
#define readVirtualROM(a) (Z80Ctrl->rom[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ])
#define writeVirtualRAM(a, d) { Z80Ctrl->ram[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ] = d; }
#define writeVirtualROM(a, d) { Z80Ctrl->rom[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ] = d; }
//#define setMemoryType(_block_,_type_,_addr_) { Z80Ctrl->page[_block_] = _type_ | _addr_; }
#define setMemoryType(_block_,_type_,_addr_) { *(*(Z80Ctrl->page + Z80Ctrl->memoryMode) +_block_) = _type_ | _addr_; }
#define backupMemoryType(_block_) { Z80Ctrl->shadowPage[_block_] = *(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + (_block_)); }
//#define restoreMemoryType(_block_) { Z80Ctrl->page[_block_] = Z80Ctrl->shadowPage[_block_]; }
#define restoreMemoryType(_block_) { *(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + (_block_)) = Z80Ctrl->shadowPage[_block_]; }
#define sendSignal(__task__, _signal_) { struct siginfo sigInfo;\
if(__task__ != NULL)\
{\
memset(&sigInfo, 0, sizeof(struct siginfo));\
sigInfo.si_signo = _signal_;\
sigInfo.si_code = SI_QUEUE;\
sigInfo.si_int = 1;\
if(send_sig_info(_signal_, &sigInfo, __task__) < 0)\
{\
pr_info("Error: Failed to send signal:%02x to:%s\n", _signal_, __task__->comm);\
}\
}\
}
#define resetZ80() {\
setupMemory(Z80Ctrl->defaultPageMode);\
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_TZPU)\
{\
sendSignal(Z80Ctrl->ioTask, SIGUSR1); \
udelay(2000);\
}\
z80_instant_reset(&Z80CPU);\
}
#define IO_ADDR_E0 0xE0
#define IO_ADDR_E1 0xE1
#define IO_ADDR_E2 0xE2
#define IO_ADDR_E3 0xE3
#define IO_ADDR_E4 0xE4
#define IO_ADDR_E5 0xE5
#define IO_ADDR_E6 0xE6
#define IO_ADDR_E7 0xE7
#define IO_ADDR_E8 0xE8
#define IO_ADDR_E9 0xE9
#define IO_ADDR_EA 0xEA
#define IO_ADDR_EB 0xEB
enum Z80_RUN_STATES {
Z80_STOP = 0x00,
Z80_STOPPED = 0x01,
Z80_PAUSE = 0x02,
Z80_PAUSED = 0x03,
Z80_CONTINUE = 0x04,
Z80_RUNNING = 0x05,
};
enum Z80_MEMORY_PROFILE {
USE_PHYSICAL_RAM = 0x00,
USE_VIRTUAL_RAM = 0x01
};
enum VIRTUAL_DEVICE {
VIRTUAL_DEVICE_NONE = 0x00000000,
VIRTUAL_DEVICE_MZ80A = 0x00000001,
VIRTUAL_DEVICE_MZ700 = 0x00000002,
VIRTUAL_DEVICE_MZ2000 = 0x00000004,
VIRTUAL_DEVICE_PCW = 0x00000008,
VIRTUAL_DEVICE_RFS40 = 0x01000000,
VIRTUAL_DEVICE_RFS80 = 0x02000000,
VIRTUAL_DEVICE_RFS = 0x03000000,
VIRTUAL_DEVICE_TZPU = 0x04000000,
};
typedef struct {
// Main RAM/ROM memory, linear but indexed as though it were banks in 1K pages.
uint8_t *ram;
uint8_t *rom;
// Compatibility mode, enables virtual mapping and virtual hardware to make the Z80 with the underlying host appear
// as a host equipped with a specific hardware add on.
// The devices are stored in an array for ease of reference and lookup in the driver and ctrl program, in actual
// use they are a bit map for performance as scanning an array is time consuming.
//
enum VIRTUAL_DEVICE virtualDevice[MAX_VIRTUAL_DEVICES];
uint32_t virtualDeviceBitMap;
uint8_t virtualDeviceCnt;
// Page pointer map.
//
// Each pointer points to a byte or block of bytes in the Z80 Memory frame, 64K Real + Banked.
// This is currently set at a block of size 0x1 per memory pointer for the MZ-700.
// The LSB of the pointer is a direct memory index to a byte or block of bytes, the upper byte of the pointer indicates type of memory space.
// 0x80<FFFFFF> - physical host RAM
// 0x40<FFFFFF> - physical host ROM
// 0x20<FFFFFF> - physical host VRAM
// 0x10<FFFFFF> - physical host hardware
// 0x08<FFFFFF> - virtual host RAM
// 0x04<FFFFFF> - virtual host ROM
// 0x02<FFFFFF> - virtual host hardware
// 16bit Input Address -> map -> Pointer to 24bit memory address + type flag.
// -> Pointer+<low bits of address> to 24bit memory address + type flag.
//uint32_t page[MEMORY_BLOCK_SLOTS];
uint32_t *page[MEMORY_MODES];
uint32_t shadowPage[MEMORY_BLOCK_SLOTS]; // Shadow page is for manipulation and backup of an existing page.
// Current memory mode as used by active driver.
uint8_t memoryMode;
// I/O Page map.
//
// This is a map to indicate the use of the I/O page and allow any required remapping.
// <0x8000><I/O Address> - physical host hardware
// <0x4000><I/O Address> - virtual host hardware
// <0x3FFF><I/O Address> - bit map to indicate allocated device.
// 16bit Input Address -> map -> Actual 16bit address to use + type flag.
uint32_t iopage[65536];
// Default page mode configured. This value reflects the default page and iotable map.
uint8_t defaultPageMode;
// Refresh DRAM mode. 1 = Refresh, 0 = No refresh. Only applicable when running code in virtual Kernel RAM.
uint8_t refreshDRAM;
// Inhibit mode is where certain memory ranges are inhibitted. The memory page is set to inhibit and this flag
// blocks actions which arent allowed during inhibit.
uint8_t inhibitMode;
// I/O lookahead flags - to overcome SSD202 io slowness.
uint8_t ioReadAhead;
uint8_t ioWriteAhead;
// Keyboard strobe and data. Required to detect hotkey press.
uint8_t keyportStrobe;
uint8_t keyportShiftCtrl;
uint8_t keyportHotKey;
uint8_t keyportTrigger;
uint8_t keyportTriggerLast;
// Governor is the delay in a 32bit loop per Z80 opcode, used to govern execution speed when using virtual memory.
// This mechanism will eventually be tied into the M/T-state calculation for a more precise delay, but at the moment,
// with the Z80 assigned to an isolated CPU, it allows time sensitive tasks such as the tape recorder to work.
// The lower the value the faster the CPU speed. Two values are present as the optimiser, seeing ROM code not changing
// is quicker than RAM (both are in the same kernel memory) as a pointer calculation needs to be made.
uint32_t cpuGovernorDelayROM;
uint32_t cpuGovernorDelayRAM;
uint8_t governorSkip;
// An I/O processor, running as a User Space daemon, can register to receive signals and events.
struct task_struct *ioTask;
// Sharp MZ Arbiter, running as a User Space daemon, registers to receive signals and events in order to direct the persona of the FusionX.
struct task_struct *arbTask;
#if(DEBUG_ENABLED != 0)
// Debugging flag.
uint8_t debug;
#endif
} t_Z80Ctrl;
// IOCTL structure for passing data from user space to driver to perform commands.
//
struct z80_addr {
uint32_t start;
uint32_t end;
uint32_t size;
};
struct z80_ctrl {
uint16_t pc;
};
struct speed {
uint32_t speedMultiplier;
};
struct virtual_device {
enum VIRTUAL_DEVICE device;
};
struct cpld_ctrl {
uint32_t cmd;
};
#if(DEBUG_ENABLED != 0)
struct debug {
uint8_t level;
};
#endif
struct ioctlCmd {
int32_t cmd;
union {
struct z80_addr addr;
struct z80_ctrl z80;
struct speed speed;
struct virtual_device vdev;
struct cpld_ctrl cpld;
#if(DEBUG_ENABLED != 0)
struct debug debug;
#endif
};
};
// Prototypes.
void setupMemory(enum Z80_MEMORY_PROFILE);
int thread_z80(void *);
#endif

View File

@@ -7,9 +7,13 @@
// This file contains the methods used in interfacing the SOM to the Z80 socket
// and host hardware via a CPLD.
// Credits:
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Oct 2022 - Initial write of the z80 kernel driver software.
// History: Oct 2022 v1.0 - Initial write of the z80 kernel driver software.
// Jan 2023 v1.1 - Numerous new tries at increasing throughput to the CPLD failed.
// Maximum read throughput of an 8bit byte due to the SSD202 GPIO
// structure is approx 2MB/s - or 512K/s for a needed 32bit word.
// Write is slower as you have to clock the data so sticking with SPI.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -59,7 +63,6 @@
//-------------------------------------------------------------------------------------------------------------------------------
// Initialise the SOM hardware used to communicate with the z80 socket and host hardware.
// The SOM interfaces to a CPLD which provides voltage level translation and also encapsulates the Z80 timing cycles as recreating
// them within the SOM is much more tricky.
@@ -184,7 +187,7 @@ int z80io_init(void)
inline uint8_t z80io_PRL_Read8(uint8_t dataFlag)
{
// Locals.
uint8_t result = 0;
volatile uint8_t result = 0;
// Byte according to flag.
if(dataFlag)
@@ -199,10 +202,31 @@ inline uint8_t z80io_PRL_Read8(uint8_t dataFlag)
return(result);
}
inline uint8_t z80io_PRL_Read(void)
{
// Locals.
volatile uint8_t result = 0;
volatile uint32_t b7, b6, b5, b4, b3, b2, b1, b0;
// Read the input registers and set value accordingly. Quicker to read registers and then apply shift/logical operators. The I/O Bus is very slow!
b7 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_7_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_7_ADDR & 1)));
b6 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_6_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_6_ADDR & 1)));
b5 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_5_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_5_ADDR & 1)));
b4 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_4_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_4_ADDR & 1)));
b3 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_3_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_3_ADDR & 1)));
b2 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_2_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_2_ADDR & 1)));
b1 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_1_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_1_ADDR & 1)));
b0 = READ_LONG(((gRIUBaseAddr) + (((PAD_Z80IO_IN_DATA_0_ADDR) & ~1)<<1) + (PAD_Z80IO_IN_DATA_0_ADDR & 1)));
result = (b7 & 0x1) << 7 | (b6 & 0x1) << 6 | (b5 & 0x1) << 5 | (b4 & 0x1) << 4 | (b3 & 0x1) << 3 | (b2 & 0x1) << 2 | (b1 & 0x1) << 1 | (b0 & 0x1);
// Return 16bit value read from CPLD.
return(result);
}
inline uint16_t z80io_PRL_Read16(void)
{
// Locals.
uint16_t result = 0;
volatile uint16_t result = 0;
// Low byte first.
CLEAR_CPLD_HIGH_BYTE();

View File

@@ -7,9 +7,13 @@
// This file contains the declarations used in interfacing the SOM to the Z80 socket
// and host hardware via a CPLD.
// Credits:
// Copyright: (c) 2019-2022 Philip Smart <philip.smart@net2net.org>
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Oct 2022 - Initial write of the z80 kernel driver software.
// History: Oct 2022 v1.0 - Initial write of the z80 kernel driver software.
// Jan 2023 v1.1 - Numerous new tries at increasing throughput to the CPLD failed.
// Maximum read throughput of an 8bit byte due to the SSD202 GPIO
// structure is approx 2MB/s - or 512K/s for a needed 32bit word.
// Write is slower as you have to clock the data so sticking with SPI.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -78,6 +82,14 @@
#define CPLD_CMD_READIO_ADDR_P5 0x35
#define CPLD_CMD_READIO_ADDR_P6 0x36
#define CPLD_CMD_READIO_ADDR_P7 0x37
#define CPLD_CMD_READIO_WRITE_ADDR 0x38
#define CPLD_CMD_READIO_WRITE_ADDR_P1 0x39
#define CPLD_CMD_READIO_WRITE_ADDR_P2 0x3A
#define CPLD_CMD_READIO_WRITE_ADDR_P3 0x3B
#define CPLD_CMD_READIO_WRITE_ADDR_P4 0x3C
#define CPLD_CMD_READIO_WRITE_ADDR_P5 0x3D
#define CPLD_CMD_READIO_WRITE_ADDR_P6 0x3E
#define CPLD_CMD_READIO_WRITE_ADDR_P7 0x3F
#define CPLD_CMD_HALT 0x50
#define CPLD_CMD_REFRESH 0x51
#define CPLD_CMD_SET_SIGROUP1 0xF0
@@ -103,10 +115,10 @@
#define PAD_SPIO_3 PAD_GPIO11
#define PAD_Z80IO_HIGH_BYTE PAD_SAR_GPIO2 // Byte requiured, 0 = Low Byte, 1 = High Byte.
#define PAD_Z80IO_READY PAD_GPIO12
#define PAD_Z80IO_LTSTATE PAD_PM_IRIN // IRIN
#define PAD_Z80IO_LTSTATE PAD_UART0_RX // GPIO47
#define PAD_Z80IO_BUSRQ PAD_GPIO13
#define PAD_Z80IO_BUSACK PAD_GPIO14
#define PAD_Z80IO_INT PAD_UART0_RX // GPIO47
#define PAD_Z80IO_INT PAD_PM_IRIN // IRIN
#define PAD_Z80IO_NMI PAD_UART0_TX // GPIO48
#define PAD_Z80IO_WAIT PAD_HSYNC_OUT // GPIO85
#define PAD_Z80IO_RESET PAD_VSYNC_OUT // GPIO86
@@ -126,11 +138,11 @@
#define PAD_SPIO_2_ADDR 0x103C14
#define PAD_SPIO_3_ADDR 0x103C16
#define PAD_Z80IO_HIGH_BYTE_ADDR 0x1425
#define PAD_Z80IO_READY_ADDR 0x103C18
#define PAD_Z80IO_LTSTATE_ADDR 0xF28 // IRIN
#define PAD_Z80IO_READY_ADDR 0x103C18 // GPIO12
#define PAD_Z80IO_LTSTATE_ADDR 0x103C30 // GPIO47
#define PAD_Z80IO_BUSRQ_ADDR 0x103C1A
#define PAD_Z80IO_BUSACK_ADDR 0x103C1C
#define PAD_Z80IO_INT_ADDR 0x103C30 // GPIO47
#define PAD_Z80IO_INT_ADDR 0xF28 // IRIN
#define PAD_Z80IO_NMI_ADDR 0x103C32 // GPIO48
#define PAD_Z80IO_WAIT_ADDR 0x103C80 // GPIO85
#define PAD_Z80IO_RESET_ADDR 0x103C82 // GPIO86
@@ -380,8 +392,10 @@
#define CPLD_READY() (MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1)
#define CPLD_RESET() (MHal_RIU_REG(PAD_Z80IO_RESET_ADDR) & 0x1)
#define CPLD_LAST_TSTATE() (MHal_RIU_REG(PAD_Z80IO_LTSTATE_ADDR) & 0x4)
#define SPI_SEND8(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
#define CPLD_Z80_INT() (MHal_RIU_REG(PAD_Z80IO_INT_ADDR) & 0x4)
#define CPLD_Z80_NMI() (MHal_RIU_REG(PAD_Z80IO_NMI_ADDR) & 0x4)
#define SPI_SEND_8(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d_); \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 1); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0);\
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
@@ -390,9 +404,18 @@
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE);\
}
#define SPI_SEND_I_8(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d_); \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 1); \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE);\
}
#define SPI_SEND16(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 2); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0);\
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
@@ -400,10 +423,9 @@
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
}
#define SPI_SEND32(_d_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)((_d_) >> 16)); \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4); \
#define SPI_SEND_16(_d1_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 2); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d1_); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0);\
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
@@ -411,6 +433,62 @@
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
}
#define SPI_SEND_P_16(_d1_) { uint32_t timeout = MAX_CHECK_CNT; \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 2); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d1_); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) != 0);\
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
}
#define SPI_SET_FRAME_SIZE() { MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4); \
}
#define SPI_SEND32(_d_) { uint32_t timeout = MAX_CHECK_CNT*2; \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)(_d_)); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)((_d_) >> 16)); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0) { if(--timeout == 0) break; };\
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
}
#define SPI_SEND_32(_d1_, _d2_) { uint32_t timeout = MAX_CHECK_CNT*2; \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d2_); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)_d1_); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0) { if(--timeout == 0) break; };\
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
}
#define SPI_SEND_I_32(_d1_, _d2_) { uint32_t timeout = MAX_CHECK_CNT*2; \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 4); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d2_); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)_d1_); \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
}
#define SPI_SEND_48(_d1_, _d2_, _d3_) { uint32_t timeout = MAX_CHECK_CNT*2; \
MSPI_WRITE(MSPI_WBF_SIZE_OFFSET, 6); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET, (uint16_t)_d3_); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+1, (uint16_t)_d2_); \
MSPI_WRITE(MSPI_WRITE_BUF_OFFSET+2, (uint16_t)_d1_); \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_ENABLE); \
while((MHal_RIU_REG(PAD_Z80IO_READY_ADDR) & 0x1) == 0) { if(--timeout == 0) break; };\
MSPI_WRITE(MSPI_TRIGGER_OFFSET, MSPI_TRIGGER); \
while((MSPI_READ(MSPI_DONE_OFFSET) & MSPI_DONE_FLAG) == 0) { if(--timeout == 0) break; } \
MSPI_WRITE(MSPI_CHIP_SELECT_OFFSET, MSPI_CS8_DISABLE | MSPI_CS7_DISABLE | MSPI_CS6_DISABLE | MSPI_CS5_DISABLE | MSPI_CS4_DISABLE | MSPI_CS3_DISABLE | MSPI_CS2_DISABLE | MSPI_CS1_DISABLE); \
MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET, MSPI_CLEAR_DONE); \
}
// read 2 byte
#define MSPI_READ(_reg_) READ_WORD(gMspBaseAddr + ((_reg_)<<2))
@@ -434,7 +512,7 @@
#define MOVDMA_WRITE(_reg_, _val_) WRITE_WORD(gMOVDMAAddr + ((_reg_)<<2), (_val_));
#define _HAL_MSPI_ClearDone() MSPI_WRITE(MSPI_DONE_CLEAR_OFFSET,MSPI_CLEAR_DONE)
#define MAX_CHECK_CNT 2000
#define MAX_CHECK_CNT 5000
#define MSPI_READ_INDEX 0x0
#define MSPI_WRITE_INDEX 0x1
@@ -453,6 +531,7 @@ uint8_t z80io_SPI_Send32(uint32_t txData, uint32_t *rxData);
uint8_t z80io_PRL_Send8(uint8_t txData);
uint8_t z680io_PRL_Send16(uint16_t txData);
#endif
uint8_t z80io_PRL_Read(void);
uint8_t z80io_PRL_Read8(uint8_t dataFlag);
uint16_t z80io_PRL_Read16(void);
uint8_t z80io_SPI_Test(void);

View File

@@ -54,7 +54,7 @@ uint8_t z80io_Z80_TestMemory(void)
spinlock_t spinLock;
unsigned long flags;
SPI_SEND8(CPLD_CMD_CLEAR_AUTO_REFRESH);
SPI_SEND_8(CPLD_CMD_CLEAR_AUTO_REFRESH);
SPI_SEND32(0x00E30000 | (0x07 << 8) | CPLD_CMD_WRITEIO_ADDR);
udelay(100);
@@ -71,16 +71,16 @@ uint8_t z80io_Z80_TestMemory(void)
SPI_SEND32(0x00EB0000 | (0xFF << 8) | CPLD_CMD_WRITEIO_ADDR);
udelay(100);
pr_info("Z80 Host Test - IO.\n");
for(idx=0; idx < 1000000; idx++)
{
SPI_SEND32(0x00E80000 | (0xD3 << 8) | CPLD_CMD_WRITEIO_ADDR);
SPI_SEND32(0xD0000000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
SPI_SEND32(0xD0100000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
SPI_SEND32(0xD0200000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
SPI_SEND32(0xD0300000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
SPI_SEND32(0xD0400000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
SPI_SEND32(0xD0500000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
}
// for(idx=0; idx < 1000000; idx++)
// {
// SPI_SEND32(0x00E80000 | (0xD3 << 8) | CPLD_CMD_WRITEIO_ADDR);
// SPI_SEND32(0xD0000000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
// SPI_SEND32(0xD0100000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
// SPI_SEND32(0xD0200000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
// SPI_SEND32(0xD0300000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
// SPI_SEND32(0xD0400000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
// SPI_SEND32(0xD0500000 | (0x41 << 8) | CPLD_CMD_WRITE_ADDR);
// }
spin_lock_init(&spinLock);
pr_info("Z80 Host Test - Testing IO Write performance.\n");
@@ -185,7 +185,7 @@ uint8_t z80io_Z80_TestMemory(void)
// Read back the same byte.
cmd = 0x10;
SPI_SEND8(cmd);
SPI_SEND_8(cmd);
while(CPLD_READY() == 0);
result = READ_CPLD_DATA_IN();
@@ -223,7 +223,7 @@ uint8_t z80io_Z80_TestMemory(void)
// Read back the same byte.
cmd = 0x20;
SPI_SEND8(cmd);
SPI_SEND_8(cmd);
while(CPLD_READY() == 0);
result = READ_CPLD_DATA_IN();
@@ -254,7 +254,7 @@ uint8_t z80io_Z80_TestMemory(void)
} else
{
cmd = 0x11;
SPI_SEND8(cmd);
SPI_SEND_8(cmd);
}
while(CPLD_READY() == 0);
result = READ_CPLD_DATA_IN();
@@ -280,7 +280,7 @@ uint8_t z80io_Z80_TestMemory(void)
} else
{
cmd = 0x21;
SPI_SEND8(cmd);
SPI_SEND_8(cmd);
}
while(CPLD_READY() == 0);
result = READ_CPLD_DATA_IN();
@@ -306,7 +306,7 @@ uint8_t z80io_Z80_TestMemory(void)
} else
{
cmd = 0x19;
SPI_SEND8(cmd);
SPI_SEND_8(cmd);
}
}
for(idx=0; idx < iterations; idx++)
@@ -322,7 +322,7 @@ uint8_t z80io_Z80_TestMemory(void)
} else
{
cmd = 0x19;
SPI_SEND8(cmd);
SPI_SEND_8(cmd);
}
}
}

View File

@@ -0,0 +1,436 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: z80vhw_mz2000.c
// Created: Oct 2022
// Author(s): Philip Smart
// Description: Z80 Virtual Hardware Driver - MZ-2000
// This file contains the methods used to emulate the original Sharp MZ-2000 without
// any additions, such as the RFS or TZFS boards.
//
// These drivers are intended to be instantiated inline to reduce overhead of a call
// and as such, they are included like header files rather than C linked object files.
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Mar 2023 v1.0 - Initial write based on the RFS hardware module.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/time.h>
#include "z80io.h"
#include <gpio_table.h>
#include <asm/io.h>
#include <infinity2m/gpio.h>
#include <infinity2m/registers.h>
// Device constants.
#define RAM_BASE_ADDR 0x00000 // Base address of the 512K RAM.
// System ROM's, either use the host machine ROM or preload a ROM image.
#define ROM_DIR "/apps/FusionX/host/MZ-2000/ROMS/"
#define ROM_IPL_ORIG_FILENAME ROM_DIR "mz2000_ipl.orig"
// Boot ROM rom load and size definitions.
#define ROM_BOOT_LOAD_ADDR 0x000000
#define ROM_BOOT_SIZE 0x800
// PCW control.
typedef struct {
uint8_t lowMemorySwap; // Boot mode lower memory is swapped to 0x8000:0xFFFF
uint8_t highMemoryVRAM; // Flag to indicate high memory range 0xD000:0xFFFF is assigned to VRAM.
uint8_t graphicsVRAM; // Flag to indicate graphics VRAM selected, default is character VRAM (0).
uint8_t regCtrl; // Control register.
} t_MZ2000Ctrl;
// RFS Board control.
static t_MZ2000Ctrl MZ2000Ctrl;
//-------------------------------------------------------------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------------------------------------------------------------
// Method to setup the memory page config to reflect the PCW configuration.
void mz2000SetupMemory(enum Z80_MEMORY_PROFILE mode)
{
// Locals.
uint32_t idx;
// The PCW contains upto 512KB of standard RAM which can be expnded to a physical max of 2MB. The kernel malloc limit is 2MB so the whole virtual
// memory can be mapped into the PCW memory address range.
// Setup defaults.
MZ2000Ctrl.lowMemorySwap = 0x01; // Set memory swap flag to swapped, ie. IPL mode sees DRAM 0x0000:0x7FFF swapped to 0x8000:0xFFFF and ROM pages into 0x0000.
MZ2000Ctrl.highMemoryVRAM = 0x00;
MZ2000Ctrl.graphicsVRAM = 0x00;
MZ2000Ctrl.regCtrl = 0x00;
// Setup default mode according to run mode, ie. Physical run or Virtual run.
//
if(mode == USE_PHYSICAL_RAM)
{
// Initialise the page pointers and memory to use physical RAM.
for(idx=0x0000; idx < MEMORY_PAGE_SIZE; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0 && idx < 0x8000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_ROM, idx);
}
else //if(idx >= 0x8000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_RAM, idx);
}
// Video RAM labelled as HW as we dont want to cache it.
//else if(idx >= 0xD000 && idx < 0xE000)
// {
// setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
//} else
// {
// setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_RAM, idx);
// }
}
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
// Cancel refresh as using physical RAM for program automatically refreshes DRAM.
Z80Ctrl->refreshDRAM = 0;
}
else if(mode == USE_VIRTUAL_RAM)
{
// Initialise the page pointers and memory to use virtual RAM.
// MZ-2000 comes up in IPL mode where lower 32K is ROM and upper 32K is RAM remapped from 0x0000.
for(idx=0x0000; idx < MEMORY_PAGE_SIZE; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0 && idx < 0x8000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
}
else
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (MZ2000Ctrl.lowMemorySwap ? idx - 0x8000 : idx));
}
}
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
// Enable refresh as using virtual RAM stops refresh of host DRAM.
Z80Ctrl->refreshDRAM = 2;
}
pr_info("MZ-2000 Memory Setup complete.\n");
}
// Method to load a ROM image into the RAM memory.
//
uint8_t mz2000LoadROM(const char* romFileName, uint32_t loadAddr, uint32_t loadSize)
{
// Locals.
uint8_t result = 0;
long noBytes;
struct file *fp;
fp = filp_open(romFileName, O_RDONLY, 0);
if(IS_ERR(fp))
{
pr_info("Error opening ROM Image:%s\n:", romFileName);
result = 1;
} else
{
vfs_llseek(fp, 0, SEEK_SET);
noBytes = kernel_read(fp, fp->f_pos, &Z80Ctrl->ram[loadAddr], loadSize);
if(noBytes < loadSize)
{
pr_info("Short load, ROM Image:%s, bytes loaded:%08x\n:", romFileName, loadSize);
}
filp_close(fp,NULL);
}
return(result);
}
// Perform any setup operations, such as variable initialisation, to enable use of this module.
void mz2000Init(uint8_t mode)
{
// Locals.
uint32_t idx;
// Initialise the virtual RAM from the HOST DRAM. This is to maintain compatibility as some applications (in my experience) have
// bugs, which Im putting down to not initialising variables. The host DRAM is in a pattern of 0x00..0x00, 0xFF..0xFF repeating
// when first powered on.
pr_info("Sync Host RAM to virtual RAM.\n");
for(idx=0; idx < Z80_VIRTUAL_RAM_SIZE; idx++)
{
// Lower memory is actually upper on startup, but ROM paged in, so set to zero.
if(idx >= 0x0000 && idx < 0x8000)
{
Z80Ctrl->ram[idx+0x8000] = 0x00;
} else
// Lower memory is paged in at 0x8000:0xFFFF
if(idx >= 0x8000 && idx < 0x10000)
{
SPI_SEND32((uint32_t)idx << 16 | CPLD_CMD_READ_ADDR);
while(CPLD_READY() == 0);
Z80Ctrl->ram[idx-0x8000] = z80io_PRL_Read8(1);
} else
{
Z80Ctrl->ram[idx] = 0x00;
}
}
// Original mode, ie. no virtual devices active, copy the host BIOS into the Virtual ROM and initialise remainder of ROM memory
// such that the host behaves as per original spec.
pr_info("Sync Host BIOS to virtual ROM.\n");
for(idx=0; idx < Z80_VIRTUAL_ROM_SIZE; idx++)
{
if(idx >= 0x0000 && idx < 0x8000)
{
SPI_SEND32((uint32_t)idx << 16 | CPLD_CMD_READ_ADDR);
while(CPLD_READY() == 0);
Z80Ctrl->rom[idx] = z80io_PRL_Read8(1);
} else
{
Z80Ctrl->rom[idx] = 0x00;
}
}
// Initial memory config.
mz2000SetupMemory(Z80Ctrl->defaultPageMode);
// mz2000LoadROM(ROM_IPL_ORIG_FILENAME, ROM_BOOT_LOAD_ADDR, ROM_BOOT_SIZE);
pr_info("Enabling MZ-2000 driver.\n");
return;
}
// Perform any de-initialisation when the driver is removed.
void mz2000Remove(void)
{
pr_info("Removing MZ-2000 driver.\n");
return;
}
// Method to decode an address and make any system memory map changes as required.
//
static inline void mz2000DecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t ioFlag, uint8_t readFlag)
{
// Locals.
uint32_t idx;
// Decoding memory address or I/O address?
if(ioFlag == 0)
{
// Certain machines have memory mapped I/O, these need to be handled in-situ as some reads may change the memory map.
// These updates are made whilst waiting for the CPLD to retrieve the requested byte.
//
switch(address)
{
default:
break;
}
} else
{
// Determine if this is a memory management port and update the memory page if required.
switch(address & 0x00FF)
{
// 8255 - Port A
case IO_ADDR_E0:
break;
// 8255 - Port B
case IO_ADDR_E1:
break;
// 8255 - Port C
// Bit 3 - L = Reset and enter IPL mode.
// Bit 1 - H = Set memory to normal state and reset cpu, RAM 0x0000:0xFFFF, L = no change.
case IO_ADDR_E2:
if(data & 0x01)
data = 0x03;
else if((data & 0x08) == 0)
data = 0x06;
else
break;
// 8255 - Control Port
// Bit 7 - H = Control word, L 3:1 define port C bit, bit 0 defines its state.
case IO_ADDR_E3:
//pr_info("E3:%02x\n", data);
// Program control register.
if(data & 0x80)
{
// Do nothing, this is the register which sets the 8255 mode.
} else
{
switch((data >> 1) & 0x07)
{
// NST toggle.
case 1:
// NST pages in all RAM and resets cpu.
if(data & 0x01)
{
MZ2000Ctrl.lowMemorySwap = 0;
for(idx=0x0000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(Z80Ctrl->defaultPageMode == USE_PHYSICAL_RAM)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_RAM, idx);
}
else
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
}
//resetZ80();
}
break;
// IPL start.
case 3:
// If IPL is active (L), reconfigure memory for power on state.
if((data & 0x01) == 0)
{
mz2000SetupMemory(Z80Ctrl->defaultPageMode);
}
break;
default:
break;
}
}
break;
// Port A - Z80 PIO, contains control bits affecting memory mapping.
// Bit
// 7 - Assign address range 0xD000:0xFFFF to V-RAM when H, when L assign RAM
// 6 - Character VRAM (H), Graphics VRAM (L)
// 4 - Change screen to 80 Char (H), 40 Char (L)
// NB. When the VRAM is paged in, if Character VRAM is selected, range 0xD000:0xD7FF is VRAM, 0xC000:0xCFFF, 0xE000:0xFFFF is RAM.
case IO_ADDR_E8:
// High memory being assigned to VRAM or reverting?
if(MZ2000Ctrl.highMemoryVRAM && (data & 0x80) == 0)
{
for(idx=0xC000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(Z80Ctrl->defaultPageMode == USE_PHYSICAL_RAM)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_RAM, idx);
} else
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (MZ2000Ctrl.lowMemorySwap ? idx - 0x8000 : idx));
}
}
MZ2000Ctrl.highMemoryVRAM = 0;
} else
// If this is the first activation of the VRAM or the state of it changes, ie. character <-> graphics, then update the memory mapping.
if( (!MZ2000Ctrl.highMemoryVRAM && (data & 0x80) != 0) || (MZ2000Ctrl.highMemoryVRAM && (MZ2000Ctrl.graphicsVRAM >> 6) != (data & 0x40)) )
{
for(idx=0xC000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
// Graphics RAM see's the entire range set to PHYSICAL, Character RAM only see's 0xD000:0xD7FF set to PHYSICAL.
if( ((data & 0x40) && (idx >= 0xD000 && idx < 0xD800)) || ((data & 0x40) == 0) )
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
}
MZ2000Ctrl.highMemoryVRAM = 1;
}
MZ2000Ctrl.graphicsVRAM = (data & 0x040) ? 1 : 0;
break;
// Port is not a memory management port.
default:
break;
}
}
}
// Method to read from either the memory mapped registers if enabled else the RAM.
static inline uint8_t mz2000Read(zuint16 address, uint8_t ioFlag)
{
// Locals.
uint8_t data = 0xFF;
// I/O Operation?
if(ioFlag)
{
switch(address)
{
default:
break;
}
} else
{
switch(address)
{
default:
if(isVirtualMemory(address))
{
// Retrieve data from virtual memory.
data = isVirtualROM(address) ? readVirtualROM(address) : readVirtualRAM(address);
}
break;
}
}
return(data);
}
// Method to handle writes.
static inline void mz2000Write(zuint16 address, zuint8 data, uint8_t ioFlag)
{
// Locals.
// uint32_t idx;
// I/O Operation?
if(ioFlag)
{
switch(address)
{
default:
break;
}
} else
{
switch(address)
{
default:
if(isVirtualRAM(address))
{
// Update virtual memory.
writeVirtualRAM(address, data);
}
}
}
return;
}

View File

@@ -0,0 +1,481 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: z80vhw_mz700.c
// Created: Oct 2022
// Author(s): Philip Smart
// Description: Z80 Virtual Hardware Driver - MZ-700
// This file contains the methods used to emulate the original Sharp MZ-700 without
// any additions, such as the RFS or TZFS boards.
//
// These drivers are intended to be instantiated inline to reduce overhead of a call
// and as such, they are included like header files rather than C linked object files.
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Mar 2023 v1.0 - Initial write based on the RFS hardware module.
// Apr 2023 v1.1 - Updates from the PCW/MZ2000 changes.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/time.h>
#include "z80io.h"
#include <gpio_table.h>
#include <asm/io.h>
#include <infinity2m/gpio.h>
#include <infinity2m/registers.h>
// Device constants.
#define RAM_BASE_ADDR 0x00000 // Base address of the 512K RAM.
// PCW control.
typedef struct {
uint8_t regCtrl; // Control register.
} t_MZ700Ctrl;
// RFS Board control.
static t_MZ700Ctrl MZ700Ctrl;
//-------------------------------------------------------------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------------------------------------------------------------
// Method to setup the memory page config to reflect the PCW configuration.
void mz700SetupMemory(enum Z80_MEMORY_PROFILE mode)
{
// Locals.
uint32_t idx;
// The PCW contains upto 512KB of standard RAM which can be expnded to a physical max of 2MB. The kernel malloc limit is 2MB so the whole virtual
// memory can be mapped into the PCW memory address range.
// Setup defaults.
MZ700Ctrl.regCtrl = 0x00;
// Setup default mode according to run mode, ie. Physical run or Virtual run.
//
if(mode == USE_PHYSICAL_RAM)
{
// Initialise the page pointers and memory to use physical RAM.
for(idx=0x0000; idx < MEMORY_PAGE_SIZE; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_ROM, idx);
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_RAM, idx);
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
}
else if(idx >= 0xE800 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_ROM, idx);
} else
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_RAM, idx);
}
}
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
// Cancel refresh as using physical RAM for program automatically refreshes DRAM.
Z80Ctrl->refreshDRAM = 0;
}
else if(mode == USE_VIRTUAL_RAM)
{
// Initialise the page pointers and memory to use virtual RAM.
for(idx=0x0000; idx < MEMORY_PAGE_SIZE; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0 && idx < 0x1000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_ROM, idx);
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_PHYSICAL_HW, idx);
}
else if(idx >= 0xE800 && idx < 0xF000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_ROM, idx);
}
else if(idx >= 0xF000 && idx < 0x10000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_ROM, idx);
}
}
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
// Enable refresh as using virtual RAM stops refresh of host DRAM.
Z80Ctrl->refreshDRAM = 2;
}
// Reset memory paging to default.
SPI_SEND_32(0x00e4, 0x00 << 8 | CPLD_CMD_WRITEIO_ADDR);
pr_info("MZ-700 Memory Setup complete.\n");
}
// Method to load a ROM image into the RAM memory.
//
uint8_t mz700LoadROM(const char* romFileName, uint32_t loadAddr, uint32_t loadSize)
{
// Locals.
uint8_t result = 0;
long noBytes;
struct file *fp;
fp = filp_open(romFileName, O_RDONLY, 0);
if(IS_ERR(fp))
{
pr_info("Error opening ROM Image:%s\n:", romFileName);
result = 1;
} else
{
vfs_llseek(fp, 0, SEEK_SET);
noBytes = kernel_read(fp, fp->f_pos, &Z80Ctrl->ram[loadAddr], loadSize);
if(noBytes < loadSize)
{
pr_info("Short load, ROM Image:%s, bytes loaded:%08x\n:", romFileName, loadSize);
}
filp_close(fp,NULL);
}
return(result);
}
// Perform any setup operations, such as variable initialisation, to enable use of this module.
void mz700Init(uint8_t mode)
{
// Locals.
uint32_t idx;
// Initialise the virtual RAM from the HOST DRAM. This is to maintain compatibility as some applications (in my experience) have
// bugs, which Im putting down to not initialising variables. The host DRAM is in a pattern of 0x00..0x00, 0xFF..0xFF repeating
// when first powered on.
pr_info("Sync Host RAM to virtual RAM.\n");
for(idx=0; idx < Z80_VIRTUAL_RAM_SIZE; idx++)
{
if(idx >= 0x1000 && idx < 0xD000)
{
SPI_SEND32((uint32_t)idx << 16 | CPLD_CMD_READ_ADDR);
while(CPLD_READY() == 0);
Z80Ctrl->ram[idx] = z80io_PRL_Read8(1);
} else
{
Z80Ctrl->ram[idx] = 0x00;
}
}
// Original mode, ie. no virtual devices active, copy the host BIOS into the Virtual ROM and initialise remainder of ROM memory
// such that the host behaves as per original spec.
pr_info("Sync Host BIOS to virtual ROM.\n");
for(idx=0; idx < Z80_VIRTUAL_ROM_SIZE; idx++)
{
// Copy BIOS and any add-on ROMS.
if((idx >= 0x0000 && idx < 0x1000) || (idx >= 0xE800 && idx < 0x10000))
{
SPI_SEND32((uint32_t)idx << 16 | CPLD_CMD_READ_ADDR);
while(CPLD_READY() == 0);
Z80Ctrl->rom[idx] = z80io_PRL_Read8(1);
} else
{
Z80Ctrl->rom[idx] = 0x00;
}
}
// Add in a test program to guage execution speed.
#if(TARGET_HOST_MZ700 == 1)
Z80Ctrl->ram[0x1200] = 0x01;
Z80Ctrl->ram[0x1201] = 0x86;
Z80Ctrl->ram[0x1202] = 0xf2;
Z80Ctrl->ram[0x1203] = 0x3e;
Z80Ctrl->ram[0x1204] = 0x15;
Z80Ctrl->ram[0x1205] = 0x3d;
Z80Ctrl->ram[0x1206] = 0x20;
Z80Ctrl->ram[0x1207] = 0xfd;
Z80Ctrl->ram[0x1208] = 0x0b;
Z80Ctrl->ram[0x1209] = 0x78;
Z80Ctrl->ram[0x120a] = 0xb1;
Z80Ctrl->ram[0x120b] = 0x20;
Z80Ctrl->ram[0x120c] = 0xf6;
Z80Ctrl->ram[0x120d] = 0xc3;
Z80Ctrl->ram[0x120e] = 0x00;
Z80Ctrl->ram[0x120f] = 0x00;
#endif
// Reset memory paging to default.
SPI_SEND_32(0x00e4, 0x00 << 8 | CPLD_CMD_WRITEIO_ADDR);
pr_info("Enabling MZ-700 driver.\n");
return;
}
// Perform any de-initialisation when the driver is removed.
void mz700Remove(void)
{
pr_info("Removing MZ-700 driver.\n");
return;
}
// Method to decode an address and make any system memory map changes as required.
//
static inline void mz700DecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t ioFlag, uint8_t readFlag)
{
// Locals.
uint32_t idx;
// Decoding memory address or I/O address?
if(ioFlag == 0)
{
// #if(DEBUG_ENABLED & 1)
// if(Z80Ctrl->debug >= 2)
// {
// pr_info("MEM:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
// }
// #endif
// Certain machines have memory mapped I/O, these need to be handled in-situ as some reads may change the memory map.
// These updates are made whilst waiting for the CPLD to retrieve the requested byte.
//
// 0000 - 0FFF : MZ80K/A/700 = Monitor ROM or RAM (MZ80A rom swap)
// 1000 - CFFF : MZ80K/A/700 = RAM
// C000 - CFFF : MZ80A = Monitor ROM (MZ80A rom swap)
// D000 - D7FF : MZ80K/A/700 = VRAM
// D800 - DFFF : MZ700 = Colour VRAM (MZ700)
// E000 - E003 : MZ80K/A/700 = 8255
// E004 - E007 : MZ80K/A/700 = 8254
// E008 - E00B : MZ80K/A/700 = LS367
// E00C - E00F : MZ80A = Memory Swap (MZ80A)
// E010 - E013 : MZ80A = Reset Memory Swap (MZ80A)
// E014 : MZ80A/700 = Normat CRT display
// E015 : MZ80A/700 = Reverse CRT display
// E200 - E2FF : MZ80A/700 = VRAM roll up/roll down.
// E800 - EFFF : MZ80K/A/700 = User ROM socket or DD Eprom (MZ700)
// F000 - F7FF : MZ80K/A/700 = Floppy Disk interface.
// F800 - FFFF : MZ80K/A/700 = Floppy Disk interface.
switch(address)
{
default:
break;
}
} else
{
// #if(DEBUG_ENABLED & 1)
// if(Z80Ctrl->debug >= 2)
// {
// pr_info("IO:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
// }
// #endif
// Determine if this is a memory management port and update the memory page if required.
switch(address & 0x00FF)
{
// MZ700 memory mode switch.
//
// MZ-700
// |0000:0FFF|1000:CFFF|D000:FFFF
// ------------------------------
// OUT 0xE0 = |DRAM | |
// OUT 0xE1 = | | |DRAM
// OUT 0xE2 = |MONITOR | |
// OUT 0xE3 = | | |Memory Mapped I/O
// OUT 0xE4 = |MONITOR |DRAM |Memory Mapped I/O
// OUT 0xE5 = | | |Inhibit
// OUT 0xE6 = | | |<return>
//
// <return> = Return to the state prior to the complimentary command being invoked.
// Enable lower 4K block as DRAM
case IO_ADDR_E0:
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
break;
// Enable upper 12K block, including Video/Memory Mapped peripherals area, as DRAM.
case IO_ADDR_E1:
if(!Z80Ctrl->inhibitMode)
{
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
// MZ-700 mode we only work in first 64K block.
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
}
break;
// Enable MOnitor ROM in lower 4K block
case IO_ADDR_E2:
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
}
break;
// Enable Video RAM and Memory mapped peripherals in upper 12K block.
case IO_ADDR_E3:
if(!Z80Ctrl->inhibitMode)
{
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
}
}
break;
// Reset to power on condition memory map.
case IO_ADDR_E4:
// Lower 4K set to Monitor ROM.
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
}
if(!Z80Ctrl->inhibitMode)
{
// Upper 12K to hardware.
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
}
}
break;
// Inhibit. Backup current page data in region 0xD000-0xFFFF and inhibit it.
case IO_ADDR_E5:
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
backupMemoryType(idx/MEMORY_BLOCK_GRANULARITY);
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_INHIBIT, idx);
}
Z80Ctrl->inhibitMode = 1;
break;
// Restore D000-FFFF to its original state.
case IO_ADDR_E6:
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
restoreMemoryType(idx/MEMORY_BLOCK_GRANULARITY);
}
Z80Ctrl->inhibitMode = 0;
break;
// Port is not a memory management port.
default:
break;
}
}
}
// Method to read from either the memory mapped registers if enabled else the RAM.
static inline uint8_t mz700Read(zuint16 address, uint8_t ioFlag)
{
// Locals.
uint8_t data = 0xFF;
// I/O Operation?
if(ioFlag)
{
switch(address)
{
default:
break;
}
} else
{
switch(address)
{
default:
if(isVirtualMemory(address))
{
// Retrieve data from virtual memory.
data = isVirtualROM(address) ? readVirtualROM(address) : readVirtualRAM(address);
}
break;
}
}
return(data);
}
// Method to handle writes.
static inline void mz700Write(zuint16 address, zuint8 data, uint8_t ioFlag)
{
// Locals.
// uint32_t idx;
// I/O Operation?
if(ioFlag)
{
switch(address)
{
default:
break;
}
} else
{
switch(address)
{
default:
if(isVirtualRAM(address))
{
// Update virtual memory.
writeVirtualRAM(address, data);
}
}
}
return;
}

View File

@@ -0,0 +1,382 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: z80vhw_mz80a.c
// Created: Oct 2022
// Author(s): Philip Smart
// Description: Z80 Virtual Hardware Driver - MZ-80A
// This file contains the methods used to emulate the original Sharp MZ-80A without
// any additions, such as the RFS or TZFS boards.
//
// These drivers are intended to be instantiated inline to reduce overhead of a call
// and as such, they are included like header files rather than C linked object files.
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Mar 2023 v1.0 - Initial write based on the RFS hardware module.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/time.h>
#include "z80io.h"
#include <gpio_table.h>
#include <asm/io.h>
#include <infinity2m/gpio.h>
#include <infinity2m/registers.h>
// Device constants.
#define RAM_BASE_ADDR 0x00000 // Base address of the 512K RAM.
// 40/80 Video Module control registers.
//
#define DSPCTL 0xDFFF // Display 40/80 select register (bit 7)
// PCW control.
typedef struct {
// MZ-80A can relocate the lower 4K ROM by swapping RAM at 0xC000.
uint8_t memSwitch;
uint8_t regCtrl; // Control register.
} t_MZ80ACtrl;
// RFS Board control.
static t_MZ80ACtrl MZ80ACtrl;
//-------------------------------------------------------------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------------------------------------------------------------
// Method to setup the memory page config to reflect the PCW configuration.
void mz80aSetupMemory(enum Z80_MEMORY_PROFILE mode)
{
// Locals.
uint32_t idx;
// Setup defaults.
MZ80ACtrl.memSwitch = 0x00;
MZ80ACtrl.regCtrl = 0x00;
// Setup default mode according to run mode, ie. Physical run or Virtual run.
//
if(mode == USE_PHYSICAL_RAM)
{
// Initialise the page pointers and memory to use physical RAM.
for(idx=0x0000; idx < MEMORY_PAGE_SIZE; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_ROM, idx);
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_RAM, idx);
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
}
else if(idx >= 0xE800 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_ROM, idx);
} else
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_RAM, idx);
}
}
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
// Cancel refresh as using physical RAM for program automatically refreshes DRAM.
Z80Ctrl->refreshDRAM = 0;
}
else if(mode == USE_VIRTUAL_RAM)
{
// Initialise the page pointers and memory to use virtual RAM.
for(idx=0x0000; idx < MEMORY_PAGE_SIZE; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0 && idx < 0x1000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_ROM, idx);
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_PHYSICAL_HW, idx);
}
else if(idx >= 0xE800 && idx < 0xF000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_HW, idx);
}
else if(idx >= 0xF000 && idx < 0x10000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_ROM, idx);
}
}
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
// Enable refresh as using virtual RAM stops refresh of host DRAM.
Z80Ctrl->refreshDRAM = 2;
}
// Original mode, ie. no virtual devices active, copy the host BIOS into the Virtual ROM and initialise remainder of ROM memory
// such that the host behaves as per original spec.
pr_info("Sync Host BIOS to virtual ROM.\n");
for(idx=0; idx < Z80_VIRTUAL_ROM_SIZE; idx++)
{
if((idx >= 0x0000 && idx < 0x1000) || (idx >= 0xF000 && idx < 0x10000))
{
SPI_SEND32((uint32_t)idx << 16 | CPLD_CMD_READ_ADDR);
while(CPLD_READY() == 0);
Z80Ctrl->rom[idx] = z80io_PRL_Read8(1);
} else
{
Z80Ctrl->rom[idx] = 0x00;
}
}
pr_info("MZ-80A Memory Setup complete.\n");
}
// Method to load a ROM image into the RAM memory.
//
uint8_t mz80aLoadROM(const char* romFileName, uint32_t loadAddr, uint32_t loadSize)
{
// Locals.
uint8_t result = 0;
long noBytes;
struct file *fp;
fp = filp_open(romFileName, O_RDONLY, 0);
if(IS_ERR(fp))
{
pr_info("Error opening ROM Image:%s\n:", romFileName);
result = 1;
} else
{
vfs_llseek(fp, 0, SEEK_SET);
noBytes = kernel_read(fp, fp->f_pos, &Z80Ctrl->ram[loadAddr], loadSize);
if(noBytes < loadSize)
{
pr_info("Short load, ROM Image:%s, bytes loaded:%08x\n:", romFileName, loadSize);
}
filp_close(fp,NULL);
}
return(result);
}
// Perform any setup operations, such as variable initialisation, to enable use of this module.
void mz80aInit(uint8_t mode)
{
// Locals.
uint32_t idx;
// Initialise the virtual RAM from the HOST DRAM. This is to maintain compatibility as some applications (in my experience) have
// bugs, which Im putting down to not initialising variables. The host DRAM is in a pattern of 0x00..0x00, 0xFF..0xFF repeating
// when first powered on.
pr_info("Sync Host RAM to virtual RAM.\n");
for(idx=0; idx < Z80_VIRTUAL_RAM_SIZE; idx++)
{
if(idx >= 0x1000 && idx < 0xD000)
{
SPI_SEND32((uint32_t)idx << 16 | CPLD_CMD_READ_ADDR);
while(CPLD_READY() == 0);
Z80Ctrl->ram[idx] = z80io_PRL_Read8(1);
} else
{
Z80Ctrl->ram[idx] = 0x00;
}
}
MZ80ACtrl.memSwitch = 0;
// If the 40/80 Video Module board is installed, ensure 40 character mode is selected.
SPI_SEND_32(DSPCTL, CPLD_CMD_READ_ADDR);
while(CPLD_READY() == 0);
SPI_SEND_32(DSPCTL, CPLD_CMD_WRITE_ADDR);
pr_info("Enabling MZ-80A driver.\n");
return;
}
// Perform any de-initialisation when the driver is removed.
void mz80aRemove(void)
{
pr_info("Removing MZ-80A driver.\n");
return;
}
// Method to decode an address and make any system memory map changes as required.
//
static inline void mz80aDecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t ioFlag, uint8_t readFlag)
{
// Locals.
uint32_t idx;
// Decoding memory address or I/O address?
if(ioFlag == 0)
{
// Certain machines have memory mapped I/O, these need to be handled in-situ as some reads may change the memory map.
// These updates are made whilst waiting for the CPLD to retrieve the requested byte.
//
// 0000 - 0FFF : MZ80K/A/700 = Monitor ROM or RAM (MZ80A rom swap)
// 1000 - CFFF : MZ80K/A/700 = RAM
// C000 - CFFF : MZ80A = Monitor ROM (MZ80A rom swap)
// D000 - D7FF : MZ80K/A/700 = VRAM
// D800 - DFFF : MZ700 = Colour VRAM (MZ700)
// E000 - E003 : MZ80K/A/700 = 8255
// E004 - E007 : MZ80K/A/700 = 8254
// E008 - E00B : MZ80K/A/700 = LS367
// E00C - E00F : MZ80A = Memory Swap (MZ80A)
// E010 - E013 : MZ80A = Reset Memory Swap (MZ80A)
// E014 : MZ80A/700 = Normat CRT display
// E015 : MZ80A/700 = Reverse CRT display
// E200 - E2FF : MZ80A/700 = VRAM roll up/roll down.
// E800 - EFFF : MZ80K/A/700 = User ROM socket or DD Eprom (MZ700)
// F000 - F7FF : MZ80K/A/700 = Floppy Disk interface.
// F800 - FFFF : MZ80K/A/700 = Floppy Disk interface.
switch(address)
{
// Memory map switch.
case 0xE00C: case 0xE00D: case 0xE00E: case 0xE00F:
if(readFlag)
{
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (0xC000+idx));
setMemoryType((idx+0xC000)/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
}
}
MZ80ACtrl.memSwitch = 1;
break;
// Reset memory map switch.
case 0xE010: case 0xE011: case 0xE012: case 0xE013:
if(readFlag)
{
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
setMemoryType((idx+0xC000)/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (idx+0xC000));
}
}
MZ80ACtrl.memSwitch = 0;
break;
default:
break;
}
} else
{
// Determine if this is a memory management port and update the memory page if required.
switch(address & 0x00FF)
{
// Port is not a memory management port.
default:
break;
}
}
}
// Method to read from either the memory mapped registers if enabled else the RAM.
static inline uint8_t mz80aRead(zuint16 address, uint8_t ioFlag)
{
// Locals.
uint8_t data = 0xFF;
// I/O Operation?
if(ioFlag)
{
switch(address)
{
default:
break;
}
} else
{
switch(address)
{
default:
if(isVirtualMemory(address))
{
// Retrieve data from virtual memory.
data = isVirtualROM(address) ? readVirtualROM(address) : readVirtualRAM(address);
}
break;
}
}
return(data);
}
// Method to handle writes.
static inline void mz80aWrite(zuint16 address, zuint8 data, uint8_t ioFlag)
{
// Locals.
// uint32_t idx;
// I/O Operation?
if(ioFlag)
{
switch(address)
{
default:
break;
}
} else
{
switch(address)
{
default:
if(isVirtualRAM(address))
{
// Update virtual memory.
writeVirtualRAM(address, data);
}
}
}
return;
}

View File

@@ -0,0 +1,379 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: z80vhw_pcw.c
// Created: Oct 2022
// Author(s): Philip Smart
// Description: Z80 Virtual Hardware Driver - Amstrad PCW-8xxx/PCW-9xxx
// This file contains the methods used to emulate the Amstrad PCW specific
// hardware.
//
// These drivers are intended to be instantiated inline to reduce overhead of a call
// and as such, they are included like header files rather than C linked object files.
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Mar 2023 v1.0 - Initial write based on the RFS hardware module.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/time.h>
#include "z80io.h"
#include <gpio_table.h>
#include <asm/io.h>
#include <infinity2m/gpio.h>
#include <infinity2m/registers.h>
// Device constants.
#define RAM_BASE_ADDR 0x00000 // Base address of the 512K RAM.
// IO Ports.
#define IO_FDC_STATUS 0x00 // NEC765 FDC Status Register.
#define IO_FDC_DATA 0x01 // NEC765 FDC Data Register.
#define IO_MEMBNK0 0xF0 // Memory bank 0000:3FFF register.
#define IO_MEMBNK1 0xF1 // Memory bank 4000:7FFF register.
#define IO_MEMBNK2 0xF2 // Memory bank 8000:BFFF register.
#define IO_MEMBNK3 0xF3 // Memory bank C000:FFFF register.
#define IO_MEMLOCK 0xF4 // CPC mode memory lock range.
#define IO_ROLLERRAM 0xF5 // Set the Roller RAM address.
#define IO_VORIGIN 0xF6 // Set screen vertical origin.
#define IO_SCREENATTR 0xF7 // Set screen attributes.
#define IO_GACMD 0xF8 // Gatearray command register.
#define IO_GASTATUS 0xF8 // Gatearray status register.
// The boot code for the PCW-8256 is located within the printer controller. To avoid special hardware within the CPLD, this code is incorporated
// into this module for rapid loading into RAM.
#define ROM_DIR "/apps/FusionX/host/PCW/roms/"
#define ROM_PCW8_BOOT_FILENAME ROM_DIR "PCW8256_boot.bin"
#define ROM_PCW9_BOOT_FILENAME ROM_DIR "PCW9256_boot.bin"
// Boot ROM rom load and size definitions.
#define ROM_BOOT_LOAD_ADDR 0x000000
#define ROM_BOOT_SIZE 275
// PCW control.
typedef struct {
uint8_t regMemBank0; // Mirror of register F0, memory block select 0x0000-0x3FFF.
uint8_t regMemBank1; // Mirror of register F1, memory block select 0x4000-0x7FFF.
uint8_t regMemBank2; // Mirror of register F2, memory block select 0x8000-0xBFFF.
uint8_t regMemBank3; // Mirror of register F3, memory block select 0xC000-0xFFFF.
uint8_t regCPCPageMode; // Mirror of the CPC paging lock register F4.
uint8_t regRollerRAM; // Mirror of Roller-RAM address register.
uint8_t regCtrl; // Control register.
} t_PCWCtrl;
// RFS Board control.
static t_PCWCtrl PCWCtrl;
//-------------------------------------------------------------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------------------------------------------------------------
// Method to setup the memory page config to reflect the PCW configuration.
void pcwSetupMemory(enum Z80_MEMORY_PROFILE mode)
{
// Locals.
uint32_t idx;
// The PCW contains upto 512KB of standard RAM which can be expnded to a physical max of 2MB. The kernel malloc limit is 2MB so the whole virtual
// memory can be mapped into the PCW memory address range.
// Setup defaults.
PCWCtrl.regMemBank0 = 0x00;
PCWCtrl.regMemBank1 = 0x01;
PCWCtrl.regMemBank2 = 0x02;
PCWCtrl.regMemBank3 = 0x03; // Keyboard is in locations 0x3FF0 - 0x3FFF of this memory block.
PCWCtrl.regCPCPageMode = 0x00;
PCWCtrl.regRollerRAM = 0x00;
PCWCtrl.regCtrl = 0x00;
// Initialise the page pointers and memory to reflect a PCW, lower 128K is used by video logic so must always be accessed in hardware.
for(idx=0x0000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0x0000 && idx < 0xFFF0)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_RAM_WT, (RAM_BASE_ADDR+idx));
}
if(idx >= 0xFFF0 && idx < 0x10000)
{
// The keyboard is memory mapped into upper bytes of block 3.
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, (RAM_BASE_ADDR+idx));
}
}
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
// Enable refresh as using virtual RAM stops refresh of host DRAM.
Z80Ctrl->refreshDRAM = 2;
// No I/O Ports on the RFS board.
pr_info("PCW Memory Setup complete.\n");
}
// Method to load a ROM image into the RAM memory.
//
uint8_t loadROM(const char* romFileName, uint32_t loadAddr, uint32_t loadSize)
{
// Locals.
uint8_t result = 0;
long noBytes;
struct file *fp;
fp = filp_open(romFileName, O_RDONLY, 0);
if(IS_ERR(fp))
{
pr_info("Error opening ROM Image:%s\n:", romFileName);
result = 1;
} else
{
vfs_llseek(fp, 0, SEEK_SET);
noBytes = kernel_read(fp, fp->f_pos, &Z80Ctrl->ram[loadAddr], loadSize);
if(noBytes < loadSize)
{
pr_info("Short load, ROM Image:%s, bytes loaded:%08x\n:", romFileName, loadSize);
}
filp_close(fp,NULL);
}
return(result);
}
// Perform any setup operations, such as variable initialisation, to enable use of this module.
void pcwInit(uint8_t mode)
{
// Locals.
//
uint32_t idx;
// Clear memory as previous use or malloc can leave it randomly set.
for(idx=0; idx < Z80_VIRTUAL_RAM_SIZE; idx++)
{
Z80Ctrl->ram[idx] = 0x00;
}
// Disable boot mode, we dont need to fetch the boot rom as we preload it.
SPI_SEND32( (0x00F8 << 16) | (0x00 << 8) | CPLD_CMD_WRITEIO_ADDR);
// Load boot ROM.
loadROM(mode == 0 ? ROM_PCW8_BOOT_FILENAME : ROM_PCW9_BOOT_FILENAME, ROM_BOOT_LOAD_ADDR, ROM_BOOT_SIZE);
// Reset.
//SPI_SEND32( (0x00F8 << 16) | (0x01 << 8) | CPLD_CMD_WRITEIO_ADDR);
// First two bytes to NULL as were not using the bootstrap and normal operations after bootstrap would disable the mode.
Z80Ctrl->ram[0] = 0x00;
Z80Ctrl->ram[1] = 0x00;
pr_info("Enabling PCW-%s driver.\n", mode == 0 ? "8256" : "9256");
return;
}
// Perform any de-initialisation when the driver is removed.
void pcwRemove(void)
{
pr_info("Removing PCW driver.\n");
return;
}
// Method to decode an address and make any system memory map changes as required.
//
static inline void pcwDecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t ioFlag, uint8_t readFlag)
{
// Locals.
uint32_t idx;
// IO Switch.
if(ioFlag)
{
switch(address&0xff)
{
case IO_FDC_STATUS:
//pr_info("FDC_STATUS:%02x\n", data);
break;
case IO_FDC_DATA:
//pr_info("FDC_DATA:%02x\n", data);
break;
case IO_MEMBNK0:
if(!readFlag)
{
PCWCtrl.regMemBank0 = (data & 0x80) ? data & 0x7f : PCWCtrl.regMemBank0;
pr_info("Setting Bank 0:%02x\n", PCWCtrl.regMemBank0);
for(idx=0x0000; idx < 0x4000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType((idx+0x0000)/MEMORY_BLOCK_GRANULARITY, PCWCtrl.regMemBank0 >= 8 ? MEMORY_TYPE_VIRTUAL_RAM : MEMORY_TYPE_PHYSICAL_RAM_WT, (RAM_BASE_ADDR+(PCWCtrl.regMemBank0*16384)+idx));
}
}
break;
case IO_MEMBNK1:
if(!readFlag)
{
PCWCtrl.regMemBank1 = (data & 0x80) ? data & 0x7f : PCWCtrl.regMemBank1;
pr_info("Setting Bank 1:%02x\n", PCWCtrl.regMemBank1);
for(idx=0x0000; idx < 0x4000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType((idx+0x4000)/MEMORY_BLOCK_GRANULARITY, PCWCtrl.regMemBank1 >= 8 ? MEMORY_TYPE_VIRTUAL_RAM : MEMORY_TYPE_PHYSICAL_RAM_WT, (RAM_BASE_ADDR+(PCWCtrl.regMemBank1*16384)+idx));
}
}
break;
case IO_MEMBNK2:
if(!readFlag)
{
PCWCtrl.regMemBank2 = (data & 0x80) ? data & 0x7f : PCWCtrl.regMemBank2;
pr_info("Setting Bank 2:%02x\n", PCWCtrl.regMemBank2);
for(idx=0x0000; idx < 0x4000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType((idx+0x8000)/MEMORY_BLOCK_GRANULARITY, PCWCtrl.regMemBank2 >= 8 ? MEMORY_TYPE_VIRTUAL_RAM : MEMORY_TYPE_PHYSICAL_RAM_WT, (RAM_BASE_ADDR+(PCWCtrl.regMemBank2*16384)+idx));
}
}
break;
case IO_MEMBNK3:
if(!readFlag)
{
PCWCtrl.regMemBank3 = (data & 0x80) ? data & 0x7f : PCWCtrl.regMemBank3;
pr_info("Setting Bank 3:%02x\n", PCWCtrl.regMemBank3);
for(idx=0x0000; idx < 0x4000; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx < 0x3FF0)
setMemoryType((idx+0xC000)/MEMORY_BLOCK_GRANULARITY, PCWCtrl.regMemBank3 >= 8 ? MEMORY_TYPE_VIRTUAL_RAM : MEMORY_TYPE_PHYSICAL_RAM_WT, (RAM_BASE_ADDR+(PCWCtrl.regMemBank3*16384)+idx));
}
}
break;
case IO_MEMLOCK:
if(!readFlag)
{
pr_info("MEMLOCK:%02x\n", data);
PCWCtrl.regCPCPageMode = data;
}
break;
case IO_ROLLERRAM:
if(!readFlag)
{
pr_info("********RollerRAM********:%02x => %04x\n", data, (((data >> 5)&0x7) * 16384)+((data&0x1f)*512));
PCWCtrl.regRollerRAM = data;
}
break;
case IO_VORIGIN:
pr_info("VORIGIN:%02x\n", data);
break;
case IO_SCREENATTR:
pr_info("SCREENATTR:%02x\n", data);
break;
case IO_GACMD:
pr_info("GACMD:%02x\n", data);
break;
default:
pr_info("Unknown:ADDR:%02x,%02x\n", address&0xff, data);
break;
}
} else
// Memory map switch.
{
switch(address)
{
default:
break;
}
}
}
// Method to read from either the memory mapped registers if enabled else the RAM.
static inline uint8_t pcwRead(zuint16 address, uint8_t ioFlag)
{
// Locals.
uint8_t data = 0xFF;
// I/O Operation?
if(ioFlag)
{
switch(address)
{
default:
break;
}
} else
{
switch(address)
{
default:
// Return the contents of the ROM at given address.
data = isVirtualROM(address) ? readVirtualROM(address) : readVirtualRAM(address);
break;
}
}
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug >= 3) pr_info("PCW-Read:%04x, BK0:%02x, BK1:%02x, BK2:%02x, BK3:%02x, CTRL:%02x\n", address, PCWCtrl.regMemBank0, PCWCtrl.regMemBank1, PCWCtrl.regMemBank2, PCWCtrl.regMemBank3, PCWCtrl.regCtrl);
#endif
return(data);
}
// Method to handle writes.
static inline void pcwWrite(zuint16 address, zuint8 data, uint8_t ioFlag)
{
// Locals.
// uint32_t idx;
// I/O Operation?
if(ioFlag)
{
switch(address)
{
default:
break;
}
} else
{
switch(address)
{
default:
// Any unprocessed write is commited to RAM.
writeVirtualRAM(address, data);
break;
}
}
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug >= 3) pr_info("PCW-Write:%04x, BK0:%02x, BK1:%02x, BK2:%02x, BK3:%02x, CTRL:%02x\n", address, PCWCtrl.regMemBank0, PCWCtrl.regMemBank1, PCWCtrl.regMemBank2, PCWCtrl.regMemBank3, PCWCtrl.regCtrl);
#endif
return;
}

View File

@@ -0,0 +1,836 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: z80vhw_rfs.c.c
// Created: Oct 2022
// Author(s): Philip Smart
// Description: Z80 Virtual Hardware Driver - Rom Filing System (RFS)
// This file contains the methods used to emulate the Rom Filing System add on for the
// MZ-80A.
//
// These drivers are intended to be instantiated inline to reduce overhead of a call
// and as such, they are included like header files rather than C linked object files.
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Feb 2023 v1.0 - Initial write based on the RFS hardware.
// v1.1 - Bug fix, write logic was one byte out of kinter.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/time.h>
#include "z80io.h"
#include <gpio_table.h>
#include <asm/io.h>
#include <infinity2m/gpio.h>
#include <infinity2m/registers.h>
// Device constants.
#define MROM_ADDR 0x00000 // Base address of the 512K Monitor ROM.
#define USER_ROM_I_ADDR 0x80000 // Base address of the first 512K User ROM.
#define USER_ROM_II_ADDR 0x100000 // Base address of the second 512K User ROM.
#define USER_ROM_III_ADDR 0x180000 // Base address of the third 512K User ROM.
// RFS Control Registers.
#define BNKCTRLRST 0xEFF8 // Bank control reset, returns all registers to power up default.
#define BNKCTRLDIS 0xEFF9 // Disable bank control registers by resetting the coded latch.
#define HWSPIDATA 0xEFFB // Hardware SPI Data register (read/write).
#define HWSPISTART 0xEFFC // Start an SPI transfer.
#define BNKSELMROM 0xEFFD // Select RFS Bank1 (MROM)
#define BNKSELUSER 0xEFFE // Select RFS Bank2 (User ROM)
#define BNKCTRL 0xEFFF // Bank Control register (read/write).
// 40/80 Video Module control registers.
//
#define DSPCTL 0xDFFF // Display 40/80 select register (bit 7)
//
// RFS v2 Control Register constants.
//
#define BBCLK 1 // BitBang SPI Clock.
#define SDCS 2 // SD Card Chip Select, active low.
#define BBMOSI 4 // BitBang MOSI (Master Out Serial In).
#define CDLTCH1 8 // Coded latch up count bit 1
#define CDLTCH2 16 // Coded latch up count bit 2
#define CDLTCH3 32 // Coded latch up count bit 3
#define BK2A19 64 // User ROM Device Select Bit 0 (or Address bit 19).
#define BK2A20 128 // User ROM Device Select Bit 1 (or Address bit 20).
// BK2A20 : BK2A19
// 0 0 = Flash RAM 0 (default).
// 0 1 = Flash RAM 1.
// 1 0 = Flasm RAM 2 or Static RAM 0.
// 1 1 = Reserved.`
#define BNKCTRLDEF BBMOSI+SDCS+BBCLK // Default on startup for the Bank Control register.
// RFS Board ROM rom filename definitions.
#if(TARGET_HOST_MZ80A == 1)
#define ROM_DIR "/apps/FusionX/host/MZ-80A/RFS/"
#elif(TARGET_HOST_MZ700 == 1)
#define ROM_DIR "/apps/FusionX/host/MZ-700/RFS/"
#else
#error "Unknown host configured."
#endif
#define ROM_MROM_40C_FILENAME ROM_DIR "MROM_256_40c.bin"
#define ROM_USER_I_40C_FILENAME ROM_DIR "USER_ROM_256_40c.bin"
#define ROM_USER_II_40C_FILENAME ROM_DIR "USER_ROM_II_256_40c.bin"
#define ROM_USER_III_40C_FILENAME ROM_DIR "USER_ROM_III_256_40c.bin"
#define ROM_MROM_80C_FILENAME ROM_DIR "MROM_256_80c.bin"
#define ROM_USER_I_80C_FILENAME ROM_DIR "USER_ROM_256_80c.bin"
#define ROM_USER_II_80C_FILENAME ROM_DIR "USER_ROM_II_256_80c.bin"
#define ROM_USER_III_80C_FILENAME ROM_DIR "USER_ROM_III_256_80c.bin"
// RFS Board ROM rom load and size definitions.
#define ROM_MROM_LOAD_ADDR 0x000000
#define ROM_USER_I_LOAD_ADDR 0x080000
#define ROM_USER_II_LOAD_ADDR 0x100000
#define ROM_USER_III_LOAD_ADDR 0x180000
#define ROM_MROM_SIZE 0x80000
#define ROM_USER_I_SIZE 0x80000
#define ROM_USER_II_SIZE 0x80000
#define ROM_USER_III_SIZE 0x80000
// SD Drive constants.
#define SD_DIR "/apps/FusionX/host/MZ-80A/RFS/"
#define SD_CARD_FILENAME SD_DIR "SHARP_MZ80A_RFS_CPM_IMAGE_1.img"// SD Card Binary Image.
// MMC/SD command (SPI mode)
#define CMD0 0x40 + 0 // GO_IDLE_STATE
#define CMD1 0x40 + 1 // SEND_OP_COND
#define ACMD41 0x40 + 41 // SEND_OP_COND (SDC)
#define CMD8 0x40 + 8 // SEND_IF_COND
#define CMD9 0x40 + 9 // SEND_CSD
#define CMD10 0x40 + 10 // SEND_CID
#define CMD12 0x40 + 12 // STOP_TRANSMISSION
#define CMD13 0x40 + 13 // SEND_STATUS
#define ACMD13 0x40 + 13 // SD_STATUS (SDC)
#define CMD16 0x40 + 16 // SET_BLOCKLEN
#define CMD17 0x40 + 17 // READ_SINGLE_BLOCK
#define CMD18 0x40 + 18 // READ_MULTIPLE_BLOCK
#define CMD23 0x40 + 23 // SET_BLOCK_COUNT
#define ACMD23 0x40 + 23 // SET_WR_BLK_ERASE_COUNT (SDC)
#define CMD24 0x40 + 24 // WRITE_BLOCK
#define CMD25 0x40 + 25 // WRITE_MULTIPLE_BLOCK
#define CMD32 0x40 + 32 // ERASE_ER_BLK_START
#define CMD33 0x40 + 33 // ERASE_ER_BLK_END
#define CMD38 0x40 + 38 // ERASE
#define CMD55 0x40 + 55 // APP_CMD
#define CMD58 0x40 + 58 // READ_OCR
#define SD_SECSIZE 512 // Default size of an SD Sector
#define SD_RETRIES 0x0100 // Number of retries before giving up.
// Card type flags (CardType)
#define CT_MMC 0x01 // MMC ver 3
#define CT_SD1 0x02 // SD ver 1
#define CT_SD2 0x04 // SD ver 2
#define CT_SDC CT_SD1|CT_SD2 // SD
#define CT_BLOCK 0x08 // Block addressing
// SD Card control variables.
typedef struct {
uint8_t trainingCnt; // Count of training bits to indicate card being initialised.
uint8_t initialised; // Flag to indicate the SD card has been initialised.
uint8_t writeFlag; // Flag to indicate an SD Write is taking place, assembling data prior to file write.
uint8_t cmdBuf[6+SD_SECSIZE]; // SD Command Input Buffer.
uint16_t rcvCntr; // SD Received byte counter.
uint8_t const *respBuf; // SD Response buffer.
uint16_t respCntr; // SD Response buffer counter.
uint16_t respLen; // SD size of data in response buffer.
struct file *fhandle; // Filehandle for the SD card image.
uint8_t regDataIn; // SD Card data in (from virtual card) register.
uint8_t regDataOut; // SD Card data out (to virtual card) register.
uint8_t dataOutFlag; // Flag to indicate data written to the SPI.
} t_SDCtrl;
// RFS Board registers.
typedef struct {
uint8_t regBank1; // Bank 1, MROM, bank select register.
uint8_t regBank2; // Bank 2, UROM, bank select register.
uint8_t regCtrl; // Control register.
uint8_t upCntr; // Register enable up counter.
uint32_t mromAddr; // Actual address in MROM of active bank.
uint32_t uromAddr; // Actual address in UROM of active bank.
uint8_t memSwitch; // MZ-80A can relocate the lower 4K ROM by swapping RAM at 0xC000.
t_SDCtrl sd; // SD Control.
} t_RFSCtrl;
// RFS Board control.
static t_RFSCtrl RFSCtrl;
//-------------------------------------------------------------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------------------------------------------------------------
// Method to setup the memory page config to reflect installation of an RFS Board.
void rfsSetupMemory(enum Z80_MEMORY_PROFILE mode)
{
// Locals.
uint32_t idx;
// The RFS Board occupies the MROM slot 0x0000:0x0FFF and the User ROM slot 0xE800:0xEFFF. The actual part of the ROM which appears in these windows
// is controlled by the REG_BANK1 (MROM) and REG_BANK2 (UROM) registers with the upper UROM registers provided in REG_CTRL.
// So on initial setup, map the MROM page to point to the Z80 ROM area 0x00000 which is the base of the first 512K Flash ROM (virtual).
// Setup defaults.
RFSCtrl.regBank1 = 0x00;
RFSCtrl.regBank2 = 0x00;
RFSCtrl.regCtrl = 0x00;
RFSCtrl.mromAddr = MROM_ADDR;
RFSCtrl.uromAddr = USER_ROM_I_ADDR;
RFSCtrl.memSwitch = 0;
RFSCtrl.sd.trainingCnt = 0;
RFSCtrl.sd.initialised = 0;
RFSCtrl.sd.dataOutFlag = 0;
RFSCtrl.sd.rcvCntr = 0;
RFSCtrl.sd.writeFlag = 0;
RFSCtrl.sd.respCntr = 0;
RFSCtrl.sd.respLen = 0;
RFSCtrl.sd.fhandle = NULL;
// Setup the initial state of the latch up-counter, used to enable access to the programmable registers.
RFSCtrl.upCntr = ((RFSCtrl.regCtrl & 0x20) >> 2) | ((RFSCtrl.regCtrl & 0x10) >> 2) | ((RFSCtrl.regCtrl & 0x08) >> 2);
// Initialise the page pointers and memory to reflect an MZ-80A with an RFS board installed.
for(idx=0x0000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0x0000 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, (RFSCtrl.mromAddr+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_PHYSICAL_HW, idx);
}
else if(idx >= 0xE800 && idx < 0xF000)
{
// Memory is both ROM and hardware, the registers share the same address space.
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM | MEMORY_TYPE_VIRTUAL_HW, (RFSCtrl.uromAddr+(idx-0xE800)));
}
else if(idx >= 0xF000 && idx < 0x10000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_ROM, (idx+(Z80_VIRTUAL_ROM_SIZE - 0x10000)));
}
}
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
// Enable refresh as using virtual RAM stops refresh of host DRAM.
Z80Ctrl->refreshDRAM = 2;
#if (TARGET_HOST_MZ700 == 1)
// Reset memory paging to default.
SPI_SEND_32(0x00e4, 0x00 << 8 | CPLD_CMD_WRITEIO_ADDR);
#endif
// No I/O Ports on the RFS board.
pr_info("RFS Memory Setup complete.\n");
}
// Method to load a ROM image into the ROM memory.
//
uint8_t rfsLoadROM(const char* romFileName, uint32_t loadAddr, uint32_t loadSize)
{
// Locals.
uint8_t result = 0;
long noBytes;
struct file *fp;
fp = filp_open(romFileName, O_RDONLY, 0);
if(IS_ERR(fp))
{
pr_info("Error opening ROM Image:%s\n:", romFileName);
result = 1;
} else
{
vfs_llseek(fp, 0, SEEK_SET);
noBytes = kernel_read(fp, fp->f_pos, &Z80Ctrl->rom[loadAddr], loadSize);
if(noBytes < loadSize)
{
// pr_info("Short load, ROM Image:%s, bytes loaded:%08x\n:", romFileName, loadSize);
}
filp_close(fp,NULL);
}
return(result);
}
// Perform any setup operations, such as variable initialisation, to enable use of this module.
void rfsInit(uint8_t mode80c)
{
// Locals.
uint32_t idx;
// Load ROMS according to the display configuration, 40 char = standard, 80 char = 40/80 board installed.
rfsLoadROM(mode80c == 0 ? ROM_MROM_40C_FILENAME : ROM_MROM_80C_FILENAME, ROM_MROM_LOAD_ADDR, ROM_MROM_SIZE);
rfsLoadROM(mode80c == 0 ? ROM_USER_I_40C_FILENAME : ROM_USER_I_80C_FILENAME, ROM_USER_I_LOAD_ADDR, ROM_MROM_SIZE);
rfsLoadROM(mode80c == 0 ? ROM_USER_II_40C_FILENAME : ROM_USER_II_80C_FILENAME, ROM_USER_II_LOAD_ADDR, ROM_MROM_SIZE);
rfsLoadROM(mode80c == 0 ? ROM_USER_III_40C_FILENAME : ROM_USER_II_80C_FILENAME, ROM_USER_III_LOAD_ADDR, ROM_MROM_SIZE);
// Copy the Floppy ROM to the top portion of ROM. USER III isnt normally used and if it is, 4K will be free.
for(idx=0xF000; idx < 0x10000; idx++)
{
SPI_SEND32((uint32_t)idx << 16 | CPLD_CMD_READ_ADDR);
while(CPLD_READY() == 0);
Z80Ctrl->rom[idx+(Z80_VIRTUAL_ROM_SIZE-0x10000)] = z80io_PRL_Read8(1);
}
#if (TARGET_HOST_MZ700 == 1)
// Reset memory paging to default.
SPI_SEND_32(0x00e4, 0x00 << 8 | CPLD_CMD_WRITEIO_ADDR);
#endif
pr_info("Enabling RFS(%d) driver.\n", mode80c == 1 ? 80 : 40);
return;
}
// Perform any de-initialisation when the driver is removed.
void rfsRemove(void)
{
pr_info("Removing RFS driver.\n");
return;
}
// Method to decode an address and make any system memory map changes as required.
//
static inline void rfsDecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t ioFlag, uint8_t readFlag)
{
// Locals.
uint32_t idx;
// Memory map switch.
if(readFlag)
{
if(address == 0xE00C || address == 0xE00D || address == 0xE00E || address == 0xE00F)
{
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (0xC000+idx));
setMemoryType((idx+0xC000)/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, (RFSCtrl.mromAddr+idx));
}
RFSCtrl.memSwitch = 0x01;
}
// Reset memory map switch.
else if(address == 0xE010 || address == 0xE011 || address == 0xE012 || address == 0xE013)
{
if(readFlag)
{
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, (RFSCtrl.mromAddr+idx));
setMemoryType((idx+0xC000)/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (0xC000+idx));
}
}
RFSCtrl.memSwitch = 0x00;
}
}
}
// Emulation of the RFS SD card. The emulation is made easier as the RFS uses automatic shift registers so we just handle byte data not assembly
// of bit data.
//
// All SD commands are added to the processor but logic (apart from a standard response) is only added for commands which RFS uses.
//
void rfsSDCard(void)
{
// Locals.
//
uint32_t lbaAddr;
int noBytes;
// If Chip select is active and we arent initialised, exit, need to initialise before processing data.
if((RFSCtrl.regCtrl & SDCS) == 0 && RFSCtrl.sd.initialised == 0)
return;
// If the Chip select is inactive and we are initialised, exit, can only process data if selected.
if((RFSCtrl.regCtrl & SDCS) && RFSCtrl.sd.initialised == 1)
return;
// SD Card initialised? If not, follow the SD protocol.
//
if(RFSCtrl.sd.initialised == 0)
{
// RFS initialisation sends 10 x 8bits, which is a little more than standard 74bits. Just check for 7 bytes and then set initialised flag.
if(++RFSCtrl.sd.trainingCnt >= 7)
{
// Try and open the SD Card image. If it cannot be open then the SD card isnt registered as initialised.
RFSCtrl.sd.fhandle = filp_open(SD_CARD_FILENAME, O_RDWR, S_IWUSR | S_IRUSR);
if(IS_ERR(RFSCtrl.sd.fhandle))
{
pr_info("Error opening SD Card Image:%s\n:", SD_CARD_FILENAME);
} else
{
RFSCtrl.sd.initialised = 1;
RFSCtrl.sd.trainingCnt = 0;
}
}
//pr_info("Training:%d, Initialised:%d\n", RFSCtrl.sd.trainingCnt, RFSCtrl.sd.initialised);
} else
{
// If we are not receiving a command and response data is available, send it.
if((RFSCtrl.sd.rcvCntr == 0 && RFSCtrl.sd.regDataOut == 0xFF) || RFSCtrl.sd.respBuf || RFSCtrl.sd.dataOutFlag == 0)
{
if(RFSCtrl.sd.respBuf)
{
RFSCtrl.sd.regDataIn = RFSCtrl.sd.respBuf[RFSCtrl.sd.respCntr++];
//pr_info("Sending Response:%02x(%d)\n", RFSCtrl.sd.regDataIn, RFSCtrl.sd.respCntr);
if(RFSCtrl.sd.respCntr == RFSCtrl.sd.respLen)
{
RFSCtrl.sd.respBuf = NULL;
RFSCtrl.sd.respCntr = 0;
}
} else
{
//pr_info("Sending Response filler:0xFF\n");
RFSCtrl.sd.regDataIn = 0xFF;
}
}
else
{
// Clear out response buffer as latest data maybe an override, such as cancel.
RFSCtrl.sd.respBuf = NULL;
RFSCtrl.sd.respCntr = 0;
// Clear out data write flag, this indicates when data is written into the SPI for transmission.
RFSCtrl.sd.dataOutFlag = 0;
// Store incoming data.
RFSCtrl.sd.cmdBuf[RFSCtrl.sd.rcvCntr++] = RFSCtrl.sd.regDataOut;
//pr_info("Received:%02x(%d)\n", RFSCtrl.sd.regDataOut, RFSCtrl.sd.rcvCntr);
// 0xFE, <sector> <crc>
if(RFSCtrl.sd.rcvCntr == (SD_SECSIZE+3) && RFSCtrl.sd.writeFlag == 1)
{
static uint8_t response[] = { 0x05 };
// Write the sector to the SD card image.
// RFSCtrl.sd.cmdBuf[SD_SECSIZE+2] = 0x00; // CRC but we dont set, not needed in this application.
// RFSCtrl.sd.cmdBuf[SD_SECSIZE+3] = 0x00;
noBytes = kernel_write(RFSCtrl.sd.fhandle, &RFSCtrl.sd.cmdBuf[1], SD_SECSIZE, RFSCtrl.sd.fhandle->f_pos);
if(noBytes == 0) response[0] = 0x06; // Write error.
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
//pr_info("Writing %d bytes, CRC(%02x,%02x)\n", noBytes, RFSCtrl.sd.cmdBuf[SD_SECSIZE+2], RFSCtrl.sd.cmdBuf[SD_SECSIZE+3]);
// Reset to idle.
RFSCtrl.sd.rcvCntr = 0;
RFSCtrl.sd.writeFlag = 0;
}
// If we are not writing (receiving data from the Z80) and we have assembled a full command, process.
else if(RFSCtrl.sd.rcvCntr == 6 && RFSCtrl.sd.writeFlag == 0)
{
RFSCtrl.sd.rcvCntr = 0;
//pr_info("Received Command:%02x,%02x,%02x,%02x,%02x,%02x\n", RFSCtrl.sd.cmdBuf[0],RFSCtrl.sd.cmdBuf[1],RFSCtrl.sd.cmdBuf[2],RFSCtrl.sd.cmdBuf[3],RFSCtrl.sd.cmdBuf[4],RFSCtrl.sd.cmdBuf[5]);
switch(RFSCtrl.sd.cmdBuf[0])
{
case CMD0: // GO_IDLE_STATE
//pr_info("GO_IDLE_STATE\n");
{
// Initialise to SPI Mode. RFS doesnt support other modes.
static const uint8_t response[] = { 0x01 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case CMD1: // SEND_OP_COND
//pr_info("SEND_OP_COND\n");
{
static const uint8_t response[] = { 0x00 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case ACMD41: // SEND_OP_COND (SDC)
//pr_info("SEND_OP_COND\n");
{
static const uint8_t response[] = { 0x00 }; // 0 = Ready, 1 = Idle
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case CMD8: // SEND_IF_COND
//pr_info("SEND_IF_COND\n");
{
static const uint8_t response[] = { 0x01, 0x00, 0x00, 0x01, 0xAA };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case CMD9: // SEND_CSD
//pr_info("SEND_CSD\n");
{
static const uint8_t response[] = { 0x00 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case CMD10: // SEND_CID
//pr_info("SEND_CID\n");
{
static const uint8_t response[] = { 0x00 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case CMD12: // STOP_TRANSMISSION
//pr_info("STOP_TRANSMISSION\n");
{
static const uint8_t response[] = { 0x00 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case ACMD13: // SD_STATUS (SDC)
//pr_info("SD_STATUS\n");
{
static const uint8_t response[] = { 0x00 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case CMD16: // SET_BLOCKLEN
//pr_info("SD: Set Block Size:%d\n", (RFSCtrl.sd.cmdBuf[2] << 8 | RFSCtrl.sd.cmdBuf[3]));
{
static const uint8_t response[] = { 0x01 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case CMD17: // READ_SINGLE_BLOCK
//pr_info("READ_SINGLE_BLOCK\n");
{
static uint8_t response[6 + SD_SECSIZE];
memset(response, 0, sizeof(response));
// Assemble LBA address and seek to the right location in the SD card image.
lbaAddr = RFSCtrl.sd.cmdBuf[1] << 24 | RFSCtrl.sd.cmdBuf[2] << 16 | RFSCtrl.sd.cmdBuf[3] << 8 | RFSCtrl.sd.cmdBuf[4];
//pr_info("Reading LBA %d\n", lbaAddr);
vfs_llseek(RFSCtrl.sd.fhandle, lbaAddr * SD_SECSIZE, SEEK_SET);
// Assemble response buffer including SD card sector.
response[0] = 0x00; // Response R1
response[1] = 0xFE; // Start of Data marker.
noBytes = kernel_read(RFSCtrl.sd.fhandle, RFSCtrl.sd.fhandle->f_pos, &response[2], SD_SECSIZE);
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = SD_SECSIZE + 2 + 2; // Sector Size + 2 bytes (R1 + Data Start) + 2 CRC
}
break;
case CMD18: // READ_MULTIPLE_BLOCK
//pr_info("READ_MULTIPLE_BLOCK\n");
{
static const uint8_t response[] = { 0x00 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case ACMD23: // SET_WR_BLK_ERASE_COUNT (SDC)
//pr_info("SET_WR_BLK_ERASE_COUNT\n");
{
static const uint8_t response[] = { 0x00 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case CMD24: // WRITE_BLOCK
//pr_info("WRITE_BLOCK\n");
{
static const uint8_t response[] = { 0x00 };
// Assemble LBA address and seek to the right location in the SD card image.
lbaAddr = RFSCtrl.sd.cmdBuf[1] << 24 | RFSCtrl.sd.cmdBuf[2] << 16 | RFSCtrl.sd.cmdBuf[3] << 8 | RFSCtrl.sd.cmdBuf[4];
//pr_info("Writing LBA %d\n", lbaAddr);
vfs_llseek(RFSCtrl.sd.fhandle, lbaAddr * SD_SECSIZE, SEEK_SET);
// Assemble response which is Ready, data can now be sent for sector. Set write flag so we know data is being received as sector data.
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
RFSCtrl.sd.writeFlag = 1;
}
break;
case CMD25: // WRITE_MULTIPLE_BLOCK
//pr_info("WRITE_MULTIPLE_BLOCK\n");
{
static const uint8_t response[] = { 0x00 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case CMD32: // ERASE_ER_BLK_START
//pr_info("ERASE_ER_BLK_START\n");
{
static const uint8_t response[] = { 0x00 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case CMD33: // ERASE_ER_BLK_END
//pr_info("ERASE_ER_BLK_END\n");
{
static const uint8_t response[] = { 0x00 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case CMD38: // ERASE
//pr_info("ERASE\n");
{
static const uint8_t response[] = { 0x00 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case CMD55: // APP_CMD
//pr_info("APP_CMD\n");
{
static const uint8_t response[] = { 0x01 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
case CMD58: // READ_OCR
//pr_info("READ_OCR\n");
{
static const uint8_t response[] = { 0x00, 0x00, 0x00, 0x00 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
default:
pr_info("UNHANDLED REQUEST:%02x,%02x,%02x,%02x,%02x,%02x\n", RFSCtrl.sd.cmdBuf[0],RFSCtrl.sd.cmdBuf[1],RFSCtrl.sd.cmdBuf[2],RFSCtrl.sd.cmdBuf[3],RFSCtrl.sd.cmdBuf[4],RFSCtrl.sd.cmdBuf[5]);
{
static const uint8_t response[] = { 0x00 };
RFSCtrl.sd.respBuf = response;
RFSCtrl.sd.respLen = sizeof(response);
}
break;
}
}
else
{
// Standard response when a byte is received but not enough assembled to process.
RFSCtrl.sd.regDataIn = 0xFF;
}
}
}
return;
}
// Method to read from either the memory mapped registers if enabled else the ROM.
static inline uint8_t rfsRead(zuint16 address, uint8_t ioFlag)
{
// Locals.
uint8_t data = 0xFF;
//pr_info("RFS+Read:%04x, BK1:%02x, BK2:%02x, CTRL:%02x, MROM:%08x, UROM:%08x\n", address, RFSCtrl.regBank1, RFSCtrl.regBank2, RFSCtrl.regCtrl, RFSCtrl.mromAddr, RFSCtrl.uromAddr);
// Any access to the control region increments the enable counter till it reaches terminal count and enables writes to the registers. When the counter
// gets to 15 the registers are enabled and the EPROM, in the control region, is disabled.
if((address >= BNKCTRLRST && address <= BNKCTRL) && RFSCtrl.upCntr < 15)
{
RFSCtrl.upCntr++;
}
// Address in control region and register bank enabled?
//
if(RFSCtrl.upCntr >= 15 && (address >= BNKCTRLRST && address <= BNKCTRL))
{
switch(address)
{
// Bank control reset, returns all registers to power up default.
case BNKCTRLRST:
break;
// Disable bank control registers by resetting the coded latch.
case BNKCTRLDIS:
RFSCtrl.upCntr = (RFSCtrl.regCtrl >> 2) & 0x0E;
break;
// Hardware SPI Data register (read/write).
case HWSPIDATA:
// Action data, ie. run the SD emulation.
data = RFSCtrl.sd.regDataIn;
//pr_info("HWSPIDATA ReadOut:%02x\n", data);
break;
// Start an SPI transfer.
case HWSPISTART:
break;
// Select RFS Bank1 (MROM) - No action for read, real hardware would store an undefined value into register.
case BNKSELMROM:
break;
// Select RFS Bank2 (User ROM) - No action for read.
case BNKSELUSER:
break;
// Bank Control register (read/write).
case BNKCTRL:
break;
}
} else
{
// Return the contents of the ROM at given address.
data = isVirtualROM(address) ? readVirtualROM(address) : readVirtualRAM(address);
}
//pr_info("RFS-Read:%04x, Data:%02x, BK1:%02x, BK2:%02x, CTRL:%02x, MROM:%08x, UROM:%08x\n", address, data, RFSCtrl.regBank1, RFSCtrl.regBank2, RFSCtrl.regCtrl, RFSCtrl.mromAddr, RFSCtrl.uromAddr);
return(data);
}
// Method to handle writes to the RFS board. Generally the RFS board.
static inline void rfsWrite(zuint16 address, zuint8 data, uint8_t ioFlag)
{
// Locals.
uint32_t idx;
//pr_info("RFS+Write:%04x, Data:%02x, BK1:%02x, BK2:%02x, CTRL:%02x, MROM:%08x, UROM:%08x\n", address, data, RFSCtrl.regBank1, RFSCtrl.regBank2, RFSCtrl.regCtrl, RFSCtrl.mromAddr, RFSCtrl.uromAddr);
// Any access to the control region increments the enable counter till it reaches terminal count and enables writes to the registers. When the counter
// gets to 15 the registers are enabled and the EPROM, in the control region, is disabled.
if((address >= BNKCTRLRST && address <= BNKCTRL) && RFSCtrl.upCntr < 15)
{
RFSCtrl.upCntr++;
}
// Address in control region and register bank enabled?
//
if(RFSCtrl.upCntr >= 15 && (address >= BNKCTRLRST && address <= BNKCTRL))
{
switch(address)
{
// Bank control reset, returns all registers to power up default.
case BNKCTRLRST: // 0xEFF8
break;
// Disable bank control registers by resetting the coded latch.
case BNKCTRLDIS: // 0xEFF9
default:
RFSCtrl.upCntr = (RFSCtrl.regCtrl >> 2) & 0x0E;
break;
// Hardware SPI Data register (read/write).
case HWSPIDATA:
RFSCtrl.sd.regDataOut = data;
RFSCtrl.sd.dataOutFlag = 1;
//pr_info("HWSPIDATA WriteIn:%02x\n", data);
break;
// Start an SPI transfer.
case HWSPISTART:
// Action data, ie. run the SD emulation as a write to this address starts the SPI clock which clocks out 8bit and clocks in 8 bits.
//pr_info("HWSPISTART\n");
rfsSDCard();
break;
// Select RFS Bank1 (MROM)
case BNKSELMROM:
RFSCtrl.regBank1 = data;
// Update monitor ROM address as register contains upper address bits of the ROM.
RFSCtrl.mromAddr = (uint32_t)(RFSCtrl.regBank1 << 12);
// Update memory map to reflect register change.
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(RFSCtrl.memSwitch)
{
// Monitor ROM is located at 0xC000.
setMemoryType((0xC000+idx)/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, (RFSCtrl.mromAddr+idx));
}
else
{
// Monitor ROM is located at 0x000.
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, (RFSCtrl.mromAddr+idx));
}
}
break;
// Select RFS Bank2 (User ROM)
case BNKSELUSER:
// Bank Control register (read/write).
case BNKCTRL:
if(address == BNKSELUSER) { RFSCtrl.regBank2 = data; } else { RFSCtrl.regCtrl = data; }
// Update user ROM address as register contain upper address bits of the ROM.
RFSCtrl.uromAddr = (uint32_t)(((((RFSCtrl.regCtrl&0xB0) << 2) | RFSCtrl.regBank2) << 11) + USER_ROM_I_ADDR);
// Update memory map to reflect register change.
for(idx=0xE800; idx < 0xF000; idx+=MEMORY_BLOCK_GRANULARITY)
{
// Memory is both ROM and hardware, the registers share the same address space.
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM | MEMORY_TYPE_VIRTUAL_HW, (RFSCtrl.uromAddr+(idx-0xE800)));
}
break;
}
} else
{
// Any unprocessed write is commited to RAM.
writeVirtualRAM(address, data);
}
//pr_info("RFS-Write:%04x, Data:%02x, BK1:%02x, BK2:%02x, CTRL:%02x, MROM:%08x, UROM:%08x\n", address, data, RFSCtrl.regBank1, RFSCtrl.regBank2, RFSCtrl.regCtrl, RFSCtrl.mromAddr, RFSCtrl.uromAddr);
return;
}

File diff suppressed because it is too large Load Diff

83
software/FusionX/start_FusionX.sh Normal file → Executable file
View File

@@ -1,6 +1,83 @@
#!/bin/sh
#########################################################################################################
##
## Name: start_FusionX.sh
## Created: March 2023
## Author(s): Philip Smart
## Description: Sharp MZ series FusionX start script.
## This script starts required services which form the FusionX ecosphere.
## tranZPUter SW memory as a User ROM application.
##
## Credits:
## Copyright: (c) 2018-2023 Philip Smart <philip.smart@net2net.org>
##
## History: March 2023 - Initial script written.
##
#########################################################################################################
## This source file is free software: you can redistribute it and#or modify
## it under the terms of the GNU General Public License as published
## by the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This source file is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see <http://www.gnu.org/licenses/>.
#########################################################################################################
ROOTDIR=/apps/FusionX
# Constants.
FUSIONXDIR=/apps/FusionX
cd ${ROOTDIR}
#nohup ${ROOTDIR}/bin/FusionX &
cd ${FUSIONXDIR}
# If not already installed, install the Sharp MZ TTY terminal driver.
if [ "`lsmod | grep ttymzdrv`" = "" ]; then
echo "Loading SharpMZ TTY Driver."
cd ${FUSIONXDIR}/modules
insmod ttymzdrv.ko
sleep 1
fi
# Start a Getty login process on the SharpMZ TTY terminal.
setsid getty 9600 /dev/ttymz0 ansi &
# Detach CPU 1 from scheduler and IRQ's as it will be dedicated to the z80drv.
for f in `ps -eaf |grep -v kthread_z80 | awk '{print $1}'`
do
taskset -pc 0 $f >/dev/null 2>/dev/null
done
# Detach IRQ's
for I in $(ls /proc/irq)
do
if [[ -d "/proc/irq/$I" ]]
then
echo 0 > /proc/irq/$I/smp_affinity_list 2>/dev/null
fi
done
# Load the Z80 driver. Small pause to ensure the driver is fully loaded and initialsed prior to loading ROM images.
echo "Loading Z80 Driver."
cd ${FUSIONXDIR}/modules
rmmod z80drv 2>/dev/null
insmod z80drv.ko
sleep 1
# Start the K64F virtual cpu.
echo "Starting K64F Virtual CPU."
${FUSIONXDIR}/bin/k64fcpu &
# Start the Sharp MZ Arbiter.
echo "Starting Sharp MZ Arbiter."
${FUSIONXDIR}/bin/sharpbiter &
# Ensure the system is set for performance mode with max frequency.
# NB: Enabling this prior to starting the Z80 results in a kernel error.
echo performance > /sys/devices//system/cpu/cpufreq/policy0/scaling_governor
echo 1200000 > /sys/devices//system/cpu/cpufreq/policy0/scaling_min_freq
# Done.
echo "FusionX running."

View File

@@ -49,6 +49,9 @@ DATE=$(date +%m%d)
BACKUPDIR=$(date +%m%d%H%M)
#images will output in ${RELEASEDIR}/images/
RELEASEDIR=`pwd`
FUSIONXDIR=`pwd`\..\FusionX
WEBSRVDIR=`pwd`\..\WebServer
Z80EMUDIR=`pwd`\..\Z80emu
#release source code
#find ./boot/ | grep -v boot/.git | cpio -pdm ${RELEASEDIR}/
#find ./project/ | grep -v project/.git | cpio -pdm ${RELEASEDIR}/
@@ -259,25 +262,25 @@ if [ -d ${RELEASEDIR}/project/image/output/customer -a "`ls ${RELEASEDIR}/projec
fi
# Setup the applications for FusionX.
mkdir -p ${RELEASEDIR}/project/image/output/sdrootfs/apps
if [ -d /srv/dvlp/Projects/tzpu/FusionX/software/FusionX ]; then
if [ -d ${FUSIONXDIR} ]; then
echo -n "FusionX "
cd /srv/dvlp/Projects/tzpu/FusionX/software/FusionX
cd ${FUSIONXDIR}
mkdir -p ${RELEASEDIR}/project/image/output/sdrootfs/apps/FusionX/
cp -r * ${RELEASEDIR}/project/image/output/sdrootfs/apps/FusionX/
cp start_FusionX.sh ${RELEASEDIR}/project/image/output/sdrootfs/apps/
chmod +x ${RELEASEDIR}/project/image/output/sdrootfs/apps/start_FusionX.sh
fi
if [ -d /srv/dvlp/Projects/tzpu/FusionX/software/WebServer/ ]; then
if [ -d ${WEBSRVDIR} ]; then
echo -n "WebServer "
cd /srv/dvlp/Projects/tzpu/FusionX/software/WebServer/
cd ${WEBSRVDIR}
mkdir -p ${RELEASEDIR}/project/image/output/sdrootfs/apps/WebServer/
cp -r WebServer webfs/ conf/ ${RELEASEDIR}/project/image/output/sdrootfs/apps/WebServer/
cp start_WebServer.sh ${RELEASEDIR}/project/image/output/sdrootfs/apps/
chmod +x ${RELEASEDIR}/project/image/output/sdrootfs/apps/start_WebServer.sh
fi
if [ -d /srv/dvlp/Projects/tzpu/FusionX/software/Z80emu/Z80/ ]; then
if [ -d ${Z80EMUDIR} ]; then
echo -n "Z80 "
cd /srv/dvlp/Projects/tzpu/FusionX/software/Z80emu/
cd ${Z80EMUDIR}
mkdir -p ${RELEASEDIR}/project/image/output/sdrootfs/apps/Z80/
cp -r Z80/* ${RELEASEDIR}/project/image/output/sdrootfs/apps/Z80/
fi
@@ -291,10 +294,14 @@ fi
# Copy any new files.
for f in DSK MZF CPM BAS CAS Basic
do
mkdir -p ${RELEASEDIR}/project/image/output/sdrootfs/apps/disk/Sharp
cp -r /srv/dvlp/Projects/tzpu/FusionX/software/${f}/ ${RELEASEDIR}/project/image/output/sdrootfs/apps/disk/Sharp/${f}/
mkdir -p ${RELEASEDIR}/project/image/output/sdrootfs/apps/FusionX/disk/
cp -r /srv/dvlp/Projects/tzpu/FusionX/software/${f}/ ${RELEASEDIR}/project/image/output/sdrootfs/apps/FusionX/disk/${f}/
done
# Copy an new rom images.
mkdir -p ${RELEASEDIR}/project/image/output/sdrootfs/apps/FusionX/roms/
cp -r /srv/dvlp/Projects/tzpu/FusionX/software/roms/* ${RELEASEDIR}/project/image/output/sdrootfs/apps/FusionX/roms/
# Make any manual setup changes.
#echo "/dev/zram0 none swap sw 0 -1" >> ${RELEASEDIR}/project/image/output/sdrootfs/etc/fstab
#echo "/dev/mmcblk1p1 none swap sw 0 -2" >> ${RELEASEDIR}/project/image/output/sdrootfs/etc/fstab

View File

@@ -1,7 +1,7 @@
// $Change: 6322424ba $
// $Change: dfa3dd5a5 $
#define MVXV_HEAD_VER {'4'}
#define MVXV_LIB_TYPE {'#', '#'}
#define MVXV_CHIP_ID {'I', '2', 'M', '#'}
#define MVXV_CHANGELIST {'g', '6', '3', '2', '2', '4', '2', '4', 'b', 'a'}
#define MVXV_CHANGELIST {'g', 'd', 'f', 'a', '3', 'd', 'd', '5', 'a', '5'}
#define MVXV_COMP_ID {'C', 'M', '_', 'U', 'B', 'T', '1', '5', '0', '1'}

View File

@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Buildroot 2020.05-g1e61fe54a-dirty Configuration
# Buildroot 2020.05-00004-g652bdd81e-dirty Configuration
#
BR2_HAVE_DOT_CONFIG=y
BR2_HOST_GCC_AT_LEAST_4_9=y
@@ -2033,7 +2033,7 @@ BR2_PACKAGE_NCURSES_ADDITIONAL_TERMINFO=""
# BR2_PACKAGE_ONIGURUMA is not set
# BR2_PACKAGE_PCRE is not set
# BR2_PACKAGE_PCRE2 is not set
# BR2_PACKAGE_POPT is not set
BR2_PACKAGE_POPT=y
# BR2_PACKAGE_READLINE is not set
# BR2_PACKAGE_SLANG is not set
# BR2_PACKAGE_TCLAP is not set
@@ -2295,7 +2295,7 @@ BR2_PACKAGE_PPPD_OVERWRITE_RESOLV_CONF=y
# BR2_PACKAGE_RP_PPPOE is not set
# BR2_PACKAGE_RPCBIND is not set
# BR2_PACKAGE_RSH_REDONE is not set
# BR2_PACKAGE_RSYNC is not set
BR2_PACKAGE_RSYNC=y
# BR2_PACKAGE_RTORRENT is not set
# BR2_PACKAGE_RTPTOOLS is not set
# BR2_PACKAGE_RYGEL is not set

View File

@@ -1,119 +0,0 @@
/*
* aks-cdu.dts - Device Tree file for AK signal CDU
*
* Copyright (C) 2012 AK signal Brno a.s.
* 2012 Jiri Prchal <jiri.prchal@aksignal.cz>
*
* Licensed under GPLv2 or later.
*/
/dts-v1/;
#include "ge863-pro3.dtsi"
/ {
chosen {
bootargs = "console=ttyS0,115200 ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs";
};
clocks {
slow_xtal {
clock-frequency = <32768>;
};
};
ahb {
apb {
usart0: serial@fffb0000 {
status = "okay";
};
usart1: serial@fffb4000 {
status = "okay";
linux,rs485-enabled-at-boot-time;
rs485-rts-delay = <0 0>;
};
usart2: serial@fffb8000 {
status = "okay";
linux,rs485-enabled-at-boot-time;
rs485-rts-delay = <0 0>;
};
usart3: serial@fffd0000 {
status = "okay";
linux,rs485-enabled-at-boot-time;
rs485-rts-delay = <0 0>;
};
macb0: ethernet@fffc4000 {
phy-mode = "rmii";
status = "okay";
};
usb1: gadget@fffa4000 {
atmel,vbus-gpio = <&pioC 15 GPIO_ACTIVE_HIGH>;
status = "okay";
};
};
usb0: ohci@500000 {
num-ports = <2>;
status = "okay";
};
nand0: nand@40000000 {
nand-bus-width = <8>;
nand-ecc-mode = "soft";
nand-on-flash-bbt;
status = "okay";
bootstrap@0 {
label = "bootstrap";
reg = <0x0 0x40000>;
};
uboot@40000 {
label = "uboot";
reg = <0x40000 0x80000>;
};
ubootenv@c0000 {
label = "ubootenv";
reg = <0xc0000 0x40000>;
};
kernel@100000 {
label = "kernel";
reg = <0x100000 0x400000>;
};
rootfs@500000 {
label = "rootfs";
reg = <0x500000 0x7b00000>;
};
};
};
leds {
compatible = "gpio-leds";
red {
gpios = <&pioC 10 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "none";
};
green {
gpios = <&pioA 5 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
default-state = "on";
};
yellow {
gpios = <&pioB 20 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
blue {
gpios = <&pioB 21 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
};
};

View File

@@ -1,13 +0,0 @@
/*
* Copyright 2014 Oleksij Rempel <linux@rempel-privat.de>
*
* Licensed under the X11 license or the GPL v2 (or later)
*/
/dts-v1/;
#include "alphascale-asm9260.dtsi"
/ {
model = "Alphascale asm9260 Development Kit";
compatible = "alphascale,asm9260devkit", "alphascale,asm9260";
};

View File

@@ -1,63 +0,0 @@
/*
* Copyright 2014 Oleksij Rempel <linux@rempel-privat.de>
*
* Licensed under the X11 license or the GPL v2 (or later)
*/
#include "skeleton.dtsi"
#include <dt-bindings/clock/alphascale,asm9260.h>
/ {
interrupt-parent = <&icoll>;
memory {
device_type = "memory";
reg = <0x20000000 0x2000000>;
};
cpus {
#address-cells = <0>;
#size-cells = <0>;
cpu {
compatible = "arm,arm926ej-s";
device_type = "cpu";
clocks = <&acc CLKID_SYS_CPU>;
};
};
osc24m: oscillator {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24000000>;
clock-accuracy = <30000>;
};
soc {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
acc: clock-controller@80040000 {
compatible = "alphascale,asm9260-clock-controller";
#clock-cells = <1>;
clocks = <&osc24m>;
reg = <0x80040000 0x204>;
};
icoll: interrupt-controller@80054000 {
compatible = "alphascale,asm9260-icoll";
interrupt-controller;
#interrupt-cells = <1>;
reg = <0x80054000 0x200>;
};
timer0: timer@80088000 {
compatible = "alphascale,asm9260-timer";
reg = <0x80088000 0x4000>;
clocks = <&acc CLKID_AHB_TIMER0>;
interrupts = <29>;
};
};
};

View File

@@ -1,35 +0,0 @@
/*
* Copyright 2015 Annapurna Labs Ltd.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* Alternatively, redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
/dts-v1/;
#include "alpine.dtsi"
/ {
model = "Annapurna Labs Alpine Dev Board";
/* no need for anything outside SOC */
};

View File

@@ -1,170 +0,0 @@
/*
* Copyright 2015 Annapurna Labs Ltd.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* Alternatively, redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "skeleton64.dtsi"
/ {
/* SOC compatibility */
compatible = "al,alpine";
/* CPU Configuration */
cpus {
#address-cells = <1>;
#size-cells = <0>;
enable-method = "al,alpine-smp";
cpu@0 {
compatible = "arm,cortex-a15";
device_type = "cpu";
reg = <0>;
clock-frequency = <0>; /* Filled by loader */
};
cpu@1 {
compatible = "arm,cortex-a15";
device_type = "cpu";
reg = <1>;
clock-frequency = <0>; /* Filled by loader */
};
cpu@2 {
compatible = "arm,cortex-a15";
device_type = "cpu";
reg = <2>;
clock-frequency = <0>; /* Filled by loader */
};
cpu@3 {
compatible = "arm,cortex-a15";
device_type = "cpu";
reg = <3>;
clock-frequency = <0>; /* Filled by loader */
};
};
soc {
#address-cells = <2>;
#size-cells = <2>;
compatible = "simple-bus";
interrupt-parent = <&gic>;
ranges;
arch-timer {
compatible = "arm,cortex-a15-timer",
"arm,armv7-timer";
interrupts =
<GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
clock-frequency = <0>; /* Filled by loader */
};
/* Interrupt Controller */
gic: gic@fb001000 {
compatible = "arm,cortex-a15-gic";
#interrupt-cells = <3>;
#size-cells = <0>;
#address-cells = <0>;
interrupt-controller;
reg = <0x0 0xfb001000 0x0 0x1000>,
<0x0 0xfb002000 0x0 0x2000>,
<0x0 0xfb004000 0x0 0x1000>,
<0x0 0xfb006000 0x0 0x2000>;
interrupts =
<GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
};
/* CPU Resume registers */
cpu-resume@fbff5ec0 {
compatible = "al,alpine-cpu-resume";
reg = <0x0 0xfbff5ec0 0x0 0x30>;
};
/* North Bridge Service Registers */
sysfabric-service@fb070000 {
compatible = "al,alpine-sysfabric-service", "syscon";
reg = <0x0 0xfb070000 0x0 0x10000>;
};
/* Performance Monitor Unit */
pmu {
compatible = "arm,cortex-a15-pmu";
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
};
uart0:uart@fd883000 {
compatible = "ns16550a";
reg = <0x0 0xfd883000 0x0 0x1000>;
clock-frequency = <0>; /* Filled by loader */
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
};
uart1:uart@0xfd884000 {
compatible = "ns16550a";
reg = <0x0 0xfd884000 0x0 0x1000>;
clock-frequency = <0>; /* Filled by loader */
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
};
/* Internal PCIe Controller */
pcie-internal@0xfbc00000 {
compatible = "pci-host-ecam-generic";
device_type = "pci";
#size-cells = <2>;
#address-cells = <3>;
#interrupt-cells = <1>;
reg = <0x0 0xfbc00000 0x0 0x100000>;
interrupt-map-mask = <0xf800 0 0 7>;
/* Add legacy interrupts for SATA devices only */
interrupt-map = <0x4000 0 0 1 &gic 0 43 4>,
<0x4800 0 0 1 &gic 0 44 4>;
/* 32 bit non prefetchable memory space */
ranges = <0x02000000 0x0 0xfe000000 0x0 0xfe000000 0x0 0x1000000>;
bus-range = <0x00 0x00>;
msi-parent = <&msix>;
};
msix: msix@fbe00000 {
compatible = "al,alpine-msix";
reg = <0x0 0xfbe00000 0x0 0x100000>;
interrupt-controller;
msi-controller;
al,msi-base-spi = <96>;
al,msi-num-spis = <64>;
};
};
};

View File

@@ -1,71 +0,0 @@
/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* VScom OnRISC
* http://www.vscom.de
*/
/dts-v1/;
#include "am335x-baltos.dtsi"
/ {
model = "OnRISC Baltos iR 2110";
};
&am33xx_pinmux {
uart1_pins: pinmux_uart1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0) /* uart1_rxd */
AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE0) /* uart1_txd */
AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0) /* uart1_ctsn */
AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_rtsn */
AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* lcd_vsync.gpio2[22] DTR */
AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_hsync.gpio2[23] DSR */
AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_pclk.gpio2[24] DCD */
AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_ac_bias_en.gpio2[25] RI */
>;
};
};
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>;
dtr-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
dsr-gpios = <&gpio2 23 GPIO_ACTIVE_LOW>;
dcd-gpios = <&gpio2 24 GPIO_ACTIVE_LOW>;
rng-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>;
status = "okay";
};
&usb0_phy {
status = "okay";
};
&usb0 {
status = "okay";
dr_mode = "host";
};
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <1>;
phy-mode = "rmii";
dual_emac_res_vlan = <1>;
};
&cpsw_emac1 {
phy_id = <&davinci_mdio>, <7>;
phy-mode = "rgmii-txid";
dual_emac_res_vlan = <2>;
};
&phy_sel {
rmii-clock-ext = <1>;
};

View File

@@ -1,119 +0,0 @@
/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* VScom OnRISC
* http://www.vscom.de
*/
/dts-v1/;
#include "am335x-baltos.dtsi"
/ {
model = "OnRISC Baltos iR 3220";
};
&am33xx_pinmux {
tca6416_pins: pinmux_tca6416_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9b4, PIN_INPUT_PULLUP | MUX_MODE7) /* xdma_event_intr1.gpio0[20] tca6416 stuff */
>;
};
uart1_pins: pinmux_uart1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0) /* uart1_rxd */
AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE0) /* uart1_txd */
AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0) /* uart1_ctsn */
AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_rtsn */
AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* lcd_vsync.gpio2[22] DTR */
AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_hsync.gpio2[23] DSR */
AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_pclk.gpio2[24] DCD */
AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_ac_bias_en.gpio2[25] RI */
>;
};
uart2_pins: pinmux_uart2_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1) /* spi0_sclk.uart2_rxd_mux3 */
AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1) /* spi0_d0.uart2_txd_mux3 */
AM33XX_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE2) /* i2c0_sda.uart2_ctsn_mux0 */
AM33XX_IOPAD(0x98c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* i2c0_scl.uart2_rtsn_mux0 */
AM33XX_IOPAD(0x830, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad12.gpio1[12] DTR */
AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad13.gpio1[13] DSR */
AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad14.gpio1[14] DCD */
AM33XX_IOPAD(0x83c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad15.gpio1[15] RI */
AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLUP | MUX_MODE7) /* mcasp0_aclkr.gpio3[18], INPUT_PULLDOWN | MODE7 */
>;
};
};
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>;
dtr-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
dsr-gpios = <&gpio2 23 GPIO_ACTIVE_LOW>;
dcd-gpios = <&gpio2 24 GPIO_ACTIVE_LOW>;
rng-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>;
status = "okay";
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
dtr-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
dsr-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
dcd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
rng-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
status = "okay";
};
&i2c1 {
tca6416: gpio@20 {
compatible = "ti,tca6416";
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&gpio0>;
interrupts = <20 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&tca6416_pins>;
};
};
&usb0_phy {
status = "okay";
};
&usb0 {
status = "okay";
dr_mode = "host";
};
&cpsw_emac0 {
phy-mode = "rmii";
dual_emac_res_vlan = <1>;
fixed-link {
speed = <100>;
full-duplex;
};
};
&cpsw_emac1 {
phy_id = <&davinci_mdio>, <7>;
phy-mode = "rgmii-txid";
dual_emac_res_vlan = <2>;
};
&phy_sel {
rmii-clock-ext = <1>;
};

View File

@@ -1,144 +0,0 @@
/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* VScom OnRISC
* http://www.vscom.de
*/
/dts-v1/;
#include "am335x-baltos.dtsi"
/ {
model = "OnRISC Baltos iR 5221";
};
&am33xx_pinmux {
tca6416_pins: pinmux_tca6416_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9b4, PIN_INPUT_PULLUP | MUX_MODE7) /* xdma_event_intr1.gpio0[20] tca6416 stuff */
>;
};
dcan1_pins: pinmux_dcan1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x968, PIN_OUTPUT | MUX_MODE2) /* uart0_ctsn.dcan1_tx_mux0 */
AM33XX_IOPAD(0x96c, PIN_INPUT | MUX_MODE2) /* uart0_rtsn.dcan1_rx_mux0 */
>;
};
uart1_pins: pinmux_uart1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0) /* uart1_rxd */
AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE0) /* uart1_txd */
AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0) /* uart1_ctsn */
AM33XX_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_rtsn */
AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* lcd_vsync.gpio2[22] DTR */
AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_hsync.gpio2[23] DSR */
AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_pclk.gpio2[24] DCD */
AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_ac_bias_en.gpio2[25] RI */
>;
};
uart2_pins: pinmux_uart2_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1) /* spi0_sclk.uart2_rxd_mux3 */
AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1) /* spi0_d0.uart2_txd_mux3 */
AM33XX_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE2) /* i2c0_sda.uart2_ctsn_mux0 */
AM33XX_IOPAD(0x98c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* i2c0_scl.uart2_rtsn_mux0 */
AM33XX_IOPAD(0x830, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad12.gpio1[12] DTR */
AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad13.gpio1[13] DSR */
AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad14.gpio1[14] DCD */
AM33XX_IOPAD(0x83c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad15.gpio1[15] RI */
AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLUP | MUX_MODE7) /* mcasp0_aclkr.gpio3[18], INPUT_PULLDOWN | MODE7 */
>;
};
};
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>;
dtr-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
dsr-gpios = <&gpio2 23 GPIO_ACTIVE_LOW>;
dcd-gpios = <&gpio2 24 GPIO_ACTIVE_LOW>;
rng-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>;
status = "okay";
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
dtr-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
dsr-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
dcd-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
rng-gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
status = "okay";
};
&i2c1 {
tca6416: gpio@20 {
compatible = "ti,tca6416";
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&gpio0>;
interrupts = <20 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&tca6416_pins>;
};
};
&usb0_phy {
status = "okay";
};
&usb1_phy {
status = "okay";
};
&usb0 {
status = "okay";
dr_mode = "host";
};
&usb1 {
status = "okay";
dr_mode = "otg";
};
&cpsw_emac0 {
phy-mode = "rmii";
dual_emac_res_vlan = <1>;
fixed-link {
speed = <100>;
full-duplex;
};
};
&cpsw_emac1 {
phy_id = <&davinci_mdio>, <7>;
phy-mode = "rgmii-txid";
dual_emac_res_vlan = <2>;
};
&phy_sel {
rmii-clock-ext = <1>;
};
&dcan1 {
pinctrl-names = "default";
pinctrl-0 = <&dcan1_pins>;
status = "okay";
};

View File

@@ -1,408 +0,0 @@
/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* VScom OnRISC
* http://www.vscom.de
*/
#include "am33xx.dtsi"
#include <dt-bindings/pwm/pwm.h>
#include <dt-bindings/interrupt-controller/irq.h>
/ {
compatible = "vscom,onrisc", "ti,am33xx";
cpus {
cpu@0 {
cpu0-supply = <&vdd1_reg>;
};
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>; /* 256 MB */
};
vbat: fixedregulator0 {
compatible = "regulator-fixed";
regulator-name = "vbat";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-boot-on;
};
wl12xx_vmmc: fixedregulator2 {
pinctrl-names = "default";
pinctrl-0 = <&wl12xx_gpio>;
compatible = "regulator-fixed";
regulator-name = "vwl1271";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio3 8 0>;
startup-delay-us = <70000>;
enable-active-high;
};
};
&am33xx_pinmux {
mmc2_pins: pinmux_mmc2_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x820, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad8.mmc1_dat0_mux0 */
AM33XX_IOPAD(0x824, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad9.mmc1_dat1_mux0 */
AM33XX_IOPAD(0x828, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad10.mmc1_dat2_mux0 */
AM33XX_IOPAD(0x82c, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_ad11.mmc1_dat3_mux0 */
AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk_mux0 */
AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd_mux0 */
AM33XX_IOPAD(0x9e4, PIN_INPUT_PULLUP | MUX_MODE7) /* emu0.gpio3[7] */
>;
};
wl12xx_gpio: pinmux_wl12xx_gpio {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9e8, PIN_OUTPUT_PULLUP | MUX_MODE7) /* emu1.gpio3[8] */
>;
};
tps65910_pins: pinmux_tps65910_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x878, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_ben1.gpio1[28] */
>;
};
i2c1_pins: pinmux_i2c1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x958, PIN_INPUT | MUX_MODE2) /* spi0_d1.i2c1_sda_mux3 */
AM33XX_IOPAD(0x95c, PIN_INPUT | MUX_MODE2) /* spi0_cs0.i2c1_scl_mux3 */
>;
};
uart0_pins: pinmux_uart0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
>;
};
cpsw_default: cpsw_default {
pinctrl-single,pins = <
/* Slave 1 */
AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs_dv */
AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_tx_en.rmii1_txen */
AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */
AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */
AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_ref_clk.rmii1_refclk */
/* Slave 2 */
AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */
AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a1.rgmii2_rctl */
AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */
AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */
AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */
AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */
AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */
AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */
AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */
AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */
AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */
AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */
>;
};
cpsw_sleep: cpsw_sleep {
pinctrl-single,pins = <
/* Slave 1 reset value */
AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
/* Slave 2 reset value*/
AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x848, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x84c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
davinci_mdio_default: davinci_mdio_default {
pinctrl-single,pins = <
/* MDIO */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
>;
};
davinci_mdio_sleep: davinci_mdio_sleep {
pinctrl-single,pins = <
/* MDIO reset value */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
nandflash_pins_s0: nandflash_pins_s0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */
AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */
AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */
AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */
AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */
AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */
AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */
AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */
AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */
AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */
AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */
AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */
AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */
AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */
AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */
>;
};
};
&elm {
status = "okay";
};
&gpmc {
pinctrl-names = "default";
pinctrl-0 = <&nandflash_pins_s0>;
ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */
status = "okay";
nand@0,0 {
compatible = "ti,omap2-nand";
reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
nand-bus-width = <8>;
ti,nand-ecc-opt = "bch8";
ti,nand-xfer-type = "polled";
gpmc,device-nand = "true";
gpmc,device-width = <1>;
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;
gpmc,cs-rd-off-ns = <44>;
gpmc,cs-wr-off-ns = <44>;
gpmc,adv-on-ns = <6>;
gpmc,adv-rd-off-ns = <34>;
gpmc,adv-wr-off-ns = <44>;
gpmc,we-on-ns = <0>;
gpmc,we-off-ns = <40>;
gpmc,oe-on-ns = <0>;
gpmc,oe-off-ns = <54>;
gpmc,access-ns = <64>;
gpmc,rd-cycle-ns = <82>;
gpmc,wr-cycle-ns = <82>;
gpmc,bus-turnaround-ns = <0>;
gpmc,cycle2cycle-delay-ns = <0>;
gpmc,clk-activation-ns = <0>;
gpmc,wr-access-ns = <40>;
gpmc,wr-data-mux-bus-ns = <0>;
#address-cells = <1>;
#size-cells = <1>;
ti,elm-id = <&elm>;
};
};
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
status = "okay";
};
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
status = "okay";
clock-frequency = <400000>;
tps: tps@2d {
reg = <0x2d>;
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&gpio1>;
interrupts = <28 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&tps65910_pins>;
};
at24@50 {
compatible = "at24,24c02";
pagesize = <8>;
reg = <0x50>;
};
};
&usb {
status = "okay";
};
&usb_ctrl_mod {
status = "okay";
};
&cppi41dma {
status = "okay";
};
#include "tps65910.dtsi"
&tps {
vcc1-supply = <&vbat>;
vcc2-supply = <&vbat>;
vcc3-supply = <&vbat>;
vcc4-supply = <&vbat>;
vcc5-supply = <&vbat>;
vcc6-supply = <&vbat>;
vcc7-supply = <&vbat>;
vccio-supply = <&vbat>;
ti,en-ck32k-xtal = <1>;
regulators {
vrtc_reg: regulator@0 {
regulator-always-on;
};
vio_reg: regulator@1 {
regulator-always-on;
};
vdd1_reg: regulator@2 {
/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
regulator-name = "vdd_mpu";
regulator-min-microvolt = <912500>;
regulator-max-microvolt = <1312500>;
regulator-boot-on;
regulator-always-on;
};
vdd2_reg: regulator@3 {
/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
regulator-name = "vdd_core";
regulator-min-microvolt = <912500>;
regulator-max-microvolt = <1150000>;
regulator-boot-on;
regulator-always-on;
};
vdd3_reg: regulator@4 {
regulator-always-on;
};
vdig1_reg: regulator@5 {
regulator-always-on;
};
vdig2_reg: regulator@6 {
regulator-always-on;
};
vpll_reg: regulator@7 {
regulator-always-on;
};
vdac_reg: regulator@8 {
regulator-always-on;
};
vaux1_reg: regulator@9 {
regulator-always-on;
};
vaux2_reg: regulator@10 {
regulator-always-on;
};
vaux33_reg: regulator@11 {
regulator-always-on;
};
vmmc_reg: regulator@12 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
};
};
&mac {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
dual_emac = <1>;
status = "okay";
};
&davinci_mdio {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
status = "okay";
};
&mmc1 {
vmmc-supply = <&vmmc_reg>;
status = "okay";
};
&mmc2 {
status = "okay";
vmmc-supply = <&wl12xx_vmmc>;
ti,non-removable;
bus-width = <4>;
cap-power-off-card;
pinctrl-names = "default";
pinctrl-0 = <&mmc2_pins>;
#address-cells = <1>;
#size-cells = <0>;
wlcore: wlcore@2 {
compatible = "ti,wl1835";
reg = <2>;
interrupt-parent = <&gpio3>;
interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
};
};
&sham {
status = "okay";
};
&aes {
status = "okay";
};
&gpio0 {
ti,no-reset-on-init;
};

View File

@@ -1,95 +0,0 @@
/*
* am335x-base0033.dts - Device Tree file for IGEP AQUILA EXPANSION
*
* Copyright (C) 2013 ISEE 2007 SL - http://www.isee.biz
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "am335x-igep0033.dtsi"
/ {
model = "IGEP COM AM335x on AQUILA Expansion";
compatible = "isee,am335x-base0033", "isee,am335x-igep0033", "ti,am33xx";
hdmi {
compatible = "ti,tilcdc,slave";
i2c = <&i2c0>;
pinctrl-names = "default", "off";
pinctrl-0 = <&nxp_hdmi_pins>;
pinctrl-1 = <&nxp_hdmi_off_pins>;
status = "okay";
};
leds_base {
pinctrl-names = "default";
pinctrl-0 = <&leds_base_pins>;
compatible = "gpio-leds";
led0 {
label = "base:red:user";
gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; /* gpio1_21 */
default-state = "off";
};
led1 {
label = "base:green:user";
gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>; /* gpio2_0 */
default-state = "off";
};
};
};
&am33xx_pinmux {
nxp_hdmi_pins: pinmux_nxp_hdmi_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE3) /* xdma_event_intr0.clkout1 */
AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0 */
AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1 */
AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2 */
AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3 */
AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4 */
AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5 */
AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6 */
AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7 */
AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8 */
AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9 */
AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10 */
AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11 */
AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12 */
AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13 */
AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14 */
AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15 */
AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0) /* lcd_vsync */
AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0) /* lcd_hsync */
AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0) /* lcd_pclk */
AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0) /* lcd_ac_bias_en */
>;
};
nxp_hdmi_off_pins: pinmux_nxp_hdmi_off_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE3) /* xdma_event_intr0.clkout1 */
>;
};
leds_base_pins: pinmux_leds_base_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */
AM33XX_IOPAD(0x888, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn3.gpio2_0 */
>;
};
};
&lcdc {
status = "okay";
};
&i2c0 {
eeprom: eeprom@50 {
compatible = "at,24c256";
reg = <0x50>;
};
};

View File

@@ -1,395 +0,0 @@
/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/ {
cpus {
cpu@0 {
cpu0-supply = <&dcdc2_reg>;
};
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>; /* 256 MB */
};
chosen {
stdout-path = &uart0;
};
leds {
pinctrl-names = "default";
pinctrl-0 = <&user_leds_s0>;
compatible = "gpio-leds";
led2 {
label = "beaglebone:green:heartbeat";
gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
default-state = "off";
};
led3 {
label = "beaglebone:green:mmc0";
gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "mmc0";
default-state = "off";
};
led4 {
label = "beaglebone:green:usr2";
gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "cpu0";
default-state = "off";
};
led5 {
label = "beaglebone:green:usr3";
gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "mmc1";
default-state = "off";
};
};
vmmcsd_fixed: fixedregulator0 {
compatible = "regulator-fixed";
regulator-name = "vmmcsd_fixed";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
};
&am33xx_pinmux {
pinctrl-names = "default";
pinctrl-0 = <&clkout2_pin>;
user_leds_s0: user_leds_s0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */
AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a6.gpio1_22 */
AM33XX_IOPAD(0x85c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a7.gpio1_23 */
AM33XX_IOPAD(0x860, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a8.gpio1_24 */
>;
};
i2c0_pins: pinmux_i2c0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
>;
};
i2c2_pins: pinmux_i2c2_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_ctsn.i2c2_sda */
AM33XX_IOPAD(0x97c, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_rtsn.i2c2_scl */
>;
};
uart0_pins: pinmux_uart0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
>;
};
clkout2_pin: pinmux_clkout2_pin {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
>;
};
cpsw_default: cpsw_default {
pinctrl-single,pins = <
/* Slave 1 */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxerr.mii1_rxerr */
AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txen.mii1_txen */
AM33XX_IOPAD(0x918, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxdv.mii1_rxdv */
AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd3.mii1_txd3 */
AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd2.mii1_txd2 */
AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd1.mii1_txd1 */
AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd0.mii1_txd0 */
AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_txclk.mii1_txclk */
AM33XX_IOPAD(0x930, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxclk.mii1_rxclk */
AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd3.mii1_rxd3 */
AM33XX_IOPAD(0x938, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd2.mii1_rxd2 */
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd1.mii1_rxd1 */
AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd0.mii1_rxd0 */
>;
};
cpsw_sleep: cpsw_sleep {
pinctrl-single,pins = <
/* Slave 1 reset value */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
davinci_mdio_default: davinci_mdio_default {
pinctrl-single,pins = <
/* MDIO */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
>;
};
davinci_mdio_sleep: davinci_mdio_sleep {
pinctrl-single,pins = <
/* MDIO reset value */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* GPIO0_6 */
>;
};
emmc_pins: pinmux_emmc_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
>;
};
};
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
status = "okay";
};
&usb {
status = "okay";
};
&usb_ctrl_mod {
status = "okay";
};
&usb0_phy {
status = "okay";
};
&usb1_phy {
status = "okay";
};
&usb0 {
status = "okay";
dr_mode = "peripheral";
};
&usb1 {
status = "okay";
dr_mode = "host";
};
&cppi41dma {
status = "okay";
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
status = "okay";
clock-frequency = <400000>;
tps: tps@24 {
reg = <0x24>;
};
baseboard_eeprom: baseboard_eeprom@50 {
compatible = "at,24c256";
reg = <0x50>;
#address-cells = <1>;
#size-cells = <1>;
baseboard_data: baseboard_data@0 {
reg = <0 0x100>;
};
};
};
&i2c2 {
pinctrl-names = "default";
pinctrl-0 = <&i2c2_pins>;
status = "okay";
clock-frequency = <100000>;
cape_eeprom0: cape_eeprom0@54 {
compatible = "at,24c256";
reg = <0x54>;
#address-cells = <1>;
#size-cells = <1>;
cape0_data: cape_data@0 {
reg = <0 0x100>;
};
};
cape_eeprom1: cape_eeprom1@55 {
compatible = "at,24c256";
reg = <0x55>;
#address-cells = <1>;
#size-cells = <1>;
cape1_data: cape_data@0 {
reg = <0 0x100>;
};
};
cape_eeprom2: cape_eeprom2@56 {
compatible = "at,24c256";
reg = <0x56>;
#address-cells = <1>;
#size-cells = <1>;
cape2_data: cape_data@0 {
reg = <0 0x100>;
};
};
cape_eeprom3: cape_eeprom3@57 {
compatible = "at,24c256";
reg = <0x57>;
#address-cells = <1>;
#size-cells = <1>;
cape3_data: cape_data@0 {
reg = <0 0x100>;
};
};
};
/include/ "tps65217.dtsi"
&tps {
/*
* Configure pmic to enter OFF-state instead of SLEEP-state ("RTC-only
* mode") at poweroff. Most BeagleBone versions do not support RTC-only
* mode and risk hardware damage if this mode is entered.
*
* For details, see linux-omap mailing list May 2015 thread
* [PATCH] ARM: dts: am335x-bone* enable pmic-shutdown-controller
* In particular, messages:
* http://www.spinics.net/lists/linux-omap/msg118585.html
* http://www.spinics.net/lists/linux-omap/msg118615.html
*
* You can override this later with
* &tps { /delete-property/ ti,pmic-shutdown-controller; }
* if you want to use RTC-only mode and made sure you are not affected
* by the hardware problems. (Tip: double-check by performing a current
* measurement after shutdown: it should be less than 1 mA.)
*/
ti,pmic-shutdown-controller;
regulators {
dcdc1_reg: regulator@0 {
regulator-name = "vdds_dpr";
regulator-always-on;
};
dcdc2_reg: regulator@1 {
/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
regulator-name = "vdd_mpu";
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <1351500>;
regulator-boot-on;
regulator-always-on;
};
dcdc3_reg: regulator@2 {
/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
regulator-name = "vdd_core";
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <1150000>;
regulator-boot-on;
regulator-always-on;
};
ldo1_reg: regulator@3 {
regulator-name = "vio,vrtc,vdds";
regulator-always-on;
};
ldo2_reg: regulator@4 {
regulator-name = "vdd_3v3aux";
regulator-always-on;
};
ldo3_reg: regulator@5 {
regulator-name = "vdd_1v8";
regulator-always-on;
};
ldo4_reg: regulator@6 {
regulator-name = "vdd_3v3a";
regulator-always-on;
};
};
};
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <0>;
phy-mode = "mii";
};
&mac {
slaves = <1>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
status = "okay";
};
&davinci_mdio {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
status = "okay";
};
&mmc1 {
status = "okay";
bus-width = <0x4>;
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins>;
cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
};
&aes {
status = "okay";
};
&sham {
status = "okay";
};

View File

@@ -1,26 +0,0 @@
/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
#include "am33xx.dtsi"
#include "am335x-bone-common.dtsi"
/ {
model = "TI AM335x BeagleBone";
compatible = "ti,am335x-bone", "ti,am33xx";
};
&ldo3_reg {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
&mmc1 {
vmmc-supply = <&ldo3_reg>;
};

View File

@@ -1,159 +0,0 @@
/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
#include "am33xx.dtsi"
#include "am335x-bone-common.dtsi"
#include <dt-bindings/display/tda998x.h>
/ {
model = "TI AM335x BeagleBone Black";
compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
};
&ldo3_reg {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
&mmc1 {
vmmc-supply = <&vmmcsd_fixed>;
};
&mmc2 {
vmmc-supply = <&vmmcsd_fixed>;
pinctrl-names = "default";
pinctrl-0 = <&emmc_pins>;
bus-width = <8>;
status = "okay";
};
&am33xx_pinmux {
nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */
AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */
AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */
AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */
AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */
AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */
AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */
AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */
AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */
AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */
AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */
AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */
AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */
AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */
AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */
AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */
AM33XX_IOPAD(0x8e0, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_vsync.lcd_vsync */
AM33XX_IOPAD(0x8e4, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_hsync.lcd_hsync */
AM33XX_IOPAD(0x8e8, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_pclk.lcd_pclk */
AM33XX_IOPAD(0x8ec, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */
>;
};
nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr0 */
>;
};
mcasp0_pins: mcasp0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLUP | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
AM33XX_IOPAD(0x994, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
AM33XX_IOPAD(0x990, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
AM33XX_IOPAD(0x86c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.GPIO1_27 */
>;
};
};
&lcdc {
status = "okay";
port {
lcdc_0: endpoint@0 {
remote-endpoint = <&hdmi_0>;
};
};
};
&i2c0 {
tda19988: tda19988 {
compatible = "nxp,tda998x";
reg = <0x70>;
pinctrl-names = "default", "off";
pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
#sound-dai-cells = <0>;
audio-ports = < TDA998x_I2S 0x03>;
ports {
port@0 {
hdmi_0: endpoint@0 {
remote-endpoint = <&lcdc_0>;
};
};
};
};
};
&rtc {
system-power-controller;
};
&mcasp0 {
#sound-dai-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&mcasp0_pins>;
status = "okay";
op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>;
serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
0 0 1 0
>;
tx-num-evt = <32>;
rx-num-evt = <32>;
};
/ {
clk_mcasp0_fixed: clk_mcasp0_fixed {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24576000>;
};
clk_mcasp0: clk_mcasp0 {
#clock-cells = <0>;
compatible = "gpio-gate-clock";
clocks = <&clk_mcasp0_fixed>;
enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
};
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "TI BeagleBone Black";
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&dailink0_master>;
simple-audio-card,frame-master = <&dailink0_master>;
dailink0_master: simple-audio-card,cpu {
sound-dai = <&mcasp0>;
clocks = <&clk_mcasp0>;
};
simple-audio-card,codec {
sound-dai = <&tda19988>;
};
};
};

View File

@@ -1,53 +0,0 @@
/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
#include "am33xx.dtsi"
#include "am335x-bone-common.dtsi"
/ {
model = "TI AM335x BeagleBone Green";
compatible = "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
};
&ldo3_reg {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
&mmc1 {
vmmc-supply = <&vmmcsd_fixed>;
};
&mmc2 {
vmmc-supply = <&vmmcsd_fixed>;
pinctrl-names = "default";
pinctrl-0 = <&emmc_pins>;
bus-width = <8>;
status = "okay";
};
&am33xx_pinmux {
uart2_pins: uart2_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1) /* spi0_sclk.uart2_rxd */
AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1) /* spi0_d0.uart2_txd */
>;
};
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
status = "okay";
};
&rtc {
system-power-controller;
};

View File

@@ -1,187 +0,0 @@
/*
* Copyright (C) 2015 Jablotron s.r.o. -- http://www.jablotron.com/
* Author: Rostislav Lisovy <lisovy@jablotron.cz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
#include "am335x-chilisom.dtsi"
/ {
model = "AM335x Chiliboard";
compatible = "grinn,am335x-chiliboard", "grinn,am335x-chilisom",
"ti,am33xx";
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&led_gpio_pins>;
led0 {
label = "led0";
gpios = <&gpio3 7 GPIO_ACTIVE_LOW>;
default-state = "keep";
linux,default-trigger = "heartbeat";
};
led1 {
label = "led1";
gpios = <&gpio3 8 GPIO_ACTIVE_LOW>;
default-state = "keep";
};
};
};
&am33xx_pinmux {
uart0_pins: pinmux_uart0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
>;
};
cpsw_default: cpsw_default {
pinctrl-single,pins = <
/* Slave 1 */
AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxerr.rmii1_rxerr */
AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txen.rmii1_txen */
AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */
AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */
AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */
AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_ref_clk.rmii_ref_clk */
>;
};
cpsw_sleep: cpsw_sleep {
pinctrl-single,pins = <
/* Slave 1 reset value */
AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
davinci_mdio_default: davinci_mdio_default {
pinctrl-single,pins = <
/* mdio_data.mdio_data */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)
/* mdio_clk.mdio_clk */
AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)
>;
};
davinci_mdio_sleep: davinci_mdio_sleep {
pinctrl-single,pins = <
/* MDIO reset value */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
usb1_drvvbus: usb1_drvvbus {
pinctrl-single,pins = <
AM33XX_IOPAD(0xa34, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* usb1_drvvbus.usb1_drvvbus */
>;
};
sd_pins: pinmux_sd_card {
pinctrl-single,pins = <
AM33XX_IOPAD(0x8f0, PIN_INPUT | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
AM33XX_IOPAD(0x8f4, PIN_INPUT | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
AM33XX_IOPAD(0x8f8, PIN_INPUT | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
AM33XX_IOPAD(0x8fc, PIN_INPUT | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
AM33XX_IOPAD(0x900, PIN_INPUT | MUX_MODE0) /* mmc0_clk.mmc0_clk */
AM33XX_IOPAD(0x904, PIN_INPUT | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
>;
};
led_gpio_pins: led_gpio_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9e4, PIN_OUTPUT | MUX_MODE7) /* emu0.gpio3_7 */
AM33XX_IOPAD(0x9e8, PIN_OUTPUT | MUX_MODE7) /* emu1.gpio3_8 */
>;
};
};
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
status = "okay";
};
&ldo4_reg {
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
/* Ethernet */
&mac {
slaves = <1>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
status = "okay";
};
&davinci_mdio {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
status = "okay";
};
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <0>;
phy-mode = "rmii";
};
&phy_sel {
rmii-clock-ext;
};
/* USB */
&usb {
status = "okay";
};
&usb_ctrl_mod {
status = "okay";
};
&usb1_phy {
status = "okay";
};
&usb1 {
pinctrl-names = "default";
pinctrl-0 = <&usb1_drvvbus>;
status = "okay";
dr_mode = "host";
};
&cppi41dma {
status = "okay";
};
/* microSD */
&mmc1 {
pinctrl-names = "default";
pinctrl-0 = <&sd_pins>;
vmmc-supply = <&ldo4_reg>;
bus-width = <0x4>;
cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
status = "okay";
};

View File

@@ -1,178 +0,0 @@
/*
* Copyright (C) 2015 Jablotron s.r.o. -- http://www.jablotron.com/
* Author: Rostislav Lisovy <lisovy@jablotron.cz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "am33xx.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
/ {
model = "Grinn AM335x ChiliSOM";
compatible = "grinn,am335x-chilisom", "ti,am33xx";
cpus {
cpu@0 {
cpu0-supply = <&dcdc2_reg>;
};
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x20000000>; /* 512 MB */
};
};
&am33xx_pinmux {
pinctrl-names = "default";
i2c0_pins: pinmux_i2c0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
>;
};
nandflash_pins: nandflash_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x800, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */
AM33XX_IOPAD(0x804, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */
AM33XX_IOPAD(0x808, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */
AM33XX_IOPAD(0x80c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */
AM33XX_IOPAD(0x810, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */
AM33XX_IOPAD(0x814, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */
AM33XX_IOPAD(0x818, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */
AM33XX_IOPAD(0x81c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */
AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */
AM33XX_IOPAD(0x87c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */
AM33XX_IOPAD(0x890, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */
AM33XX_IOPAD(0x894, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */
AM33XX_IOPAD(0x898, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_wen.gpmc_wen */
AM33XX_IOPAD(0x89c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */
>;
};
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
status = "okay";
clock-frequency = <400000>;
tps: tps@24 {
reg = <0x24>;
};
};
/include/ "tps65217.dtsi"
&tps {
regulators {
dcdc1_reg: regulator@0 {
regulator-name = "vdds_dpr";
regulator-always-on;
};
dcdc2_reg: regulator@1 {
/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
regulator-name = "vdd_mpu";
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <1325000>;
regulator-boot-on;
regulator-always-on;
};
dcdc3_reg: regulator@2 {
/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
regulator-name = "vdd_core";
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <1150000>;
regulator-boot-on;
regulator-always-on;
};
ldo1_reg: regulator@3 {
regulator-name = "vio,vrtc,vdds";
regulator-boot-on;
regulator-always-on;
};
ldo2_reg: regulator@4 {
regulator-name = "vdd_3v3aux";
regulator-boot-on;
regulator-always-on;
};
ldo3_reg: regulator@5 {
regulator-name = "vdd_1v8";
regulator-boot-on;
regulator-always-on;
};
ldo4_reg: regulator@6 {
regulator-name = "vdd_3v3d";
regulator-boot-on;
regulator-always-on;
};
};
};
&rtc {
system-power-controller;
pinctrl-0 = <&ext_wakeup>;
pinctrl-names = "default";
ext_wakeup: ext-wakeup {
pins = "ext_wakeup0";
input-enable;
};
};
/* NAND Flash */
&elm {
status = "okay";
};
&gpmc {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&nandflash_pins>;
ranges = <0 0 0x08000000 0x01000000>; /* CS0 0 @addr 0x08000000, size 0x01000000 */
nand@0,0 {
compatible = "ti,omap2-nand";
reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
ti,nand-ecc-opt = "bch8";
ti,elm-id = <&elm>;
nand-bus-width = <8>;
gpmc,device-width = <1>;
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;
gpmc,cs-rd-off-ns = <44>;
gpmc,cs-wr-off-ns = <44>;
gpmc,adv-on-ns = <6>;
gpmc,adv-rd-off-ns = <34>;
gpmc,adv-wr-off-ns = <44>;
gpmc,we-on-ns = <0>;
gpmc,we-off-ns = <40>;
gpmc,oe-on-ns = <0>;
gpmc,oe-off-ns = <54>;
gpmc,access-ns = <64>;
gpmc,rd-cycle-ns = <82>;
gpmc,wr-cycle-ns = <82>;
gpmc,bus-turnaround-ns = <0>;
gpmc,cycle2cycle-delay-ns = <0>;
gpmc,clk-activation-ns = <0>;
gpmc,wr-access-ns = <40>;
gpmc,wr-data-mux-bus-ns = <0>;
};
};

View File

@@ -1,569 +0,0 @@
/*
* am335x-cm-t335.dts - Device Tree file for Compulab CM-T335
*
* Copyright (C) 2014 - 2015 CompuLab Ltd. - http://www.compulab.co.il/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
#include "am33xx.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
/ {
model = "CompuLab CM-T335";
compatible = "compulab,cm-t335", "ti,am33xx";
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x8000000>; /* 128 MB */
};
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&gpio_led_pins>;
led0 {
label = "cm_t335:green";
gpios = <&gpio2 0 GPIO_ACTIVE_LOW>; /* gpio2_0 */
linux,default-trigger = "heartbeat";
};
};
/* regulator for mmc */
vmmc_fixed: fixedregulator0 {
compatible = "regulator-fixed";
regulator-name = "vmmc_fixed";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
/* Regulator for WiFi */
vwlan_fixed: fixedregulator2 {
compatible = "regulator-fixed";
regulator-name = "vwlan_fixed";
gpio = <&gpio0 20 GPIO_ACTIVE_HIGH>; /* gpio0_20 */
enable-active-high;
regulator-boot-off;
};
backlight {
compatible = "pwm-backlight";
pwms = <&ecap0 0 50000 0>;
brightness-levels = <0 51 53 56 62 75 101 152 255>;
default-brightness-level = <8>;
};
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "cm-t335";
simple-audio-card,widgets =
"Microphone", "Mic Jack",
"Line", "Line In",
"Headphone", "Headphone Jack";
simple-audio-card,routing =
"Headphone Jack", "LHPOUT",
"Headphone Jack", "RHPOUT",
"LLINEIN", "Line In",
"RLINEIN", "Line In",
"MICIN", "Mic Jack";
simple-audio-card,format = "i2s";
simple-audio-card,bitclock-master = <&sound_master>;
simple-audio-card,frame-master = <&sound_master>;
simple-audio-card,cpu {
sound-dai = <&mcasp1>;
};
sound_master: simple-audio-card,codec {
sound-dai = <&tlv320aic23>;
system-clock-frequency = <12000000>;
};
};
};
&am33xx_pinmux {
pinctrl-names = "default";
pinctrl-0 = <&bluetooth_pins>;
i2c0_pins: pinmux_i2c0_pins {
pinctrl-single,pins = <
/* i2c0_sda.i2c0_sda */
AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0)
/* i2c0_scl.i2c0_scl */
AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0)
>;
};
i2c1_pins: pinmux_i2c1_pins {
pinctrl-single,pins = <
/* uart0_ctsn.i2c1_sda */
AM33XX_IOPAD(0x968, PIN_INPUT_PULLUP | MUX_MODE2)
/* uart0_rtsn.i2c1_scl */
AM33XX_IOPAD(0x96c, PIN_INPUT_PULLUP | MUX_MODE2)
>;
};
gpio_led_pins: pinmux_gpio_led_pins {
pinctrl-single,pins = <
/* gpmc_csn3.gpio2_0 */
AM33XX_IOPAD(0x888, PIN_OUTPUT | MUX_MODE7)
>;
};
nandflash_pins: pinmux_nandflash_pins {
pinctrl-single,pins = <
/* gpmc_ad0.gpmc_ad0 */
AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0)
/* gpmc_ad1.gpmc_ad1 */
AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0)
/* gpmc_ad2.gpmc_ad2 */
AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0)
/* gpmc_ad3.gpmc_ad3 */
AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0)
/* gpmc_ad4.gpmc_ad4 */
AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0)
/* gpmc_ad5.gpmc_ad5 */
AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0)
/* gpmc_ad6.gpmc_ad6 */
AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0)
/* gpmc_ad7.gpmc_ad7 */
AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0)
/* gpmc_wait0.gpmc_wait0 */
AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0)
/* gpmc_wpn.gpio0_30 */
AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7)
/* gpmc_csn0.gpmc_csn0 */
AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0)
/* gpmc_advn_ale.gpmc_advn_ale */
AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0)
/* gpmc_oen_ren.gpmc_oen_ren */
AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0)
/* gpmc_wen.gpmc_wen */
AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0)
/* gpmc_ben0_cle.gpmc_ben0_cle */
AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0)
>;
};
uart0_pins: pinmux_uart0_pins {
pinctrl-single,pins = <
/* uart0_rxd.uart0_rxd */
AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)
/* uart0_txd.uart0_txd */
AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)
>;
};
uart1_pins: pinmux_uart1_pins {
pinctrl-single,pins = <
/* uart1_ctsn.uart1_ctsn */
AM33XX_IOPAD(0x978, PIN_INPUT | MUX_MODE0)
/* uart1_rtsn.uart1_rtsn */
AM33XX_IOPAD(0x97C, PIN_OUTPUT_PULLDOWN | MUX_MODE0)
/* uart1_rxd.uart1_rxd */
AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0)
/* uart1_txd.uart1_txd */
AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0)
>;
};
dcan0_pins: pinmux_dcan0_pins {
pinctrl-single,pins = <
/* uart1_ctsn.dcan0_tx */
AM33XX_IOPAD(0x978, PIN_OUTPUT | MUX_MODE2)
/* uart1_rtsn.dcan0_rx */
AM33XX_IOPAD(0x97C, PIN_INPUT | MUX_MODE2)
>;
};
dcan1_pins: pinmux_dcan1_pins {
pinctrl-single,pins = <
/* uart1_rxd.dcan1_tx */
AM33XX_IOPAD(0x980, PIN_OUTPUT | MUX_MODE2)
/* uart1_txd.dcan1_rx */
AM33XX_IOPAD(0x984, PIN_INPUT | MUX_MODE2)
>;
};
ecap0_pins: pinmux_ecap0_pins {
pinctrl-single,pins = <
/* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out MODE0 */
AM33XX_IOPAD(0x964, 0x0)
>;
};
cpsw_default: cpsw_default {
pinctrl-single,pins = <
/* Slave 1 */
/* mii1_tx_en.rgmii1_tctl */
AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2)
/* mii1_rxdv.rgmii1_rctl */
AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2)
/* mii1_txd3.rgmii1_td3 */
AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)
/* mii1_txd2.rgmii1_td2 */
AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2)
/* mii1_txd1.rgmii1_td1 */
AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2)
/* mii1_txd0.rgmii1_td0 */
AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2)
/* mii1_txclk.rgmii1_tclk */
AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2)
/* mii1_rxclk.rgmii1_rclk */
AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2)
/* mii1_rxd3.rgmii1_rd3 */
AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2)
/* mii1_rxd2.rgmii1_rd2 */
AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2)
/* mii1_rxd1.rgmii1_rd1 */
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2)
/* mii1_rxd0.rgmii1_rd0 */
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2)
>;
};
cpsw_sleep: cpsw_sleep {
pinctrl-single,pins = <
/* Slave 1 reset value */
AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
davinci_mdio_default: davinci_mdio_default {
pinctrl-single,pins = <
/* mdio_data.mdio_data */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)
/* mdio_clk.mdio_clk */
AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)
>;
};
davinci_mdio_sleep: davinci_mdio_sleep {
pinctrl-single,pins = <
/* MDIO reset value */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
/* mmc0_dat3.mmc0_dat3 */
AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0)
/* mmc0_dat2.mmc0_dat2 */
AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0)
/* mmc0_dat1.mmc0_dat1 */
AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0)
/* mmc0_dat0.mmc0_dat0 */
AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0)
/* mmc0_clk.mmc0_clk */
AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0)
/* mmc0_cmd.mmc0_cmd */
AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0)
>;
};
spi0_pins: pinmux_spi0_pins {
pinctrl-single,pins = <
/* spi0_sclk.spi0_sclk */
AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE0)
/* spi0_d0.spi0_d0 */
AM33XX_IOPAD(0x954, PIN_OUTPUT_PULLUP | MUX_MODE0)
/* spi0_d1.spi0_d1 */
AM33XX_IOPAD(0x958, PIN_INPUT | MUX_MODE0)
/* spi0_cs0.spi0_cs0 */
AM33XX_IOPAD(0x95C, PIN_OUTPUT | MUX_MODE0)
/* spi0_cs1.spi0_cs1 */
AM33XX_IOPAD(0x960, PIN_OUTPUT | MUX_MODE0)
>;
};
/* wl1271 bluetooth */
bluetooth_pins: pinmux_bluetooth_pins {
pinctrl-single,pins = <
/* XDMA_EVENT_INTR0.gpio0_19 - bluetooth enable */
AM33XX_IOPAD(0x9b0, PIN_OUTPUT_PULLUP | MUX_MODE7)
>;
};
/* TLV320AIC23B codec */
mcasp1_pins: pinmux_mcasp1_pins {
pinctrl-single,pins = <
/* MII1_CRS.mcasp1_aclkx */
AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE4)
/* MII1_RX_ER.mcasp1_fsx */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE4)
/* MII1_COL.mcasp1_axr2 */
AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE4)
/* RMII1_REF_CLK.mcasp1_axr3 */
AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE4)
>;
};
/* wl1271 WiFi */
wifi_pins: pinmux_wifi_pins {
pinctrl-single,pins = <
/* EMU1.gpio3_8 - WiFi IRQ */
AM33XX_IOPAD(0x9e8, PIN_INPUT_PULLUP | MUX_MODE7)
/* XDMA_EVENT_INTR1.gpio0_20 - WiFi enable */
AM33XX_IOPAD(0x9b4, PIN_OUTPUT | MUX_MODE7)
>;
};
};
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
status = "okay";
};
/* WLS1271 bluetooth */
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>;
status = "okay";
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
status = "okay";
clock-frequency = <400000>;
/* CM-T335 board EEPROM */
eeprom: 24c02@50 {
compatible = "atmel,24c02";
reg = <0x50>;
pagesize = <16>;
};
/* Real Time Clock */
ext_rtc: em3027@56 {
compatible = "emmicro,em3027";
reg = <0x56>;
};
/* Audio codec */
tlv320aic23: codec@1a {
compatible = "ti,tlv320aic23";
reg = <0x1a>;
#sound-dai-cells= <0>;
status = "okay";
};
};
&usb {
status = "okay";
};
&usb_ctrl_mod {
status = "okay";
};
&usb0_phy {
status = "okay";
};
&usb0 {
status = "okay";
};
&cppi41dma {
status = "okay";
};
&epwmss0 {
status = "okay";
ecap0: ecap@48300100 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&ecap0_pins>;
};
};
&gpmc {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&nandflash_pins>;
ranges = <0 0 0x08000000 0x10000000>; /* CS0: NAND */
nand@0,0 {
compatible = "ti,omap2-nand";
reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
ti,nand-ecc-opt = "bch8";
ti,elm-id = <&elm>;
nand-bus-width = <8>;
gpmc,device-width = <1>;
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;
gpmc,cs-rd-off-ns = <44>;
gpmc,cs-wr-off-ns = <44>;
gpmc,adv-on-ns = <6>;
gpmc,adv-rd-off-ns = <34>;
gpmc,adv-wr-off-ns = <44>;
gpmc,we-on-ns = <0>;
gpmc,we-off-ns = <40>;
gpmc,oe-on-ns = <0>;
gpmc,oe-off-ns = <54>;
gpmc,access-ns = <64>;
gpmc,rd-cycle-ns = <82>;
gpmc,wr-cycle-ns = <82>;
gpmc,bus-turnaround-ns = <0>;
gpmc,cycle2cycle-delay-ns = <0>;
gpmc,clk-activation-ns = <0>;
gpmc,wr-access-ns = <40>;
gpmc,wr-data-mux-bus-ns = <0>;
/* MTD partition table */
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "spl";
reg = <0x00000000 0x00200000>;
};
partition@1 {
label = "uboot";
reg = <0x00200000 0x00100000>;
};
partition@2 {
label = "uboot environment";
reg = <0x00300000 0x00100000>;
};
partition@3 {
label = "dtb";
reg = <0x00400000 0x00100000>;
};
partition@4 {
label = "splash";
reg = <0x00500000 0x00400000>;
};
partition@5 {
label = "linux";
reg = <0x00900000 0x00600000>;
};
partition@6 {
label = "rootfs";
reg = <0x00F00000 0>;
};
};
};
&elm {
status = "okay";
};
&mac {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
slaves = <1>;
status = "okay";
};
&davinci_mdio {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
status = "okay";
};
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <0>;
phy-mode = "rgmii-txid";
};
&mmc1 {
status = "okay";
vmmc-supply = <&vmmc_fixed>;
bus-width = <4>;
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins>;
};
&dcan0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&dcan0_pins>;
};
&dcan1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&dcan1_pins>;
};
/* Touschscreen and analog digital converter */
&tscadc {
status = "okay";
tsc {
ti,wires = <4>;
ti,x-plate-resistance = <200>;
ti,coordinate-readouts = <5>;
ti,wire-config = <0x01 0x10 0x23 0x32>;
ti,charge-delay = <0x400>;
};
adc {
ti,adc-channels = <4 5 6 7>;
};
};
/* CPU audio */
&mcasp1 {
pinctrl-names = "default";
pinctrl-0 = <&mcasp1_pins>;
op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>;
/* 16 serializers */
num-serializer = <16>;
serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0
>;
tx-num-evt = <1>;
rx-num-evt = <1>;
#sound-dai-cells= <0>;
status = "okay";
};
&spi0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
ti,pindir-d0-out-d1-in = <1>;
/* WLS1271 WiFi */
wlcore: wlcore@1 {
compatible = "ti,wl1271";
pinctrl-names = "default";
pinctrl-0 = <&wifi_pins>;
reg = <1>;
spi-max-frequency = <48000000>;
clock-xtal;
ref-clock-frequency = <38400000>;
interrupt-parent = <&gpio3>;
interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
vwlan-supply = <&vwlan_fixed>;
};
};

View File

@@ -1,785 +0,0 @@
/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
#include "am33xx.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
/ {
model = "TI AM335x EVM";
compatible = "ti,am335x-evm", "ti,am33xx";
cpus {
cpu@0 {
cpu0-supply = <&vdd1_reg>;
};
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>; /* 256 MB */
};
vbat: fixedregulator0 {
compatible = "regulator-fixed";
regulator-name = "vbat";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-boot-on;
};
lis3_reg: fixedregulator1 {
compatible = "regulator-fixed";
regulator-name = "lis3_reg";
regulator-boot-on;
};
wlan_en_reg: fixedregulator2 {
compatible = "regulator-fixed";
regulator-name = "wlan-en-regulator";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
/* WLAN_EN GPIO for this board - Bank1, pin16 */
gpio = <&gpio1 16 0>;
/* WLAN card specific delay */
startup-delay-us = <70000>;
enable-active-high;
};
matrix_keypad: matrix_keypad0 {
compatible = "gpio-matrix-keypad";
debounce-delay-ms = <5>;
col-scan-delay-us = <2>;
row-gpios = <&gpio1 25 GPIO_ACTIVE_HIGH /* Bank1, pin25 */
&gpio1 26 GPIO_ACTIVE_HIGH /* Bank1, pin26 */
&gpio1 27 GPIO_ACTIVE_HIGH>; /* Bank1, pin27 */
col-gpios = <&gpio1 21 GPIO_ACTIVE_HIGH /* Bank1, pin21 */
&gpio1 22 GPIO_ACTIVE_HIGH>; /* Bank1, pin22 */
linux,keymap = <0x0000008b /* MENU */
0x0100009e /* BACK */
0x02000069 /* LEFT */
0x0001006a /* RIGHT */
0x0101001c /* ENTER */
0x0201006c>; /* DOWN */
};
gpio_keys: volume_keys0 {
compatible = "gpio-keys";
#address-cells = <1>;
#size-cells = <0>;
autorepeat;
switch9 {
label = "volume-up";
linux,code = <115>;
gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
wakeup-source;
};
switch10 {
label = "volume-down";
linux,code = <114>;
gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
wakeup-source;
};
};
backlight {
compatible = "pwm-backlight";
pwms = <&ecap0 0 50000 0>;
brightness-levels = <0 51 53 56 62 75 101 152 255>;
default-brightness-level = <8>;
};
panel {
compatible = "ti,tilcdc,panel";
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&lcd_pins_s0>;
panel-info {
ac-bias = <255>;
ac-bias-intrpt = <0>;
dma-burst-sz = <16>;
bpp = <32>;
fdd = <0x80>;
sync-edge = <0>;
sync-ctrl = <1>;
raster-order = <0>;
fifo-th = <0>;
};
display-timings {
800x480p62 {
clock-frequency = <30000000>;
hactive = <800>;
vactive = <480>;
hfront-porch = <39>;
hback-porch = <39>;
hsync-len = <47>;
vback-porch = <29>;
vfront-porch = <13>;
vsync-len = <2>;
hsync-active = <1>;
vsync-active = <1>;
};
};
};
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "AM335x-EVM";
simple-audio-card,widgets =
"Headphone", "Headphone Jack",
"Line", "Line In";
simple-audio-card,routing =
"Headphone Jack", "HPLOUT",
"Headphone Jack", "HPROUT",
"LINE1L", "Line In",
"LINE1R", "Line In";
simple-audio-card,format = "dsp_b";
simple-audio-card,bitclock-master = <&sound_master>;
simple-audio-card,frame-master = <&sound_master>;
simple-audio-card,bitclock-inversion;
simple-audio-card,cpu {
sound-dai = <&mcasp1>;
};
sound_master: simple-audio-card,codec {
sound-dai = <&tlv320aic3106>;
system-clock-frequency = <12000000>;
};
};
};
&am33xx_pinmux {
pinctrl-names = "default";
pinctrl-0 = <&matrix_keypad_s0 &volume_keys_s0 &clkout2_pin>;
matrix_keypad_s0: matrix_keypad_s0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */
AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a6.gpio1_22 */
AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a9.gpio1_25 */
AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a10.gpio1_26 */
AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_a11.gpio1_27 */
>;
};
volume_keys_s0: volume_keys_s0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x950, PIN_INPUT_PULLDOWN | MUX_MODE7) /* spi0_sclk.gpio0_2 */
AM33XX_IOPAD(0x954, PIN_INPUT_PULLDOWN | MUX_MODE7) /* spi0_d0.gpio0_3 */
>;
};
i2c0_pins: pinmux_i2c0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
>;
};
i2c1_pins: pinmux_i2c1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_d1.i2c1_sda */
AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_cs0.i2c1_scl */
>;
};
uart0_pins: pinmux_uart0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
>;
};
uart1_pins: pinmux_uart1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x978, PIN_INPUT | MUX_MODE0) /* uart1_ctsn.uart1_ctsn */
AM33XX_IOPAD(0x97C, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_rtsn.uart1_rtsn */
AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0) /* uart1_rxd.uart1_rxd */
AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_txd.uart1_txd */
>;
};
clkout2_pin: pinmux_clkout2_pin {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
>;
};
nandflash_pins_s0: nandflash_pins_s0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */
AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */
AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */
AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */
AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */
AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */
AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */
AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */
AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */
AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */
AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */
AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */
AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */
AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */
AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */
>;
};
ecap0_pins: backlight_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x964, MUX_MODE0) /* eCAP0_in_PWM0_out.eCAP0_in_PWM0_out */
>;
};
cpsw_default: cpsw_default {
pinctrl-single,pins = <
/* Slave 1 */
AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */
AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */
AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */
AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */
AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */
AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */
AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */
AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */
AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */
AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */
>;
};
cpsw_sleep: cpsw_sleep {
pinctrl-single,pins = <
/* Slave 1 reset value */
AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
davinci_mdio_default: davinci_mdio_default {
pinctrl-single,pins = <
/* MDIO */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
>;
};
davinci_mdio_sleep: davinci_mdio_sleep {
pinctrl-single,pins = <
/* MDIO reset value */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
>;
};
mmc3_pins: pinmux_mmc3_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a1.mmc2_dat0, INPUT_PULLUP | MODE3 */
AM33XX_IOPAD(0x848, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a2.mmc2_dat1, INPUT_PULLUP | MODE3 */
AM33XX_IOPAD(0x84c, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a3.mmc2_dat2, INPUT_PULLUP | MODE3 */
AM33XX_IOPAD(0x878, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_ben1.mmc2_dat3, INPUT_PULLUP | MODE3 */
AM33XX_IOPAD(0x888, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_csn3.mmc2_cmd, INPUT_PULLUP | MODE3 */
AM33XX_IOPAD(0x88c, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_clk.mmc2_clk, INPUT_PULLUP | MODE3 */
>;
};
wlan_pins: pinmux_wlan_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a0.gpio1_16 */
AM33XX_IOPAD(0x99c, PIN_INPUT | MUX_MODE7) /* mcasp0_ahclkr.gpio3_17 */
AM33XX_IOPAD(0x9ac, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* mcasp0_ahclkx.gpio3_21 */
>;
};
lcd_pins_s0: lcd_pins_s0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x820, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad8.lcd_data23 */
AM33XX_IOPAD(0x824, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad9.lcd_data22 */
AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad10.lcd_data21 */
AM33XX_IOPAD(0x82c, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad11.lcd_data20 */
AM33XX_IOPAD(0x830, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad12.lcd_data19 */
AM33XX_IOPAD(0x834, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad13.lcd_data18 */
AM33XX_IOPAD(0x838, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad14.lcd_data17 */
AM33XX_IOPAD(0x83c, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad15.lcd_data16 */
AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */
AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */
AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */
AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */
AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */
AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */
AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */
AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */
AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */
AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */
AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */
AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */
AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */
AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */
AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */
AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */
AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0) /* lcd_vsync.lcd_vsync */
AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0) /* lcd_hsync.lcd_hsync */
AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0) /* lcd_pclk.lcd_pclk */
AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */
>;
};
mcasp1_pins: mcasp1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */
AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */
AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
>;
};
mcasp1_pins_sleep: mcasp1_pins_sleep {
pinctrl-single,pins = <
AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
dcan1_pins_default: dcan1_pins_default {
pinctrl-single,pins = <
AM33XX_IOPAD(0x968, PIN_OUTPUT | MUX_MODE2) /* uart0_ctsn.d_can1_tx */
AM33XX_IOPAD(0x96c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* uart0_rtsn.d_can1_rx */
>;
};
};
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
status = "okay";
};
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>;
status = "okay";
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
status = "okay";
clock-frequency = <400000>;
tps: tps@2d {
reg = <0x2d>;
};
};
&usb {
status = "okay";
};
&usb_ctrl_mod {
status = "okay";
};
&usb0_phy {
status = "okay";
};
&usb1_phy {
status = "okay";
};
&usb0 {
status = "okay";
};
&usb1 {
status = "okay";
dr_mode = "host";
};
&cppi41dma {
status = "okay";
};
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
status = "okay";
clock-frequency = <100000>;
lis331dlh: lis331dlh@18 {
compatible = "st,lis331dlh", "st,lis3lv02d";
reg = <0x18>;
Vdd-supply = <&lis3_reg>;
Vdd_IO-supply = <&lis3_reg>;
st,click-single-x;
st,click-single-y;
st,click-single-z;
st,click-thresh-x = <10>;
st,click-thresh-y = <10>;
st,click-thresh-z = <10>;
st,irq1-click;
st,irq2-click;
st,wakeup-x-lo;
st,wakeup-x-hi;
st,wakeup-y-lo;
st,wakeup-y-hi;
st,wakeup-z-lo;
st,wakeup-z-hi;
st,min-limit-x = <120>;
st,min-limit-y = <120>;
st,min-limit-z = <140>;
st,max-limit-x = <550>;
st,max-limit-y = <550>;
st,max-limit-z = <750>;
};
tsl2550: tsl2550@39 {
compatible = "taos,tsl2550";
reg = <0x39>;
};
tmp275: tmp275@48 {
compatible = "ti,tmp275";
reg = <0x48>;
};
tlv320aic3106: tlv320aic3106@1b {
#sound-dai-cells = <0>;
compatible = "ti,tlv320aic3106";
reg = <0x1b>;
status = "okay";
/* Regulators */
AVDD-supply = <&vaux2_reg>;
IOVDD-supply = <&vaux2_reg>;
DRVDD-supply = <&vaux2_reg>;
DVDD-supply = <&vbat>;
};
};
&lcdc {
status = "okay";
blue-and-red-wiring = "crossed";
};
&elm {
status = "okay";
};
&epwmss0 {
status = "okay";
ecap0: ecap@48300100 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&ecap0_pins>;
};
};
&gpmc {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&nandflash_pins_s0>;
ranges = <0 0 0x08000000 0x1000000>; /* CS0: 16MB for NAND */
nand@0,0 {
compatible = "ti,omap2-nand";
reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
ti,nand-ecc-opt = "bch8";
ti,elm-id = <&elm>;
nand-bus-width = <8>;
gpmc,device-width = <1>;
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;
gpmc,cs-rd-off-ns = <44>;
gpmc,cs-wr-off-ns = <44>;
gpmc,adv-on-ns = <6>;
gpmc,adv-rd-off-ns = <34>;
gpmc,adv-wr-off-ns = <44>;
gpmc,we-on-ns = <0>;
gpmc,we-off-ns = <40>;
gpmc,oe-on-ns = <0>;
gpmc,oe-off-ns = <54>;
gpmc,access-ns = <64>;
gpmc,rd-cycle-ns = <82>;
gpmc,wr-cycle-ns = <82>;
gpmc,bus-turnaround-ns = <0>;
gpmc,cycle2cycle-delay-ns = <0>;
gpmc,clk-activation-ns = <0>;
gpmc,wr-access-ns = <40>;
gpmc,wr-data-mux-bus-ns = <0>;
/* MTD partition table */
/* All SPL-* partitions are sized to minimal length
* which can be independently programmable. For
* NAND flash this is equal to size of erase-block */
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "NAND.SPL";
reg = <0x00000000 0x000020000>;
};
partition@1 {
label = "NAND.SPL.backup1";
reg = <0x00020000 0x00020000>;
};
partition@2 {
label = "NAND.SPL.backup2";
reg = <0x00040000 0x00020000>;
};
partition@3 {
label = "NAND.SPL.backup3";
reg = <0x00060000 0x00020000>;
};
partition@4 {
label = "NAND.u-boot-spl-os";
reg = <0x00080000 0x00040000>;
};
partition@5 {
label = "NAND.u-boot";
reg = <0x000C0000 0x00100000>;
};
partition@6 {
label = "NAND.u-boot-env";
reg = <0x001C0000 0x00020000>;
};
partition@7 {
label = "NAND.u-boot-env.backup1";
reg = <0x001E0000 0x00020000>;
};
partition@8 {
label = "NAND.kernel";
reg = <0x00200000 0x00800000>;
};
partition@9 {
label = "NAND.file-system";
reg = <0x00A00000 0x0F600000>;
};
};
};
#include "tps65910.dtsi"
&mcasp1 {
#sound-dai-cells = <0>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&mcasp1_pins>;
pinctrl-1 = <&mcasp1_pins_sleep>;
status = "okay";
op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>;
/* 4 serializers */
serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
0 0 1 2
>;
tx-num-evt = <32>;
rx-num-evt = <32>;
};
&tps {
vcc1-supply = <&vbat>;
vcc2-supply = <&vbat>;
vcc3-supply = <&vbat>;
vcc4-supply = <&vbat>;
vcc5-supply = <&vbat>;
vcc6-supply = <&vbat>;
vcc7-supply = <&vbat>;
vccio-supply = <&vbat>;
regulators {
vrtc_reg: regulator@0 {
regulator-always-on;
};
vio_reg: regulator@1 {
regulator-always-on;
};
vdd1_reg: regulator@2 {
/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
regulator-name = "vdd_mpu";
regulator-min-microvolt = <912500>;
regulator-max-microvolt = <1351500>;
regulator-boot-on;
regulator-always-on;
};
vdd2_reg: regulator@3 {
/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
regulator-name = "vdd_core";
regulator-min-microvolt = <912500>;
regulator-max-microvolt = <1150000>;
regulator-boot-on;
regulator-always-on;
};
vdd3_reg: regulator@4 {
regulator-always-on;
};
vdig1_reg: regulator@5 {
regulator-always-on;
};
vdig2_reg: regulator@6 {
regulator-always-on;
};
vpll_reg: regulator@7 {
regulator-always-on;
};
vdac_reg: regulator@8 {
regulator-always-on;
};
vaux1_reg: regulator@9 {
regulator-always-on;
};
vaux2_reg: regulator@10 {
regulator-always-on;
};
vaux33_reg: regulator@11 {
regulator-always-on;
};
vmmc_reg: regulator@12 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
};
};
&mac {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
status = "okay";
};
&davinci_mdio {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
status = "okay";
};
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <0>;
phy-mode = "rgmii-txid";
};
&cpsw_emac1 {
phy_id = <&davinci_mdio>, <1>;
phy-mode = "rgmii-txid";
};
&tscadc {
status = "okay";
tsc {
ti,wires = <4>;
ti,x-plate-resistance = <200>;
ti,coordinate-readouts = <5>;
ti,wire-config = <0x00 0x11 0x22 0x33>;
ti,charge-delay = <0x400>;
};
adc {
ti,adc-channels = <4 5 6 7>;
};
};
&mmc1 {
status = "okay";
vmmc-supply = <&vmmc_reg>;
bus-width = <4>;
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins>;
cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
};
&mmc3 {
/* these are on the crossbar and are outlined in the
xbar-event-map element */
dmas = <&edma_xbar 12 0 1
&edma_xbar 13 0 2>;
dma-names = "tx", "rx";
status = "okay";
vmmc-supply = <&wlan_en_reg>;
bus-width = <4>;
pinctrl-names = "default";
pinctrl-0 = <&mmc3_pins &wlan_pins>;
ti,non-removable;
ti,needs-special-hs-handling;
cap-power-off-card;
keep-power-in-suspend;
#address-cells = <1>;
#size-cells = <0>;
wlcore: wlcore@0 {
compatible = "ti,wl1835";
reg = <2>;
interrupt-parent = <&gpio3>;
interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
};
};
&sham {
status = "okay";
};
&aes {
status = "okay";
};
&dcan1 {
status = "disabled"; /* Enable only if Profile 1 is selected */
pinctrl-names = "default";
pinctrl-0 = <&dcan1_pins_default>;
};

View File

@@ -1,718 +0,0 @@
/*
* Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* AM335x Starter Kit
* http://www.ti.com/tool/tmdssk3358
*/
/dts-v1/;
#include "am33xx.dtsi"
#include <dt-bindings/pwm/pwm.h>
#include <dt-bindings/interrupt-controller/irq.h>
/ {
model = "TI AM335x EVM-SK";
compatible = "ti,am335x-evmsk", "ti,am33xx";
cpus {
cpu@0 {
cpu0-supply = <&vdd1_reg>;
};
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>; /* 256 MB */
};
vbat: fixedregulator0 {
compatible = "regulator-fixed";
regulator-name = "vbat";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-boot-on;
};
lis3_reg: fixedregulator1 {
compatible = "regulator-fixed";
regulator-name = "lis3_reg";
regulator-boot-on;
};
wl12xx_vmmc: fixedregulator2 {
pinctrl-names = "default";
pinctrl-0 = <&wl12xx_gpio>;
compatible = "regulator-fixed";
regulator-name = "vwl1271";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
gpio = <&gpio1 29 0>;
startup-delay-us = <70000>;
enable-active-high;
};
vtt_fixed: fixedregulator3 {
compatible = "regulator-fixed";
regulator-name = "vtt";
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <1500000>;
gpio = <&gpio0 7 GPIO_ACTIVE_HIGH>;
regulator-always-on;
regulator-boot-on;
enable-active-high;
};
leds {
pinctrl-names = "default";
pinctrl-0 = <&user_leds_s0>;
compatible = "gpio-leds";
led1 {
label = "evmsk:green:usr0";
gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led2 {
label = "evmsk:green:usr1";
gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led3 {
label = "evmsk:green:mmc0";
gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "mmc0";
default-state = "off";
};
led4 {
label = "evmsk:green:heartbeat";
gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
default-state = "off";
};
};
gpio_buttons: gpio_buttons0 {
compatible = "gpio-keys";
#address-cells = <1>;
#size-cells = <0>;
switch1 {
label = "button0";
linux,code = <0x100>;
gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
};
switch2 {
label = "button1";
linux,code = <0x101>;
gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
};
switch3 {
label = "button2";
linux,code = <0x102>;
gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>;
wakeup-source;
};
switch4 {
label = "button3";
linux,code = <0x103>;
gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
};
};
backlight {
compatible = "pwm-backlight";
pwms = <&ecap2 0 50000 PWM_POLARITY_INVERTED>;
brightness-levels = <0 58 61 66 75 90 125 170 255>;
default-brightness-level = <8>;
};
sound {
compatible = "simple-audio-card";
simple-audio-card,name = "AM335x-EVMSK";
simple-audio-card,widgets =
"Headphone", "Headphone Jack";
simple-audio-card,routing =
"Headphone Jack", "HPLOUT",
"Headphone Jack", "HPROUT";
simple-audio-card,format = "dsp_b";
simple-audio-card,bitclock-master = <&sound_master>;
simple-audio-card,frame-master = <&sound_master>;
simple-audio-card,bitclock-inversion;
simple-audio-card,cpu {
sound-dai = <&mcasp1>;
};
sound_master: simple-audio-card,codec {
sound-dai = <&tlv320aic3106>;
system-clock-frequency = <24000000>;
};
};
panel {
compatible = "ti,tilcdc,panel";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&lcd_pins_default>;
pinctrl-1 = <&lcd_pins_sleep>;
status = "okay";
panel-info {
ac-bias = <255>;
ac-bias-intrpt = <0>;
dma-burst-sz = <16>;
bpp = <32>;
fdd = <0x80>;
sync-edge = <0>;
sync-ctrl = <1>;
raster-order = <0>;
fifo-th = <0>;
};
display-timings {
480x272 {
hactive = <480>;
vactive = <272>;
hback-porch = <43>;
hfront-porch = <8>;
hsync-len = <4>;
vback-porch = <12>;
vfront-porch = <4>;
vsync-len = <10>;
clock-frequency = <9000000>;
hsync-active = <0>;
vsync-active = <0>;
};
};
};
};
&am33xx_pinmux {
pinctrl-names = "default";
pinctrl-0 = <&gpio_keys_s0 &clkout2_pin>;
lcd_pins_default: lcd_pins_default {
pinctrl-single,pins = <
AM33XX_IOPAD(0x820, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad8.lcd_data23 */
AM33XX_IOPAD(0x824, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad9.lcd_data22 */
AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad10.lcd_data21 */
AM33XX_IOPAD(0x82c, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad11.lcd_data20 */
AM33XX_IOPAD(0x830, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad12.lcd_data19 */
AM33XX_IOPAD(0x834, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad13.lcd_data18 */
AM33XX_IOPAD(0x838, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad14.lcd_data17 */
AM33XX_IOPAD(0x83c, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad15.lcd_data16 */
AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */
AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */
AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */
AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */
AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */
AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */
AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */
AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */
AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */
AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */
AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */
AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */
AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */
AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */
AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */
AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */
AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0) /* lcd_vsync.lcd_vsync */
AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0) /* lcd_hsync.lcd_hsync */
AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0) /* lcd_pclk.lcd_pclk */
AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */
>;
};
lcd_pins_sleep: lcd_pins_sleep {
pinctrl-single,pins = <
AM33XX_IOPAD(0x820, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad8.lcd_data23 */
AM33XX_IOPAD(0x824, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad9.lcd_data22 */
AM33XX_IOPAD(0x828, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad10.lcd_data21 */
AM33XX_IOPAD(0x82c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad11.lcd_data20 */
AM33XX_IOPAD(0x830, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad12.lcd_data19 */
AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad13.lcd_data18 */
AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad14.lcd_data17 */
AM33XX_IOPAD(0x83c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad15.lcd_data16 */
AM33XX_IOPAD(0x8a0, PULL_DISABLE | MUX_MODE7) /* lcd_data0.lcd_data0 */
AM33XX_IOPAD(0x8a4, PULL_DISABLE | MUX_MODE7) /* lcd_data1.lcd_data1 */
AM33XX_IOPAD(0x8a8, PULL_DISABLE | MUX_MODE7) /* lcd_data2.lcd_data2 */
AM33XX_IOPAD(0x8ac, PULL_DISABLE | MUX_MODE7) /* lcd_data3.lcd_data3 */
AM33XX_IOPAD(0x8b0, PULL_DISABLE | MUX_MODE7) /* lcd_data4.lcd_data4 */
AM33XX_IOPAD(0x8b4, PULL_DISABLE | MUX_MODE7) /* lcd_data5.lcd_data5 */
AM33XX_IOPAD(0x8b8, PULL_DISABLE | MUX_MODE7) /* lcd_data6.lcd_data6 */
AM33XX_IOPAD(0x8bc, PULL_DISABLE | MUX_MODE7) /* lcd_data7.lcd_data7 */
AM33XX_IOPAD(0x8c0, PULL_DISABLE | MUX_MODE7) /* lcd_data8.lcd_data8 */
AM33XX_IOPAD(0x8c4, PULL_DISABLE | MUX_MODE7) /* lcd_data9.lcd_data9 */
AM33XX_IOPAD(0x8c8, PULL_DISABLE | MUX_MODE7) /* lcd_data10.lcd_data10 */
AM33XX_IOPAD(0x8cc, PULL_DISABLE | MUX_MODE7) /* lcd_data11.lcd_data11 */
AM33XX_IOPAD(0x8d0, PULL_DISABLE | MUX_MODE7) /* lcd_data12.lcd_data12 */
AM33XX_IOPAD(0x8d4, PULL_DISABLE | MUX_MODE7) /* lcd_data13.lcd_data13 */
AM33XX_IOPAD(0x8d8, PULL_DISABLE | MUX_MODE7) /* lcd_data14.lcd_data14 */
AM33XX_IOPAD(0x8dc, PULL_DISABLE | MUX_MODE7) /* lcd_data15.lcd_data15 */
AM33XX_IOPAD(0x8e0, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_vsync.lcd_vsync */
AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_hsync.lcd_hsync */
AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_pclk.lcd_pclk */
AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7) /* lcd_ac_bias_en.lcd_ac_bias_en */
>;
};
user_leds_s0: user_leds_s0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x810, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad4.gpio1_4 */
AM33XX_IOPAD(0x814, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad5.gpio1_5 */
AM33XX_IOPAD(0x818, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad6.gpio1_6 */
AM33XX_IOPAD(0x81c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_ad7.gpio1_7 */
>;
};
gpio_keys_s0: gpio_keys_s0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x894, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_oen_ren.gpio2_3 */
AM33XX_IOPAD(0x890, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_advn_ale.gpio2_2 */
AM33XX_IOPAD(0x870, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_wait0.gpio0_30 */
AM33XX_IOPAD(0x89c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_ben0_cle.gpio2_5 */
>;
};
i2c0_pins: pinmux_i2c0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
>;
};
uart0_pins: pinmux_uart0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
>;
};
clkout2_pin: pinmux_clkout2_pin {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
>;
};
ecap2_pins: backlight_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x99c, MUX_MODE4) /* mcasp0_ahclkr.ecap2_in_pwm2_out */
>;
};
cpsw_default: cpsw_default {
pinctrl-single,pins = <
/* Slave 1 */
AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */
AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */
AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */
AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */
AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */
AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */
AM33XX_IOPAD(0x92c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */
AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */
AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd3.rgmii1_rd3 */
AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd2.rgmii1_rd2 */
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd1.rgmii1_rd1 */
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE2) /* mii1_rxd0.rgmii1_rd0 */
/* Slave 2 */
AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a0.rgmii2_tctl */
AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a1.rgmii2_rctl */
AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a2.rgmii2_td3 */
AM33XX_IOPAD(0x84c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a3.rgmii2_td2 */
AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a4.rgmii2_td1 */
AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a5.rgmii2_td0 */
AM33XX_IOPAD(0x858, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* gpmc_a6.rgmii2_tclk */
AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a7.rgmii2_rclk */
AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a8.rgmii2_rd3 */
AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a9.rgmii2_rd2 */
AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a10.rgmii2_rd1 */
AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE2) /* gpmc_a11.rgmii2_rd0 */
>;
};
cpsw_sleep: cpsw_sleep {
pinctrl-single,pins = <
/* Slave 1 reset value */
AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
/* Slave 2 reset value*/
AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x844, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x848, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x84c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x858, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x85c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x860, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
davinci_mdio_default: davinci_mdio_default {
pinctrl-single,pins = <
/* MDIO */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
>;
};
davinci_mdio_sleep: davinci_mdio_sleep {
pinctrl-single,pins = <
/* MDIO reset value */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
>;
};
mcasp1_pins: mcasp1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_crs.mcasp1_aclkx */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE4) /* mii1_rxerr.mcasp1_fsx */
AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLDOWN | MUX_MODE4) /* mii1_col.mcasp1_axr2 */
AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE4) /* rmii1_ref_clk.mcasp1_axr3 */
>;
};
mcasp1_pins_sleep: mcasp1_pins_sleep {
pinctrl-single,pins = <
AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
mmc2_pins: pinmux_mmc2_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_31 */
AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
>;
};
wl12xx_gpio: pinmux_wl12xx_gpio {
pinctrl-single,pins = <
AM33XX_IOPAD(0x87c, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_csn0.gpio1_29 */
>;
};
};
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
status = "okay";
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
status = "okay";
clock-frequency = <400000>;
tps: tps@2d {
reg = <0x2d>;
};
lis331dlh: lis331dlh@18 {
compatible = "st,lis331dlh", "st,lis3lv02d";
reg = <0x18>;
Vdd-supply = <&lis3_reg>;
Vdd_IO-supply = <&lis3_reg>;
st,click-single-x;
st,click-single-y;
st,click-single-z;
st,click-thresh-x = <10>;
st,click-thresh-y = <10>;
st,click-thresh-z = <10>;
st,irq1-click;
st,irq2-click;
st,wakeup-x-lo;
st,wakeup-x-hi;
st,wakeup-y-lo;
st,wakeup-y-hi;
st,wakeup-z-lo;
st,wakeup-z-hi;
st,min-limit-x = <120>;
st,min-limit-y = <120>;
st,min-limit-z = <140>;
st,max-limit-x = <550>;
st,max-limit-y = <550>;
st,max-limit-z = <750>;
};
tlv320aic3106: tlv320aic3106@1b {
#sound-dai-cells = <0>;
compatible = "ti,tlv320aic3106";
reg = <0x1b>;
status = "okay";
/* Regulators */
AVDD-supply = <&vaux2_reg>;
IOVDD-supply = <&vaux2_reg>;
DRVDD-supply = <&vaux2_reg>;
DVDD-supply = <&vbat>;
};
};
&usb {
status = "okay";
};
&usb_ctrl_mod {
status = "okay";
};
&usb0_phy {
status = "okay";
};
&usb1_phy {
status = "okay";
};
&usb0 {
status = "okay";
};
&usb1 {
status = "okay";
dr_mode = "host";
};
&cppi41dma {
status = "okay";
};
&epwmss2 {
status = "okay";
ecap2: ecap@48304100 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&ecap2_pins>;
};
};
#include "tps65910.dtsi"
&tps {
vcc1-supply = <&vbat>;
vcc2-supply = <&vbat>;
vcc3-supply = <&vbat>;
vcc4-supply = <&vbat>;
vcc5-supply = <&vbat>;
vcc6-supply = <&vbat>;
vcc7-supply = <&vbat>;
vccio-supply = <&vbat>;
regulators {
vrtc_reg: regulator@0 {
regulator-always-on;
};
vio_reg: regulator@1 {
regulator-always-on;
};
vdd1_reg: regulator@2 {
/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
regulator-name = "vdd_mpu";
regulator-min-microvolt = <912500>;
regulator-max-microvolt = <1351500>;
regulator-boot-on;
regulator-always-on;
};
vdd2_reg: regulator@3 {
/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
regulator-name = "vdd_core";
regulator-min-microvolt = <912500>;
regulator-max-microvolt = <1150000>;
regulator-boot-on;
regulator-always-on;
};
vdd3_reg: regulator@4 {
regulator-always-on;
};
vdig1_reg: regulator@5 {
regulator-always-on;
};
vdig2_reg: regulator@6 {
regulator-always-on;
};
vpll_reg: regulator@7 {
regulator-always-on;
};
vdac_reg: regulator@8 {
regulator-always-on;
};
vaux1_reg: regulator@9 {
regulator-always-on;
};
vaux2_reg: regulator@10 {
regulator-always-on;
};
vaux33_reg: regulator@11 {
regulator-always-on;
};
vmmc_reg: regulator@12 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
};
};
&mac {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
dual_emac = <1>;
status = "okay";
};
&davinci_mdio {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
status = "okay";
};
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <0>;
phy-mode = "rgmii-txid";
dual_emac_res_vlan = <1>;
};
&cpsw_emac1 {
phy_id = <&davinci_mdio>, <1>;
phy-mode = "rgmii-txid";
dual_emac_res_vlan = <2>;
};
&mmc1 {
status = "okay";
vmmc-supply = <&vmmc_reg>;
bus-width = <4>;
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins>;
cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
};
&sham {
status = "okay";
};
&aes {
status = "okay";
};
&gpio0 {
ti,no-reset-on-init;
};
&mmc2 {
status = "okay";
vmmc-supply = <&wl12xx_vmmc>;
ti,non-removable;
bus-width = <4>;
cap-power-off-card;
keep-power-in-suspend;
pinctrl-names = "default";
pinctrl-0 = <&mmc2_pins>;
#address-cells = <1>;
#size-cells = <0>;
wlcore: wlcore@2 {
compatible = "ti,wl1271";
reg = <2>;
interrupt-parent = <&gpio0>;
interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; /* gpio 31 */
ref-clock-frequency = <38400000>;
};
};
&mcasp1 {
#sound-dai-cells = <0>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&mcasp1_pins>;
pinctrl-1 = <&mcasp1_pins_sleep>;
status = "okay";
op-mode = <0>; /* MCASP_IIS_MODE */
tdm-slots = <2>;
/* 4 serializers */
serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
0 0 1 2
>;
tx-num-evt = <32>;
rx-num-evt = <32>;
};
&tscadc {
status = "okay";
tsc {
ti,wires = <4>;
ti,x-plate-resistance = <200>;
ti,coordinate-readouts = <5>;
ti,wire-config = <0x00 0x11 0x22 0x33>;
};
};
&lcdc {
status = "okay";
blue-and-red-wiring = "crossed";
};

View File

@@ -1,322 +0,0 @@
/*
* Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/*
* AM335x ICE V2 board
* http://www.ti.com/tool/tmdsice3359
*/
/dts-v1/;
#include "am33xx.dtsi"
/ {
model = "TI AM3359 ICE-V2";
compatible = "ti,am3359-icev2", "ti,am33xx";
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>; /* 256 MB */
};
vbat: fixedregulator0 {
compatible = "regulator-fixed";
regulator-name = "vbat";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-boot-on;
};
vtt_fixed: fixedregulator1 {
compatible = "regulator-fixed";
regulator-name = "vtt";
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <1500000>;
gpio = <&gpio0 18 GPIO_ACTIVE_HIGH>;
regulator-always-on;
regulator-boot-on;
enable-active-high;
};
leds0 {
compatible = "gpio-leds";
led0 {
label = "out0";
gpios = <&tpic2810 0 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led1 {
label = "out1";
gpios = <&tpic2810 1 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led2 {
label = "out2";
gpios = <&tpic2810 2 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led3 {
label = "out3";
gpios = <&tpic2810 3 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led4 {
label = "out4";
gpios = <&tpic2810 4 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led5 {
label = "out5";
gpios = <&tpic2810 5 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led6 {
label = "out6";
gpios = <&tpic2810 6 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led7 {
label = "out7";
gpios = <&tpic2810 7 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
};
/* Tricolor status LEDs */
leds1 {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&user_leds>;
led0 {
label = "status0:red:cpu0";
gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
default-state = "off";
linux,default-trigger = "cpu0";
};
led1 {
label = "status0:green:usr";
gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led2 {
label = "status0:yellow:usr";
gpios = <&gpio3 9 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led3 {
label = "status1:red:mmc0";
gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>;
default-state = "off";
linux,default-trigger = "mmc0";
};
led4 {
label = "status1:green:usr";
gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led5 {
label = "status1:yellow:usr";
gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
};
gpio-decoder {
compatible = "gpio-decoder";
gpios = <&pca9536 3 GPIO_ACTIVE_HIGH>,
<&pca9536 2 GPIO_ACTIVE_HIGH>,
<&pca9536 1 GPIO_ACTIVE_HIGH>,
<&pca9536 0 GPIO_ACTIVE_HIGH>;
linux,axis = <0>; /* ABS_X */
decoder-max-value = <9>;
};
};
&am33xx_pinmux {
user_leds: user_leds {
pinctrl-single,pins = <
AM33XX_IOPAD(0x91c, PIN_OUTPUT | MUX_MODE7) /* (J18) gmii1_txd3.gpio0[16] */
AM33XX_IOPAD(0x920, PIN_OUTPUT | MUX_MODE7) /* (K15) gmii1_txd2.gpio0[17] */
AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE7) /* (A15) xdma_event_intr0.gpio0[19] */
AM33XX_IOPAD(0x9b4, PIN_OUTPUT | MUX_MODE7) /* (D14) xdma_event_intr1.gpio0[20] */
AM33XX_IOPAD(0x880, PIN_OUTPUT | MUX_MODE7) /* (U9) gpmc_csn1.gpio1[30] */
AM33XX_IOPAD(0x92c, PIN_OUTPUT | MUX_MODE7) /* (K18) gmii1_txclk.gpio3[9] */
>;
};
mmc0_pins_default: mmc0_pins_default {
pinctrl-single,pins = <
AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* (F17) mmc0_dat3.mmc0_dat3 */
AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* (F18) mmc0_dat2.mmc0_dat2 */
AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* (G15) mmc0_dat1.mmc0_dat1 */
AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* (G16) mmc0_dat0.mmc0_dat0 */
AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* (G17) mmc0_clk.mmc0_clk */
AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* (G18) mmc0_cmd.mmc0_cmd */
AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE5) /* (C15) spi0_cs1.mmc0_sdcd */
>;
};
i2c0_pins_default: i2c0_pins_default {
pinctrl-single,pins = <
AM33XX_IOPAD(0x988, PIN_INPUT | MUX_MODE0) /* (C17) I2C0_SDA.I2C0_SDA */
AM33XX_IOPAD(0x98c, PIN_INPUT | MUX_MODE0) /* (C16) I2C0_SCL.I2C0_SCL */
>;
};
spi0_pins_default: spi0_pins_default {
pinctrl-single,pins = <
AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) /* (A17) spi0_sclk.spi0_sclk */
AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* (B17) spi0_d0.spi0_d0 */
AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* (B16) spi0_d1.spi0_d1 */
AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0) /* (A16) spi0_cs0.spi0_cs0 */
>;
};
uart3_pins_default: uart3_pins_default {
pinctrl-single,pins = <
AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE1) /* (L17) gmii1_rxd3.uart3_rxd */
AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLUP | MUX_MODE1) /* (L16) gmii1_rxd2.uart3_txd */
>;
};
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_default>;
status = "okay";
clock-frequency = <400000>;
tps: power-controller@2d {
reg = <0x2d>;
};
tpic2810: gpio@60 {
compatible = "ti,tpic2810";
reg = <0x60>;
gpio-controller;
#gpio-cells = <2>;
};
pca9536: gpio@41 {
compatible = "ti,pca9536";
reg = <0x41>;
gpio-controller;
#gpio-cells = <2>;
};
};
#include "tps65910.dtsi"
&tps {
vcc1-supply = <&vbat>;
vcc2-supply = <&vbat>;
vcc3-supply = <&vbat>;
vcc4-supply = <&vbat>;
vcc5-supply = <&vbat>;
vcc6-supply = <&vbat>;
vcc7-supply = <&vbat>;
vccio-supply = <&vbat>;
regulators {
vrtc_reg: regulator@0 {
regulator-always-on;
};
vio_reg: regulator@1 {
regulator-always-on;
};
vdd1_reg: regulator@2 {
regulator-name = "vdd_mpu";
regulator-min-microvolt = <912500>;
regulator-max-microvolt = <1326000>;
regulator-boot-on;
regulator-always-on;
};
vdd2_reg: regulator@3 {
regulator-name = "vdd_core";
regulator-min-microvolt = <912500>;
regulator-max-microvolt = <1144000>;
regulator-boot-on;
regulator-always-on;
};
vdd3_reg: regulator@4 {
regulator-always-on;
};
vdig1_reg: regulator@5 {
regulator-always-on;
};
vdig2_reg: regulator@6 {
regulator-always-on;
};
vpll_reg: regulator@7 {
regulator-always-on;
};
vdac_reg: regulator@8 {
regulator-always-on;
};
vaux1_reg: regulator@9 {
regulator-always-on;
};
vaux2_reg: regulator@10 {
regulator-always-on;
};
vaux33_reg: regulator@11 {
regulator-always-on;
};
vmmc_reg: regulator@12 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
};
};
&mmc1 {
status = "okay";
vmmc-supply = <&vmmc_reg>;
bus-width = <4>;
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_default>;
};
&gpio0 {
/* Do not idle the GPIO used for holding the VTT regulator */
ti,no-reset-on-init;
ti,no-idle-on-init;
};
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&uart3_pins_default>;
status = "okay";
};

View File

@@ -1,323 +0,0 @@
/*
* am335x-igep0033.dtsi - Device Tree file for IGEP COM AQUILA AM335x
*
* Copyright (C) 2013 ISEE 2007 SL - http://www.isee.biz
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
#include "am33xx.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
/ {
cpus {
cpu@0 {
cpu0-supply = <&vdd1_reg>;
};
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>; /* 256 MB */
};
leds {
pinctrl-names = "default";
pinctrl-0 = <&leds_pins>;
compatible = "gpio-leds";
led0 {
label = "com:green:user";
gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
default-state = "on";
};
};
vbat: fixedregulator0 {
compatible = "regulator-fixed";
regulator-name = "vbat";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-boot-on;
};
vmmc: fixedregulator1 {
compatible = "regulator-fixed";
regulator-name = "vmmc";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
};
&am33xx_pinmux {
i2c0_pins: pinmux_i2c0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
>;
};
nandflash_pins: pinmux_nandflash_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */
AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */
AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */
AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */
AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */
AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */
AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */
AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */
AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */
AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */
AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */
AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */
AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */
AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */
AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */
>;
};
uart0_pins: pinmux_uart0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
>;
};
leds_pins: pinmux_leds_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x85c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a7.gpio1_23 */
>;
};
};
&mac {
status = "okay";
};
&davinci_mdio {
status = "okay";
};
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <0>;
phy-mode = "rmii";
};
&cpsw_emac1 {
phy_id = <&davinci_mdio>, <1>;
phy-mode = "rmii";
};
&phy_sel {
rmii-clock-ext;
};
&elm {
status = "okay";
};
&gpmc {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&nandflash_pins>;
ranges = <0 0 0x08000000 0x1000000>; /* CS0: 16MB for NAND */
nand@0,0 {
compatible = "ti,omap2-nand";
reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
nand-bus-width = <8>;
ti,nand-ecc-opt = "bch8";
gpmc,device-width = <1>;
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;
gpmc,cs-rd-off-ns = <44>;
gpmc,cs-wr-off-ns = <44>;
gpmc,adv-on-ns = <6>;
gpmc,adv-rd-off-ns = <34>;
gpmc,adv-wr-off-ns = <44>;
gpmc,we-on-ns = <0>;
gpmc,we-off-ns = <40>;
gpmc,oe-on-ns = <0>;
gpmc,oe-off-ns = <54>;
gpmc,access-ns = <64>;
gpmc,rd-cycle-ns = <82>;
gpmc,wr-cycle-ns = <82>;
gpmc,bus-turnaround-ns = <0>;
gpmc,cycle2cycle-delay-ns = <0>;
gpmc,clk-activation-ns = <0>;
gpmc,wr-access-ns = <40>;
gpmc,wr-data-mux-bus-ns = <0>;
#address-cells = <1>;
#size-cells = <1>;
ti,elm-id = <&elm>;
/* MTD partition table */
partition@0 {
label = "SPL";
reg = <0x00000000 0x000080000>;
};
partition@1 {
label = "U-boot";
reg = <0x00080000 0x001e0000>;
};
partition@2 {
label = "U-Boot Env";
reg = <0x00260000 0x00020000>;
};
partition@3 {
label = "Kernel";
reg = <0x00280000 0x00500000>;
};
partition@4 {
label = "File System";
reg = <0x00780000 0x007880000>;
};
};
};
&i2c0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
clock-frequency = <400000>;
tps: tps@2d {
reg = <0x2d>;
};
};
&mmc1 {
status = "okay";
vmmc-supply = <&vmmc>;
bus-width = <4>;
};
&uart0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
};
&usb {
status = "okay";
};
&usb_ctrl_mod {
status = "okay";
};
&usb0_phy {
status = "okay";
};
&usb1_phy {
status = "okay";
};
&usb0 {
status = "okay";
};
&usb1 {
status = "okay";
dr_mode = "host";
};
&cppi41dma {
status = "okay";
};
#include "tps65910.dtsi"
&tps {
vcc1-supply = <&vbat>;
vcc2-supply = <&vbat>;
vcc3-supply = <&vbat>;
vcc4-supply = <&vbat>;
vcc5-supply = <&vbat>;
vcc6-supply = <&vbat>;
vcc7-supply = <&vbat>;
vccio-supply = <&vbat>;
regulators {
vrtc_reg: regulator@0 {
regulator-always-on;
};
vio_reg: regulator@1 {
regulator-always-on;
};
vdd1_reg: regulator@2 {
/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
regulator-name = "vdd_mpu";
regulator-min-microvolt = <912500>;
regulator-max-microvolt = <1312500>;
regulator-boot-on;
regulator-always-on;
};
vdd2_reg: regulator@3 {
/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
regulator-name = "vdd_core";
regulator-min-microvolt = <912500>;
regulator-max-microvolt = <1150000>;
regulator-boot-on;
regulator-always-on;
};
vdd3_reg: regulator@4 {
regulator-always-on;
};
vdig1_reg: regulator@5 {
regulator-always-on;
};
vdig2_reg: regulator@6 {
regulator-always-on;
};
vpll_reg: regulator@7 {
regulator-always-on;
};
vdac_reg: regulator@8 {
regulator-always-on;
};
vaux1_reg: regulator@9 {
regulator-always-on;
};
vaux2_reg: regulator@10 {
regulator-always-on;
};
vaux33_reg: regulator@11 {
regulator-always-on;
};
vmmc_reg: regulator@12 {
regulator-always-on;
};
};
};

View File

@@ -1,366 +0,0 @@
/*
* Copyright (C) 2014 NovaTech LLC - http://www.novatechweb.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
#include "am33xx.dtsi"
/ {
model = "NovaTech OrionLXm";
compatible = "novatech,am335x-lxm", "ti,am33xx";
cpus {
cpu@0 {
cpu0-supply = <&vdd1_reg>;
};
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x20000000>; /* 512 MB */
};
/* Power supply provides a fixed 5V @2A */
vbat: fixedregulator0 {
compatible = "regulator-fixed";
regulator-name = "vbat";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-boot-on;
};
/* Power supply provides a fixed 3.3V @3A */
vmmcsd_fixed: fixedregulator1 {
compatible = "regulator-fixed";
regulator-name = "vmmcsd_fixed";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
};
};
&am33xx_pinmux {
mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3 */
AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2 */
AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat1 */
AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat0 */
AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk */
AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd */
>;
};
i2c0_pins: pinmux_i2c0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x988, PIN_INPUT | MUX_MODE0) /* i2c0_sda.i2c0_sda */
AM33XX_IOPAD(0x98c, PIN_INPUT | MUX_MODE0) /* i2c0_scl.i2c0_scl */
>;
};
cpsw_default: cpsw_default {
pinctrl-single,pins = <
/* Slave 1 */
AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii1_int */
AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* rmii1_crs_dv */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE1) /* rmii1_rxer */
AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* rmii1_txen */
AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* rmii1_td1 */
AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* rmii1_td0 */
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* rmii1_rd1 */
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE1) /* rmii1_rd0 */
AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_refclk */
/* Slave 2 */
AM33XX_IOPAD(0x840, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* rmii2_txen */
AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* rmii2_td1 */
AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* rmii2_td0 */
AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE3) /* rmii2_rd1 */
AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE3) /* rmii2_rd0 */
AM33XX_IOPAD(0x870, PIN_INPUT_PULLDOWN | MUX_MODE3) /* rmii2_crs_dv */
AM33XX_IOPAD(0x874, PIN_INPUT_PULLDOWN | MUX_MODE3) /* rmii2_rxer */
AM33XX_IOPAD(0x878, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii2_int */
AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE1) /* rmii2_refclk */
>;
};
cpsw_sleep: cpsw_sleep {
pinctrl-single,pins = <
/* Slave 1 reset value */
AM33XX_IOPAD(0x864, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii1_int */
AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii1_crs_dv */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii1_rxer */
AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii1_txen */
AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii1_td1 */
AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii1_td0 */
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii1_rd1 */
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii1_rd0 */
AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii1_refclk */
/* Slave 2 reset value*/
AM33XX_IOPAD(0x840, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii2_txen */
AM33XX_IOPAD(0x850, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii2_td1 */
AM33XX_IOPAD(0x854, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii2_td0 */
AM33XX_IOPAD(0x868, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii2_rd1 */
AM33XX_IOPAD(0x86c, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii2_rd0 */
AM33XX_IOPAD(0x870, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii2_crs_dv */
AM33XX_IOPAD(0x874, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii2_rxer */
AM33XX_IOPAD(0x878, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii2_int */
AM33XX_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7) /* rmii2_refclk */
>;
};
davinci_mdio_default: davinci_mdio_default {
pinctrl-single,pins = <
/* MDIO */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
>;
};
davinci_mdio_sleep: davinci_mdio_sleep {
pinctrl-single,pins = <
/* MDIO reset value */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
emmc_pins: pinmux_emmc_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
>;
};
uart0_pins: pinmux_uart0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
>;
};
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
status = "okay";
clock-frequency = <400000>;
serial_config1: serial_config1@20 {
compatible = "nxp,pca9539";
reg = <0x20>;
};
serial_config2: serial_config2@21 {
compatible = "nxp,pca9539";
reg = <0x21>;
};
tps: tps@2d {
compatible = "ti,tps65910";
reg = <0x2d>;
};
};
/include/ "tps65910.dtsi"
&tps {
vcc1-supply = <&vbat>;
vcc2-supply = <&vbat>;
vcc3-supply = <&vbat>;
vcc4-supply = <&vbat>;
vcc5-supply = <&vbat>;
vcc6-supply = <&vbat>;
vcc7-supply = <&vbat>;
vccio-supply = <&vbat>;
regulators {
/* vrtc - unused */
vio_reg: regulator@1 {
regulator-name = "vio_1v5,ddr";
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <1500000>;
regulator-boot-on;
regulator-always-on;
};
vdd1_reg: regulator@2 {
regulator-name = "vdd1,mpu";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <1500000>;
regulator-boot-on;
regulator-always-on;
};
vdd2_reg: regulator@3 {
regulator-name = "vdd2_1v1,core";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <1100000>;
regulator-boot-on;
regulator-always-on;
};
/* vdd3 - unused */
/* vdig1 - unused */
vdig2_reg: regulator@6 {
regulator-name = "vdig2_1v8,vdds_pll";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
};
/* vpll - unused */
vdac_reg: regulator@8 {
regulator-name = "vdac_1v8,vdds";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
};
vaux1_reg: regulator@9 {
regulator-name = "vaux1_1v8,usb";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-boot-on;
regulator-always-on;
};
vaux2_reg: regulator@10 {
regulator-name = "vaux2_3v3,io";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
vaux33_reg: regulator@11 {
regulator-name = "vaux33_3v3,usb";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
vmmc_reg: regulator@12 {
regulator-name = "vmmc_3v3,io";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
};
};
&sham {
status = "okay";
};
&aes {
status = "okay";
};
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
status = "okay";
};
&usb {
status = "okay";
};
&usb_ctrl_mod {
status = "okay";
};
&usb0_phy {
status = "okay";
};
&usb1_phy {
status = "okay";
};
&usb0 {
status = "okay";
dr_mode = "host";
};
&usb1 {
status = "okay";
dr_mode = "host";
};
&cppi41dma {
status = "okay";
};
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <5>;
phy-mode = "rmii";
dual_emac_res_vlan = <2>;
};
&cpsw_emac1 {
phy_id = <&davinci_mdio>, <4>;
phy-mode = "rmii";
dual_emac_res_vlan = <3>;
};
&phy_sel {
rmii-clock-ext;
};
&mac {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
dual_emac = <1>;
status = "okay";
};
&davinci_mdio {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
status = "okay";
};
&mmc1 {
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins>;
vmmc-supply = <&vmmcsd_fixed>;
bus-width = <4>;
status = "okay";
};
&mmc2 {
pinctrl-names = "default";
pinctrl-0 = <&emmc_pins>;
vmmc-supply = <&vmmcsd_fixed>;
bus-width = <8>;
ti,non-removable;
status = "okay";
};

View File

@@ -1,440 +0,0 @@
/*
* Copyright (C) 2013 Newflow Ltd - http://www.newflow.co.uk/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
#include "am33xx.dtsi"
/ {
model = "Newflow AM335x NanoBone";
compatible = "ti,am33xx";
cpus {
cpu@0 {
cpu0-supply = <&dcdc2_reg>;
};
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>; /* 256 MB */
};
leds {
compatible = "gpio-leds";
led0 {
label = "nanobone:green:usr1";
gpios = <&gpio1 5 0>;
default-state = "off";
};
};
};
&am33xx_pinmux {
pinctrl-names = "default";
pinctrl-0 = <&misc_pins>;
misc_pins: misc_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x95c, PIN_OUTPUT | MUX_MODE7) /* spi0_cs0.gpio0_5 */
>;
};
gpmc_pins: gpmc_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */
AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */
AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */
AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */
AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */
AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */
AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */
AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */
AM33XX_IOPAD(0x820, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad8.gpmc_ad8 */
AM33XX_IOPAD(0x824, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad9.gpmc_ad9 */
AM33XX_IOPAD(0x828, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad10.gpmc_ad10 */
AM33XX_IOPAD(0x82c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad11.gpmc_ad11 */
AM33XX_IOPAD(0x830, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad12.gpmc_ad12 */
AM33XX_IOPAD(0x834, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad13.gpmc_ad13 */
AM33XX_IOPAD(0x838, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad14.gpmc_ad14 */
AM33XX_IOPAD(0x83c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad15.gpmc_ad15 */
AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */
AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */
AM33XX_IOPAD(0x880, PIN_OUTPUT | MUX_MODE0) /* gpmc_csn1.gpmc_csn1 */
AM33XX_IOPAD(0x884, PIN_OUTPUT | MUX_MODE0) /* gpmc_csn2.gpmc_csn2 */
AM33XX_IOPAD(0x888, PIN_OUTPUT | MUX_MODE0) /* gpmc_csn3.gpmc_csn3 */
AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */
AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */
AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */
AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0) /* gpmc_ben0_cle.gpmc_ben0_cle */
AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE1) /* lcd_data1.gpmc_a1 */
AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE1) /* lcd_data2.gpmc_a2 */
AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE1) /* lcd_data3.gpmc_a3 */
AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE1) /* lcd_data4.gpmc_a4 */
AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE1) /* lcd_data5.gpmc_a5 */
AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE1) /* lcd_data6.gpmc_a6 */
AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE1) /* lcd_data7.gpmc_a7 */
AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE1) /* lcd_vsync.gpmc_a8 */
AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE1) /* lcd_hsync.gpmc_a9 */
AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE1) /* lcd_pclk.gpmc_a10 */
>;
};
i2c0_pins: i2c0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x988, PIN_INPUT_PULLDOWN | MUX_MODE0) /* i2c0_sda.i2c0_sda */
AM33XX_IOPAD(0x98c, PIN_INPUT_PULLDOWN | MUX_MODE0) /* i2c0_scl.i2c0_scl */
>;
};
uart0_pins: uart0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
AM33XX_IOPAD(0x974, PIN_OUTPUT | MUX_MODE0) /* uart0_txd.uart0_txd */
>;
};
uart1_pins: uart1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x978, PIN_OUTPUT | MUX_MODE7) /* uart1_ctsn.uart1_ctsn */
AM33XX_IOPAD(0x97c, PIN_OUTPUT | MUX_MODE7) /* uart1_rtsn.uart1_rtsn */
AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0) /* uart1_rxd.uart1_rxd */
AM33XX_IOPAD(0x984, PIN_OUTPUT | MUX_MODE0) /* uart1_txd.uart1_txd */
>;
};
uart2_pins: uart2_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x8c0, PIN_INPUT_PULLUP | MUX_MODE7) /* lcd_data8.gpio2[14] */
AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE7) /* lcd_data9.gpio2[15] */
AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1) /* spi0_sclk.uart2_rxd */
AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1) /* spi0_d0.uart2_txd */
>;
};
uart3_pins: uart3_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x8c8, PIN_INPUT_PULLUP | MUX_MODE6) /* lcd_data10.uart3_ctsn */
AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE6) /* lcd_data11.uart3_rtsn */
AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE1) /* spi0_cs1.uart3_rxd */
AM33XX_IOPAD(0x964, PIN_OUTPUT | MUX_MODE1) /* ecap0_in_pwm0_out.uart3_txd */
>;
};
uart4_pins: uart4_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x8d0, PIN_INPUT_PULLUP | MUX_MODE6) /* lcd_data12.uart4_ctsn */
AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE6) /* lcd_data13.uart4_rtsn */
AM33XX_IOPAD(0x968, PIN_INPUT | MUX_MODE1) /* uart0_ctsn.uart4_rxd */
AM33XX_IOPAD(0x96c, PIN_OUTPUT | MUX_MODE1) /* uart0_rtsn.uart4_txd */
>;
};
uart5_pins: uart5_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x8d8, PIN_INPUT | MUX_MODE4) /* lcd_data14.uart5_rxd */
AM33XX_IOPAD(0x944, PIN_OUTPUT | MUX_MODE3) /* rmiii1_refclk.uart5_txd */
>;
};
mmc1_pins: mmc1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk.mmc0_clk */
AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
AM33XX_IOPAD(0x9e8, PIN_INPUT_PULLUP | MUX_MODE7) /* emu1.gpio3[8] */
AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLUP | MUX_MODE7) /* mcasp0_aclkr.gpio3[18] */
>;
};
};
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
status = "okay";
};
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>;
status = "okay";
rts-gpio = <&gpio0 13 GPIO_ACTIVE_HIGH>;
rs485-rts-active-high;
rs485-rx-during-tx;
rs485-rts-delay = <1 1>;
linux,rs485-enabled-at-boot-time;
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
status = "okay";
rts-gpio = <&gpio2 15 GPIO_ACTIVE_HIGH>;
rs485-rts-active-high;
rs485-rts-delay = <1 1>;
linux,rs485-enabled-at-boot-time;
};
&uart3 {
pinctrl-names = "default";
pinctrl-0 = <&uart3_pins>;
status = "okay";
};
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins>;
status = "okay";
};
&uart5 {
pinctrl-names = "default";
pinctrl-0 = <&uart5_pins>;
status = "okay";
};
&i2c0 {
status = "okay";
pinctrl-names = "default";
clock-frequency = <400000>;
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
gpio@20 {
compatible = "microchip,mcp23017";
gpio-controller;
#gpio-cells = <2>;
reg = <0x20>;
};
tps: tps@24 {
reg = <0x24>;
};
eeprom@53 {
compatible = "microchip,24c02";
reg = <0x53>;
pagesize = <8>;
};
rtc@68 {
compatible = "dallas,ds1307";
reg = <0x68>;
};
};
&elm {
status = "okay";
};
&gpmc {
compatible = "ti,am3352-gpmc";
ti,hwmods = "gpmc";
status = "okay";
gpmc,num-waitpins = <2>;
pinctrl-names = "default";
pinctrl-0 = <&gpmc_pins>;
#address-cells = <2>;
#size-cells = <1>;
ranges = <0 0 0x08000000 0x08000000>; /* CS0: NOR 128M */
nor@0,0 {
reg = <0 0x00000000 0x08000000>;
compatible = "cfi-flash";
linux,mtd-name = "spansion,s29gl010p11t";
bank-width = <2>;
gpmc,mux-add-data = <2>;
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;
gpmc,cs-rd-off-ns = <160>;
gpmc,cs-wr-off-ns = <160>;
gpmc,adv-on-ns = <10>;
gpmc,adv-rd-off-ns = <30>;
gpmc,adv-wr-off-ns = <30>;
gpmc,oe-on-ns = <40>;
gpmc,oe-off-ns = <160>;
gpmc,we-on-ns = <40>;
gpmc,we-off-ns = <160>;
gpmc,rd-cycle-ns = <160>;
gpmc,wr-cycle-ns = <160>;
gpmc,access-ns = <150>;
gpmc,page-burst-access-ns = <10>;
gpmc,cycle2cycle-samecsen;
gpmc,cycle2cycle-delay-ns = <20>;
gpmc,wr-data-mux-bus-ns = <70>;
gpmc,wr-access-ns = <80>;
#address-cells = <1>;
#size-cells = <1>;
/*
MTD partition table
===================
+------------+-->0x00000000-> U-Boot start
| |
| |-->0x000BFFFF-> U-Boot end
| |-->0x000C0000-> ENV1 start
| |
| |-->0x000DFFFF-> ENV1 end
| |-->0x000E0000-> ENV2 start
| |
| |-->0x000FFFFF-> ENV2 end
| |-->0x00100000-> Kernel start
| |
| |-->0x004FFFFF-> Kernel end
| |-->0x00500000-> File system start
| |
| |-->0x01FFFFFF-> File system end
| |-->0x02000000-> User data start
| |
| |-->0x03FFFFFF-> User data end
| |-->0x04000000-> Data storage start
| |
+------------+-->0x08000000-> NOR end (Free end)
*/
partition@0 {
label = "boot";
reg = <0x00000000 0x000c0000>; /* 768KB */
};
partition@1 {
label = "env1";
reg = <0x000c0000 0x00020000>; /* 128KB */
};
partition@2 {
label = "env2";
reg = <0x000e0000 0x00020000>; /* 128KB */
};
partition@3 {
label = "kernel";
reg = <0x00100000 0x00400000>; /* 4MB */
};
partition@4 {
label = "rootfs";
reg = <0x00500000 0x01b00000>; /* 27MB */
};
partition@5 {
label = "user";
reg = <0x02000000 0x02000000>; /* 32MB */
};
partition@6 {
label = "data";
reg = <0x04000000 0x04000000>; /* 64MB */
};
};
};
&mac {
dual_emac;
status = "okay";
};
&davinci_mdio {
status = "okay";
};
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <0>;
phy-mode = "mii";
dual_emac_res_vlan = <1>;
};
&cpsw_emac1 {
phy_id = <&davinci_mdio>, <1>;
phy-mode = "mii";
dual_emac_res_vlan = <2>;
};
&mmc1 {
status = "okay";
vmmc-supply = <&ldo4_reg>;
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins>;
bus-width = <4>;
cd-gpios = <&gpio3 8 0>;
wp-gpios = <&gpio3 18 0>;
};
#include "tps65217.dtsi"
&tps {
regulators {
dcdc1_reg: regulator@0 {
/* +1.5V voltage with ±4% tolerance */
regulator-min-microvolt = <1450000>;
regulator-max-microvolt = <1550000>;
regulator-boot-on;
regulator-always-on;
};
dcdc2_reg: regulator@1 {
/* VDD_MPU voltage limits 0.95V - 1.1V with ±4% tolerance */
regulator-name = "vdd_mpu";
regulator-min-microvolt = <915000>;
regulator-max-microvolt = <1140000>;
regulator-boot-on;
regulator-always-on;
};
dcdc3_reg: regulator@2 {
/* VDD_CORE voltage limits 0.95V - 1.1V with ±4% tolerance */
regulator-name = "vdd_core";
regulator-min-microvolt = <915000>;
regulator-max-microvolt = <1140000>;
regulator-boot-on;
regulator-always-on;
};
ldo1_reg: regulator@3 {
/* +1.8V voltage with ±4% tolerance */
regulator-min-microvolt = <1750000>;
regulator-max-microvolt = <1870000>;
regulator-boot-on;
regulator-always-on;
};
ldo2_reg: regulator@4 {
/* +3.3V voltage with ±4% tolerance */
regulator-min-microvolt = <3175000>;
regulator-max-microvolt = <3430000>;
regulator-boot-on;
regulator-always-on;
};
ldo3_reg: regulator@5 {
/* +1.8V voltage with ±4% tolerance */
regulator-min-microvolt = <1750000>;
regulator-max-microvolt = <1870000>;
regulator-boot-on;
regulator-always-on;
};
ldo4_reg: regulator@6 {
/* +3.3V voltage with ±4% tolerance */
regulator-min-microvolt = <3175000>;
regulator-max-microvolt = <3430000>;
regulator-boot-on;
regulator-always-on;
};
};
};

View File

@@ -1,656 +0,0 @@
/*
* Copyright (C) 2014 Gumstix, Inc. - https://www.gumstix.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
#include <dt-bindings/input/input.h>
#include "am33xx.dtsi"
/ {
model = "Gumstix Pepper";
compatible = "gumstix,am335x-pepper", "ti,am33xx";
cpus {
cpu@0 {
cpu0-supply = <&dcdc3_reg>;
};
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x20000000>; /* 512 MB */
};
buttons: user_buttons {
compatible = "gpio-keys";
};
leds: user_leds {
compatible = "gpio-leds";
};
panel: lcd_panel {
compatible = "ti,tilcdc,panel";
};
sound: sound_iface {
compatible = "ti,da830-evm-audio";
};
vbat: fixedregulator0 {
compatible = "regulator-fixed";
};
v3v3c_reg: fixedregulator1 {
compatible = "regulator-fixed";
};
vdd5_reg: fixedregulator2 {
compatible = "regulator-fixed";
};
};
/* I2C Busses */
&i2c0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
clock-frequency = <400000>;
tps: tps@24 {
reg = <0x24>;
};
eeprom: eeprom@50 {
compatible = "at,24c256";
reg = <0x50>;
};
audio_codec: tlv320aic3106@1b {
compatible = "ti,tlv320aic3106";
reg = <0x1b>;
ai3x-micbias-vg = <0x2>;
};
accel: lis331dlh@1d {
compatible = "st,lis3lv02d";
reg = <0x1d>;
};
};
&i2c1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
clock-frequency = <400000>;
};
&am33xx_pinmux {
i2c0_pins: pinmux_i2c0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
>;
};
i2c1_pins: pinmux_i2c1 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x90C, PIN_INPUT_PULLUP | MUX_MODE3) /* mii1_crs,i2c1_sda */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE3) /* mii1_rxerr,i2c1_scl */
>;
};
};
/* Accelerometer */
&accel {
pinctrl-names = "default";
pinctrl-0 = <&accel_pins>;
Vdd-supply = <&ldo3_reg>;
Vdd_IO-supply = <&ldo3_reg>;
st,irq1-click;
st,wakeup-x-lo;
st,wakeup-x-hi;
st,wakeup-y-lo;
st,wakeup-y-hi;
st,wakeup-z-lo;
st,wakeup-z-hi;
st,min-limit-x = <92>;
st,max-limit-x = <14>;
st,min-limit-y = <14>;
st,max-limit-y = <92>;
st,min-limit-z = <92>;
st,max-limit-z = <14>;
};
&am33xx_pinmux {
accel_pins: pinmux_accel {
pinctrl-single,pins = <
AM33XX_IOPAD(0x898, PIN_INPUT | MUX_MODE7) /* gpmc_wen.gpio2_4 */
>;
};
};
/* Audio */
&audio_codec {
status = "okay";
gpio-reset = <&gpio1 16 GPIO_ACTIVE_LOW>;
AVDD-supply = <&ldo3_reg>;
IOVDD-supply = <&ldo3_reg>;
DRVDD-supply = <&ldo3_reg>;
DVDD-supply = <&dcdc1_reg>;
};
&sound {
ti,model = "AM335x-EVM";
ti,audio-codec = <&audio_codec>;
ti,mcasp-controller = <&mcasp0>;
ti,codec-clock-rate = <12000000>;
ti,audio-routing =
"Headphone Jack", "HPLOUT",
"Headphone Jack", "HPROUT",
"MIC3L", "Mic3L Switch";
};
&mcasp0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&audio_pins>;
op-mode = <0>; /* MCASP_ISS_MODE */
tdm-slots = <2>;
serial-dir = <
1 2 0 0
0 0 0 0
0 0 0 0
0 0 0 0
>;
tx-num-evt = <1>;
rx-num-evt = <1>;
};
&am33xx_pinmux {
audio_pins: pinmux_audio {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
AM33XX_IOPAD(0x994, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
AM33XX_IOPAD(0x990, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
AM33XX_IOPAD(0x998, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_axr0.mcasp0_axr0 */
AM33XX_IOPAD(0x9a8, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_axr1.mcasp0_axr1 */
AM33XX_IOPAD(0x840, PIN_OUTPUT | MUX_MODE7) /* gpmc_a0.gpio1_16 */
>;
};
};
/* Display: 24-bit LCD Screen */
&panel {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&lcd_pins>;
panel-info {
ac-bias = <255>;
ac-bias-intrpt = <0>;
dma-burst-sz = <16>;
bpp = <32>;
fdd = <0x80>;
sync-edge = <0>;
sync-ctrl = <1>;
raster-order = <0>;
fifo-th = <0>;
};
display-timings {
native-mode = <&timing0>;
timing0: 480x272 {
clock-frequency = <18400000>;
hactive = <480>;
vactive = <272>;
hfront-porch = <8>;
hback-porch = <4>;
hsync-len = <41>;
vfront-porch = <4>;
vback-porch = <2>;
vsync-len = <10>;
hsync-active = <1>;
vsync-active = <1>;
};
};
};
&lcdc {
status = "okay";
};
&am33xx_pinmux {
lcd_pins: pinmux_lcd {
pinctrl-single,pins = <
AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0.lcd_data0 */
AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1.lcd_data1 */
AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2.lcd_data2 */
AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3.lcd_data3 */
AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4.lcd_data4 */
AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5.lcd_data5 */
AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6.lcd_data6 */
AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7.lcd_data7 */
AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8.lcd_data8 */
AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9.lcd_data9 */
AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10.lcd_data10 */
AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11.lcd_data11 */
AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12.lcd_data12 */
AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13.lcd_data13 */
AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14.lcd_data14 */
AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15.lcd_data15 */
AM33XX_IOPAD(0x820, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad8.lcd_data16 */
AM33XX_IOPAD(0x824, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad9.lcd_data17 */
AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad10.lcd_data18 */
AM33XX_IOPAD(0x82c, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad11.lcd_data19 */
AM33XX_IOPAD(0x830, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad12.lcd_data20 */
AM33XX_IOPAD(0x834, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad13.lcd_data21 */
AM33XX_IOPAD(0x838, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad14.lcd_data22 */
AM33XX_IOPAD(0x83c, PIN_OUTPUT | MUX_MODE1) /* gpmc_ad15.lcd_data23 */
AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0) /* lcd_vsync.lcd_vsync */
AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0) /* lcd_hsync.lcd_hsync */
AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0) /* lcd_pclk.lcd_pclk */
AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0) /* lcd_ac_bias_en.lcd_ac_bias_en */
/* Display Enable */
AM33XX_IOPAD(0x86c, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a11.gpio1_27 */
>;
};
};
/* Ethernet */
&cpsw_emac0 {
status = "okay";
phy_id = <&davinci_mdio>, <0>;
phy-mode = "rgmii";
};
&cpsw_emac1 {
status = "okay";
phy_id = <&davinci_mdio>, <1>;
phy-mode = "rgmii";
};
&davinci_mdio {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mdio_pins>;
};
&mac {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&ethernet_pins>;
};
&am33xx_pinmux {
ethernet_pins: pinmux_ethernet {
pinctrl-single,pins = <
AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txen.rgmii1_tctl */
AM33XX_IOPAD(0x918, PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_rxdv.rgmii1_rctl */
AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd3.rgmii1_td3 */
AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd2.rgmii1_td2 */
AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd1.rgmii1_td1 */
AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mii1_txd0.rgmii1_td0 */
AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_txclk.rgmii1_tclk */
AM33XX_IOPAD(0x930, PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_rxclk.rgmii1_rclk */
AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_rxd3.rgmii1_rxd3 */
AM33XX_IOPAD(0x938, PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_rxd2.rgmii1_rxd2 */
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_rxd1.rgmii1_rxd1 */
AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE2) /* mii1_rxd0.rgmii1_rxd0 */
/* ethernet interrupt */
AM33XX_IOPAD(0x944, PIN_INPUT_PULLUP | MUX_MODE7) /* rmii2_refclk.gpio0_29 */
/* ethernet PHY nReset */
AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLUP | MUX_MODE7) /* mii1_col.gpio3_0 */
>;
};
mdio_pins: pinmux_mdio {
pinctrl-single,pins = <
AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
>;
};
};
/* MMC */
&mmc1 {
/* Bootable SD card slot */
status = "okay";
vmmc-supply = <&ldo3_reg>;
bus-width = <4>;
pinctrl-names = "default";
pinctrl-0 = <&sd_pins>;
cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
};
&mmc2 {
/* eMMC (not populated) on MMC #2 */
status = "disabled";
pinctrl-names = "default";
pinctrl-0 = <&emmc_pins>;
vmmc-supply = <&ldo3_reg>;
bus-width = <8>;
ti,non-removable;
};
&mmc3 {
/* Wifi & Bluetooth on MMC #3 */
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&wireless_pins>;
vmmmc-supply = <&v3v3c_reg>;
bus-width = <4>;
ti,non-removable;
dmas = <&edma_xbar 12 0 1
&edma_xbar 13 0 2>;
dma-names = "tx", "rx";
};
&am33xx_pinmux {
sd_pins: pinmux_sd_card {
pinctrl-single,pins = <
AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk.mmc0_clk */
AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
>;
};
emmc_pins: pinmux_emmc {
pinctrl-single,pins = <
AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
/* EMMC nReset */
AM33XX_IOPAD(0x874, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_31 */
>;
};
wireless_pins: pinmux_wireless {
pinctrl-single,pins = <
AM33XX_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a1.mmc2_dat0 */
AM33XX_IOPAD(0x848, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a2.mmc2_dat1 */
AM33XX_IOPAD(0x84c, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_a3.mmc2_dat2 */
AM33XX_IOPAD(0x878, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_ben1.mmc2_dat3 */
AM33XX_IOPAD(0x888, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_csn3.mmc2_cmd */
AM33XX_IOPAD(0x88c, PIN_INPUT_PULLUP | MUX_MODE3) /* gpmc_clk.mmc1_clk */
/* WLAN nReset */
AM33XX_IOPAD(0x860, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a8.gpio1_24 */
/* WLAN nPower down */
AM33XX_IOPAD(0x870, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_wait0.gpio0_30 */
/* 32kHz Clock */
AM33XX_IOPAD(0x9b4, PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */
>;
};
};
/* Power */
&vbat {
regulator-name = "vbat";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
};
&v3v3c_reg {
regulator-name = "v3v3c_reg";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
vin-supply = <&vbat>;
};
&vdd5_reg {
regulator-name = "vdd5_reg";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
vin-supply = <&vbat>;
};
/include/ "tps65217.dtsi"
&tps {
backlight {
isel = <1>; /* ISET1 */
fdim = <200>; /* TPS65217_BL_FDIM_200HZ */
default-brightness = <80>;
};
regulators {
dcdc1_reg: regulator@0 {
/* VDD_1V8 system supply */
regulator-always-on;
};
dcdc2_reg: regulator@1 {
/* VDD_CORE voltage limits 0.95V - 1.26V with +/-4% tolerance */
regulator-name = "vdd_core";
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <1150000>;
regulator-boot-on;
regulator-always-on;
};
dcdc3_reg: regulator@2 {
/* VDD_MPU voltage limits 0.95V - 1.1V with +/-4% tolerance */
regulator-name = "vdd_mpu";
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <1325000>;
regulator-boot-on;
regulator-always-on;
};
ldo1_reg: regulator@3 {
/* VRTC 1.8V always-on supply */
regulator-name = "vrtc,vdds";
regulator-always-on;
};
ldo2_reg: regulator@4 {
/* 3.3V rail */
regulator-name = "vdd_3v3aux";
regulator-always-on;
};
ldo3_reg: regulator@5 {
/* VDD_3V3A 3.3V rail */
regulator-name = "vdd_3v3a";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
ldo4_reg: regulator@6 {
/* VDD_3V3B 3.3V rail */
regulator-name = "vdd_3v3b";
regulator-always-on;
};
};
};
/* SPI Busses */
&spi0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
};
&am33xx_pinmux {
spi0_pins: pinmux_spi0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_sclk.spi0_sclk */
AM33XX_IOPAD(0x95C, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_cs0.spi0_cs0 */
AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d0.spi0_d0 */
AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d1.spi0_d1 */
>;
};
};
/* Touch Screen */
&tscadc {
status = "okay";
tsc {
ti,wires = <4>;
ti,x-plate-resistance = <200>;
ti,coordinate-readouts = <5>;
ti,wire-config = <0x00 0x11 0x22 0x33>;
};
adc {
ti,adc-channels = <4 5 6 7>;
};
};
/* UARTs */
&uart0 {
/* Serial Console */
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
};
&uart1 {
/* Broken out to J6 header */
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>;
};
&am33xx_pinmux {
uart0_pins: pinmux_uart0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
>;
};
uart1_pins: pinmux_uart1 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE0) /* uart1_ctsn.uart1_ctsn */
AM33XX_IOPAD(0x97C, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_rtsn.uart1_rtsn */
AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0) /* uart1_rxd.uart1_rxd */
AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_txd.uart1_txd */
>;
};
};
/* USB */
&usb {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&usb_pins>;
};
&usb_ctrl_mod {
status = "okay";
};
&usb0_phy {
status = "okay";
};
&usb1_phy {
status = "okay";
};
&usb0 {
status = "okay";
dr_mode = "host";
};
&usb1 {
status = "okay";
dr_mode = "host";
};
&cppi41dma {
status = "okay";
};
&am33xx_pinmux {
usb_pins: pinmux_usb {
pinctrl-single,pins = <
/* USB0 Over-Current (active low) */
AM33XX_IOPAD(0x864, PIN_INPUT | MUX_MODE7) /* gpmc_a9.gpio1_25 */
/* USB1 Over-Current (active low) */
AM33XX_IOPAD(0x868, PIN_INPUT | MUX_MODE7) /* gpmc_a10.gpio1_26 */
>;
};
};
/* User IO */
&leds {
pinctrl-names = "default";
pinctrl-0 = <&user_leds_pins>;
led0 {
label = "pepper:user0:blue";
gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "none";
default-state = "off";
};
led1 {
label = "pepper:user1:red";
gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "none";
default-state = "off";
};
};
&buttons {
pinctrl-names = "default";
pinctrl-0 = <&user_buttons_pins>;
#address-cells = <1>;
#size-cells = <0>;
button0 {
label = "home";
linux,code = <KEY_HOME>;
gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
wakeup-source;
};
button1 {
label = "menu";
linux,code = <KEY_MENU>;
gpios = <&gpio1 23 GPIO_ACTIVE_LOW>;
wakeup-source;
};
buttons2 {
label = "power";
linux,code = <KEY_POWER>;
gpios = <&gpio0 7 GPIO_ACTIVE_LOW>;
wakeup-source;
};
};
&am33xx_pinmux {
user_leds_pins: pinmux_user_leds {
pinctrl-single,pins = <
AM33XX_IOPAD(0x850, PIN_OUTPUT | MUX_MODE7) /* gpmc_a4.gpio1_20 */
AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE7) /* gpmc_a5.gpio1_21 */
>;
};
user_buttons_pins: pinmux_user_buttons {
pinctrl-single,pins = <
AM33XX_IOPAD(0x858, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_a6.gpio1_22 */
AM33XX_IOPAD(0x85C, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_a7.gpio1_21 */
AM33XX_IOPAD(0x964, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_a8.gpio0_7 */
>;
};
};

View File

@@ -1,373 +0,0 @@
/*
* Copyright (C) 2015 Phytec Messtechnik GmbH
* Author: Teresa Remmet <t.remmet@phytec.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "am33xx.dtsi"
#include <dt-bindings/interrupt-controller/irq.h>
/ {
model = "Phytec AM335x phyCORE";
compatible = "phytec,am335x-phycore-som", "ti,am33xx";
aliases {
rtc0 = &i2c_rtc;
rtc1 = &rtc;
};
cpus {
cpu@0 {
cpu0-supply = <&vdd1_reg>;
};
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>; /* 256 MB */
};
regulators {
compatible = "simple-bus";
vcc5v: fixedregulator0 {
compatible = "regulator-fixed";
regulator-name = "vcc5v";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-boot-on;
regulator-always-on;
};
};
};
/* Crypto Module */
&aes {
status = "okay";
};
&sham {
status = "okay";
};
/* Ethernet */
&am33xx_pinmux {
ethernet0_pins: pinmux_ethernet0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_crs.rmii1_crs_dv */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxerr.rmii1_rxerr */
AM33XX_IOPAD(0x914, PIN_OUTPUT | MUX_MODE1) /* mii1_txen.rmii1_txen */
AM33XX_IOPAD(0x924, PIN_OUTPUT | MUX_MODE1) /* mii1_txd1.rmii1_txd1 */
AM33XX_IOPAD(0x928, PIN_OUTPUT | MUX_MODE1) /* mii1_txd0.rmii1_txd0 */
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd1.rmii1_rxd1 */
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE1) /* mii1_rxd0.rmii1_rxd0 */
AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii1_refclk.rmii1_refclk */
>;
};
mdio_pins: pinmux_mdio {
pinctrl-single,pins = <
/* MDIO */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
>;
};
};
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <0>;
phy-mode = "rmii";
dual_emac_res_vlan = <1>;
};
&davinci_mdio {
pinctrl-names = "default";
pinctrl-0 = <&mdio_pins>;
status = "okay";
};
&mac {
slaves = <1>;
pinctrl-names = "default";
pinctrl-0 = <&ethernet0_pins>;
status = "okay";
};
&phy_sel {
rmii-clock-ext;
};
/* I2C Busses */
&am33xx_pinmux {
i2c0_pins: pinmux_i2c0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x988, PIN_INPUT | MUX_MODE0) /* i2c0_sda.i2c0_sda */
AM33XX_IOPAD(0x98c, PIN_INPUT | MUX_MODE0) /* i2c0_scl.i2c0_scl */
>;
};
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
clock-frequency = <400000>;
status = "okay";
tps: pmic@2d {
reg = <0x2d>;
};
i2c_eeprom: eeprom@52 {
compatible = "atmel,24c32";
pagesize = <32>;
reg = <0x52>;
status = "disabled";
};
i2c_rtc: rtc@68 {
compatible = "rv4162";
reg = <0x68>;
status = "disabled";
};
};
/* NAND memory */
&am33xx_pinmux {
nandflash_pins: pinmux_nandflash {
pinctrl-single,pins = <
AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */
AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */
AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */
AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */
AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */
AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */
AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */
AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */
AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */
AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */
AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */
AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */
AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */
AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */
>;
};
};
&elm {
status = "okay";
};
&gpmc {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&nandflash_pins>;
ranges = <0 0 0x08000000 0x1000000>; /* CS0: NAND */
nandflash: nand@0,0 {
compatible = "ti,omap2-nand";
reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
interrupt-parent = <&gpmc>;
interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
<1 IRQ_TYPE_NONE>; /* termcount */
rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
nand-bus-width = <8>;
ti,nand-ecc-opt = "bch8";
gpmc,device-nand = "true";
gpmc,device-width = <1>;
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;
gpmc,cs-rd-off-ns = <30>;
gpmc,cs-wr-off-ns = <30>;
gpmc,adv-on-ns = <0>;
gpmc,adv-rd-off-ns = <30>;
gpmc,adv-wr-off-ns = <30>;
gpmc,we-on-ns = <0>;
gpmc,we-off-ns = <20>;
gpmc,oe-on-ns = <10>;
gpmc,oe-off-ns = <30>;
gpmc,access-ns = <30>;
gpmc,rd-cycle-ns = <30>;
gpmc,wr-cycle-ns = <30>;
gpmc,bus-turnaround-ns = <0>;
gpmc,cycle2cycle-delay-ns = <50>;
gpmc,cycle2cycle-diffcsen;
gpmc,clk-activation-ns = <0>;
gpmc,wr-access-ns = <30>;
gpmc,wr-data-mux-bus-ns = <0>;
ti,elm-id = <&elm>;
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "xload";
reg = <0x0 0x20000>;
};
partition@1 {
label = "xload_backup1";
reg = <0x20000 0x20000>;
};
partition@2 {
label = "xload_backup2";
reg = <0x40000 0x20000>;
};
partition@3 {
label = "xload_backup3";
reg = <0x60000 0x20000>;
};
partition@4 {
label = "barebox";
reg = <0x80000 0x80000>;
};
partition@5 {
label = "bareboxenv";
reg = <0x100000 0x40000>;
};
partition@6 {
label = "oftree";
reg = <0x140000 0x40000>;
};
partition@7 {
label = "kernel";
reg = <0x180000 0x800000>;
};
partition@8 {
label = "root";
reg = <0x980000 0x0>;
};
};
};
/* Power */
#include "tps65910.dtsi"
&tps {
vcc1-supply = <&vcc5v>;
vcc2-supply = <&vcc5v>;
vcc3-supply = <&vcc5v>;
vcc4-supply = <&vcc5v>;
vcc5-supply = <&vcc5v>;
vcc6-supply = <&vcc5v>;
vcc7-supply = <&vcc5v>;
vccio-supply = <&vcc5v>;
regulators {
vrtc_reg: regulator@0 {
regulator-always-on;
};
vio_reg: regulator@1 {
regulator-always-on;
};
vdd1_reg: regulator@2 {
/* VDD_MPU voltage limits 0.95V - 1.325V with +/-4% tolerance */
regulator-name = "vdd_mpu";
regulator-min-microvolt = <912500>;
regulator-max-microvolt = <1378000>;
regulator-boot-on;
regulator-always-on;
};
vdd2_reg: regulator@3 {
/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
regulator-name = "vdd_core";
regulator-min-microvolt = <912500>;
regulator-max-microvolt = <1150000>;
regulator-boot-on;
regulator-always-on;
};
vdd3_reg: regulator@4 {
regulator-always-on;
};
vdig1_reg: regulator@5 {
regulator-name = "vdig1_1p8v";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
vdig2_reg: regulator@6 {
regulator-always-on;
};
vpll_reg: regulator@7 {
regulator-always-on;
};
vdac_reg: regulator@8 {
regulator-always-on;
};
vaux1_reg: regulator@9 {
regulator-always-on;
};
vaux2_reg: regulator@10 {
regulator-always-on;
};
vaux33_reg: regulator@11 {
regulator-always-on;
};
vmmc_reg: regulator@12 {
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
};
};
/* SPI Busses */
&am33xx_pinmux {
spi0_pins: pinmux_spi0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x950, PIN_INPUT_PULLDOWN | MUX_MODE0) /* spi0_clk.spi0_clk */
AM33XX_IOPAD(0x954, PIN_INPUT_PULLDOWN | MUX_MODE0) /* spi0_d0.spi0_d0 */
AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_d1.spi0_d1 */
AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0) /* spi0_cs0.spi0_cs0 */
>;
};
};
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
status = "okay";
serial_flash: m25p80@0 {
compatible = "m25p80";
spi-max-frequency = <48000000>;
reg = <0x0>;
m25p,fast-read;
status = "disabled";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "xload";
reg = <0x0 0x20000>;
};
partition@1 {
label = "barebox";
reg = <0x20000 0x80000>;
};
partition@2 {
label = "bareboxenv";
reg = <0xa0000 0x20000>;
};
partition@3 {
label = "oftree";
reg = <0xc0000 0x20000>;
};
partition@4 {
label = "kernel";
reg = <0xe0000 0x0>;
};
};
};

View File

@@ -1,219 +0,0 @@
/*
* am335x-sbc-t335.dts - Device Tree file for Compulab SBC-T335
*
* Copyright (C) 2014 - 2015 CompuLab Ltd. - http://www.compulab.co.il/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include "am335x-cm-t335.dts"
/ {
model = "CompuLab CM-T335 on SB-T335";
compatible = "compulab,sbc-t335", "compulab,cm-t335", "ti,am33xx";
/* DRM display driver */
panel {
compatible = "ti,tilcdc,panel";
status = "okay";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&lcd_pins_default>;
pinctrl-1 = <&lcd_pins_sleep>;
panel-info {
ac-bias = <255>;
ac-bias-intrpt = <0>;
dma-burst-sz = <16>;
bpp = <32>;
fdd = <0x80>;
sync-edge = <0>;
sync-ctrl = <1>;
raster-order = <0>;
fifo-th = <0>;
};
display-timings {
/* Timing selection performed by U-Boot */
timing0: lcd {/* 800x480p62 */
clock-frequency = <30000000>;
hactive = <800>;
vactive = <480>;
hfront-porch = <39>;
hback-porch = <39>;
hsync-len = <47>;
vback-porch = <29>;
vfront-porch = <13>;
vsync-len = <2>;
hsync-active = <1>;
vsync-active = <1>;
};
timing1: dvi { /* 1024x768p60 */
clock-frequency = <65000000>;
hactive = <1024>;
hfront-porch = <24>;
hback-porch = <160>;
hsync-len = <136>;
vactive = <768>;
vfront-porch = <3>;
vback-porch = <29>;
vsync-len = <6>;
hsync-active = <0>;
vsync-active = <0>;
};
};
};
};
&am33xx_pinmux {
/* Display */
lcd_pins_default: lcd_pins_default {
pinctrl-single,pins = <
/* gpmc_ad8.lcd_data23 */
AM33XX_IOPAD(0x820, PIN_OUTPUT | MUX_MODE1)
/* gpmc_ad9.lcd_data22 */
AM33XX_IOPAD(0x824, PIN_OUTPUT | MUX_MODE1)
/* gpmc_ad10.lcd_data21 */
AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE1)
/* gpmc_ad11.lcd_data20 */
AM33XX_IOPAD(0x82c, PIN_OUTPUT | MUX_MODE1)
/* gpmc_ad12.lcd_data19 */
AM33XX_IOPAD(0x830, PIN_OUTPUT | MUX_MODE1)
/* gpmc_ad13.lcd_data18 */
AM33XX_IOPAD(0x834, PIN_OUTPUT | MUX_MODE1)
/* gpmc_ad14.lcd_data17 */
AM33XX_IOPAD(0x838, PIN_OUTPUT | MUX_MODE1)
/* gpmc_ad15.lcd_data16 */
AM33XX_IOPAD(0x83c, PIN_OUTPUT | MUX_MODE1)
/* lcd_data0.lcd_data0 */
AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0)
/* lcd_data1.lcd_data1 */
AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0)
/* lcd_data2.lcd_data2 */
AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0)
/* lcd_data3.lcd_data3 */
AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0)
/* lcd_data4.lcd_data4 */
AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0)
/* lcd_data5.lcd_data5 */
AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0)
/* lcd_data6.lcd_data6 */
AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0)
/* lcd_data7.lcd_data7 */
AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0)
/* lcd_data8.lcd_data8 */
AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0)
/* lcd_data9.lcd_data9 */
AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0)
/* lcd_data10.lcd_data10 */
AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0)
/* lcd_data11.lcd_data11 */
AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0)
/* lcd_data12.lcd_data12 */
AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0)
/* lcd_data13.lcd_data13 */
AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0)
/* lcd_data14.lcd_data14 */
AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0)
/* lcd_data15.lcd_data15 */
AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0)
/* lcd_vsync.lcd_vsync */
AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0)
/* lcd_hsync.lcd_hsync */
AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0)
/* lcd_pclk.lcd_pclk */
AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0)
/* lcd_ac_bias_en.lcd_ac_bias_en */
AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0)
>;
};
lcd_pins_sleep: lcd_pins_sleep {
pinctrl-single,pins = <
/* gpmc_ad8.lcd_data23 */
AM33XX_IOPAD(0x820, PIN_INPUT_PULLDOWN | MUX_MODE7)
/* gpmc_ad9.lcd_data22 */
AM33XX_IOPAD(0x824, PIN_INPUT_PULLDOWN | MUX_MODE7)
/* gpmc_ad10.lcd_data21 */
AM33XX_IOPAD(0x828, PIN_INPUT_PULLDOWN | MUX_MODE7)
/* gpmc_ad11.lcd_data20 */
AM33XX_IOPAD(0x82c, PIN_INPUT_PULLDOWN | MUX_MODE7)
/* gpmc_ad12.lcd_data19 */
AM33XX_IOPAD(0x830, PIN_INPUT_PULLDOWN | MUX_MODE7)
/* gpmc_ad13.lcd_data18 */
AM33XX_IOPAD(0x834, PIN_INPUT_PULLDOWN | MUX_MODE7)
/* gpmc_ad14.lcd_data17 */
AM33XX_IOPAD(0x838, PIN_INPUT_PULLDOWN | MUX_MODE7)
/* gpmc_ad15.lcd_data16 */
AM33XX_IOPAD(0x83c, PIN_INPUT_PULLDOWN | MUX_MODE7)
/* lcd_data0.lcd_data0 */
AM33XX_IOPAD(0x8a0, PULL_DISABLE | MUX_MODE7)
/* lcd_data1.lcd_data1 */
AM33XX_IOPAD(0x8a4, PULL_DISABLE | MUX_MODE7)
/* lcd_data2.lcd_data2 */
AM33XX_IOPAD(0x8a8, PULL_DISABLE | MUX_MODE7)
/* lcd_data3.lcd_data3 */
AM33XX_IOPAD(0x8ac, PULL_DISABLE | MUX_MODE7)
/* lcd_data4.lcd_data4 */
AM33XX_IOPAD(0x8b0, PULL_DISABLE | MUX_MODE7)
/* lcd_data5.lcd_data5 */
AM33XX_IOPAD(0x8b4, PULL_DISABLE | MUX_MODE7)
/* lcd_data6.lcd_data6 */
AM33XX_IOPAD(0x8b8, PULL_DISABLE | MUX_MODE7)
/* lcd_data7.lcd_data7 */
AM33XX_IOPAD(0x8bc, PULL_DISABLE | MUX_MODE7)
/* lcd_data8.lcd_data8 */
AM33XX_IOPAD(0x8c0, PULL_DISABLE | MUX_MODE7)
/* lcd_data9.lcd_data9 */
AM33XX_IOPAD(0x8c4, PULL_DISABLE | MUX_MODE7)
/* lcd_data10.lcd_data10 */
AM33XX_IOPAD(0x8c8, PULL_DISABLE | MUX_MODE7)
/* lcd_data11.lcd_data11 */
AM33XX_IOPAD(0x8cc, PULL_DISABLE | MUX_MODE7)
/* lcd_data12.lcd_data12 */
AM33XX_IOPAD(0x8d0, PULL_DISABLE | MUX_MODE7)
/* lcd_data13.lcd_data13 */
AM33XX_IOPAD(0x8d4, PULL_DISABLE | MUX_MODE7)
/* lcd_data14.lcd_data14 */
AM33XX_IOPAD(0x8d8, PULL_DISABLE | MUX_MODE7)
/* lcd_data15.lcd_data15 */
AM33XX_IOPAD(0x8dc, PULL_DISABLE | MUX_MODE7)
/* lcd_vsync.lcd_vsync */
AM33XX_IOPAD(0x8e0, PIN_INPUT_PULLDOWN | MUX_MODE7)
/* lcd_hsync.lcd_hsync */
AM33XX_IOPAD(0x8e4, PIN_INPUT_PULLDOWN | MUX_MODE7)
/* lcd_pclk.lcd_pclk */
AM33XX_IOPAD(0x8e8, PIN_INPUT_PULLDOWN | MUX_MODE7)
/* lcd_ac_bias_en.lcd_ac_bias_en */
AM33XX_IOPAD(0x8ec, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
};
&i2c0 {
/* GPIO extender */
gpio_ext: pca9555@26 {
compatible = "nxp,pca9555";
pinctrl-names = "default";
gpio-controller;
#gpio-cells = <2>;
reg = <0x26>;
dvi_ena {
gpio-hog;
gpios = <13 GPIO_ACTIVE_HIGH>;
output-high;
line-name = "dvi-enable";
};
lcd_ena {
gpio-hog;
gpios = <11 GPIO_ACTIVE_HIGH>;
output-high;
line-name = "lcd-enable";
};
};
};
/* Display */
&lcdc {
status = "okay";
};

View File

@@ -1,577 +0,0 @@
/*
* support for the bosch am335x based shc c3 board
*
* Copyright, C) 2015 Heiko Schocher <hs@denx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
#include "am33xx.dtsi"
#include <dt-bindings/input/input.h>
/ {
model = "Bosch SHC";
compatible = "ti,am335x-shc", "ti,am335x-bone", "ti,am33xx";
aliases {
mmcblk0 = &mmc1;
mmcblk1 = &mmc2;
};
cpus {
cpu@0 {
/*
* To consider voltage drop between PMIC and SoC,
* tolerance value is reduced to 2% from 4% and
* voltage value is increased as a precaution.
*/
operating-points = <
/* kHz uV */
594000 1225000
294000 1125000
>;
voltage-tolerance = <2>; /* 2 percentage */
cpu0-supply = <&dcdc2_reg>;
};
};
gpio_keys {
compatible = "gpio-keys";
back_button {
label = "Back Button";
gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>;
linux,code = <KEY_BACK>;
debounce-interval = <1000>;
wakeup-source;
};
front_button {
label = "Front Button";
gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>;
linux,code = <KEY_FRONT>;
debounce-interval = <1000>;
wakeup-source;
};
};
leds {
pinctrl-names = "default";
pinctrl-0 = <&user_leds_s0>;
compatible = "gpio-leds";
led1 {
label = "shc:power:red";
gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led2 {
label = "shc:power:bl";
gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
default-state = "on";
};
led3 {
label = "shc:lan:red";
gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led4 {
label = "shc:lan:bl";
gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led5 {
label = "shc:cloud:red";
gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
led6 {
label = "shc:cloud:bl";
gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x20000000>; /* 512 MB */
};
vmmcsd_fixed: fixedregulator0 {
compatible = "regulator-fixed";
regulator-name = "vmmcsd_fixed";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
};
&aes {
status = "okay";
};
&cppi41dma {
status = "okay";
};
&davinci_mdio {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
status = "okay";
ethernetphy0: ethernet-phy@0 {
reg = <0>;
smsc,disable-energy-detect;
};
};
&epwmss1 {
status = "okay";
ehrpwm1: pwm@48302200 {
pinctrl-names = "default";
pinctrl-0 = <&ehrpwm1_pins>;
status = "okay";
};
};
&gpio1 {
hmtc_rst {
gpio-hog;
gpios = <24 GPIO_ACTIVE_LOW>;
output-high;
line-name = "homematic_reset";
};
hmtc_prog {
gpio-hog;
gpios = <27 GPIO_ACTIVE_LOW>;
output-high;
line-name = "homematic_program";
};
};
&gpio3 {
zgb_rst {
gpio-hog;
gpios = <18 GPIO_ACTIVE_LOW>;
output-low;
line-name = "zigbee_reset";
};
zgb_boot {
gpio-hog;
gpios = <19 GPIO_ACTIVE_HIGH>;
output-high;
line-name = "zigbee_boot";
};
};
&i2c0 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
status = "okay";
clock-frequency = <400000>;
tps: tps@24 {
reg = <0x24>;
};
at24@50 {
compatible = "at24,24c32";
pagesize = <32>;
reg = <0x50>;
};
pcf8563@51 {
compatible = "nxp,pcf8563";
reg = <0x51>;
};
};
&mac {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
status = "okay";
slaves = <1>;
cpsw_emac0: slave@4a100200 {
phy_id = <&davinci_mdio>, <0>;
phy-mode = "mii";
phy-handle = <&ethernetphy0>;
};
};
&mmc1 {
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins>;
bus-width = <0x4>;
cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
cd-inverted;
max-frequency = <26000000>;
vmmc-supply = <&vmmcsd_fixed>;
status = "okay";
};
&mmc2 {
pinctrl-names = "default";
pinctrl-0 = <&emmc_pins>;
bus-width = <8>;
max-frequency = <26000000>;
sd-uhs-sdr25;
vmmc-supply = <&vmmcsd_fixed>;
status = "okay";
};
&mmc3 {
pinctrl-names = "default";
pinctrl-0 = <&mmc3_pins>;
bus-width = <4>;
cap-power-off-card;
max-frequency = <26000000>;
sd-uhs-sdr25;
vmmc-supply = <&vmmcsd_fixed>;
status = "okay";
};
&rtc {
ti,no-init;
};
&sham {
status = "okay";
};
&tps {
compatible = "ti,tps65217";
ti,pmic-shutdown-controller;
regulators {
#address-cells = <1>;
#size-cells = <0>;
dcdc1_reg: regulator@0 {
reg = <0>;
regulator-name = "vdds_dpr";
regulator-compatible = "dcdc1";
regulator-min-microvolt = <1300000>;
regulator-max-microvolt = <1450000>;
regulator-boot-on;
regulator-always-on;
};
dcdc2_reg: regulator@1 {
reg = <1>;
/*
* VDD_MPU voltage limits 0.95V - 1.26V with
* +/-4% tolerance
*/
regulator-compatible = "dcdc2";
regulator-name = "vdd_mpu";
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <1375000>;
regulator-boot-on;
regulator-always-on;
regulator-ramp-delay = <70000>;
};
dcdc3_reg: regulator@2 {
reg = <2>;
/*
* VDD_CORE voltage limits 0.95V - 1.1V with
* +/-4% tolerance
*/
regulator-name = "vdd_core";
regulator-compatible = "dcdc3";
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <1125000>;
regulator-boot-on;
regulator-always-on;
};
ldo1_reg: regulator@3 {
reg = <3>;
regulator-name = "vio,vrtc,vdds";
regulator-compatible = "ldo1";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
ldo2_reg: regulator@4 {
reg = <4>;
regulator-name = "vdd_3v3aux";
regulator-compatible = "ldo2";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
ldo3_reg: regulator@5 {
reg = <5>;
regulator-name = "vdd_1v8";
regulator-compatible = "ldo3";
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
ldo4_reg: regulator@6 {
reg = <6>;
regulator-name = "vdd_3v3a";
regulator-compatible = "ldo4";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
};
};
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
status = "okay";
};
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins>;
status = "okay";
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
status = "okay";
};
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins>;
status = "okay";
};
&usb {
status = "okay";
};
&usb_ctrl_mod {
status = "okay";
};
&usb1_phy {
status = "okay";
};
&usb1 {
status = "okay";
dr_mode = "host";
};
&am33xx_pinmux {
pinctrl-names = "default";
pinctrl-0 = <&clkout2_pin>;
clkout2_pin: pinmux_clkout2_pin {
pinctrl-single,pins = <
/* xdma_event_intr1.clkout2 */
AM33XX_IOPAD(0x9b4, PIN_INPUT | MUX_MODE6)
>;
};
cpsw_default: cpsw_default {
pinctrl-single,pins = <
/* Slave 1 */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE0)
AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE0)
>;
};
cpsw_sleep: cpsw_sleep {
pinctrl-single,pins = <
/* Slave 1 reset value */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
davinci_mdio_default: davinci_mdio_default {
pinctrl-single,pins = <
/* mdio_data.mdio_data */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0)
/* mdio_clk.mdio_clk */
AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0)
>;
};
davinci_mdio_sleep: davinci_mdio_sleep {
pinctrl-single,pins = <
/* MDIO reset value */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
ehrpwm1_pins: pinmux_ehrpwm1 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x84c, PIN_OUTPUT | MUX_MODE6) /* gpmc_a3.gpio1_19 */
>;
};
emmc_pins: pinmux_emmc_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x880, PIN_INPUT | MUX_MODE2)
AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2)
AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1)
AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1)
AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1)
AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1)
AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1)
AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1)
AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1)
AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1)
>;
};
i2c0_pins: pinmux_i2c0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x988, PIN_INPUT | MUX_MODE0)
AM33XX_IOPAD(0x98c, PIN_INPUT | MUX_MODE0)
>;
};
mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE5)
>;
};
mmc3_pins: pinmux_mmc3_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x830, PIN_INPUT | MUX_MODE3)
AM33XX_IOPAD(0x834, PIN_INPUT | MUX_MODE3)
AM33XX_IOPAD(0x838, PIN_INPUT | MUX_MODE3)
AM33XX_IOPAD(0x83c, PIN_INPUT | MUX_MODE3)
AM33XX_IOPAD(0x888, PIN_INPUT | MUX_MODE3)
AM33XX_IOPAD(0x88c, PIN_INPUT | MUX_MODE3)
>;
};
uart0_pins: pinmux_uart0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x968, PIN_INPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x96c, PIN_OUTPUT | MUX_MODE0)
AM33XX_IOPAD(0x970, PIN_INPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x974, PIN_OUTPUT | MUX_MODE0)
>;
};
uart1_pins: pinmux_uart1 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x978, PIN_INPUT_PULLDOWN | MUX_MODE0)
AM33XX_IOPAD(0x97C, PIN_OUTPUT | MUX_MODE0)
AM33XX_IOPAD(0x980, PIN_INPUT | MUX_MODE0)
AM33XX_IOPAD(0x984, PIN_OUTPUT | MUX_MODE0)
>;
};
uart2_pins: pinmux_uart2_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x950, PIN_INPUT | MUX_MODE1)
AM33XX_IOPAD(0x954, PIN_OUTPUT | MUX_MODE1)
>;
};
uart4_pins: pinmux_uart4_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE6)
AM33XX_IOPAD(0x874, PIN_OUTPUT_PULLUP | MUX_MODE6)
>;
};
user_leds_s0: user_leds_s0 {
pinctrl-single,pins = <
AM33XX_IOPAD(0x820, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x824, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x82c, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x840, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x844, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x848, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x858, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x85c, PIN_OUTPUT_PULLUP | MUX_MODE7)
AM33XX_IOPAD(0x860, PIN_INPUT | MUX_MODE7)
AM33XX_IOPAD(0x864, PIN_INPUT | MUX_MODE7)
AM33XX_IOPAD(0x868, PIN_INPUT | MUX_MODE7)
AM33XX_IOPAD(0x86c, PIN_INPUT | MUX_MODE7)
AM33XX_IOPAD(0x878, PIN_OUTPUT_PULLUP | MUX_MODE7)
AM33XX_IOPAD(0x87c, PIN_INPUT | MUX_MODE7)
AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x894, PIN_INPUT | MUX_MODE7)
AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x958, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x95c, PIN_OUTPUT | MUX_MODE7)
AM33XX_IOPAD(0x964, PIN_OUTPUT_PULLUP | MUX_MODE7)
AM33XX_IOPAD(0x9a0, PIN_OUTPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x9a4, PIN_OUTPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x9a8, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLUP | MUX_MODE7)
>;
};
};

View File

@@ -1,507 +0,0 @@
/*
* Copyright (C) 2015 Toby Churchill - http://www.toby-churchill.com/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
#include "am33xx.dtsi"
/ {
model = "Toby Churchill SL50 Series";
compatible = "tcl,am335x-sl50", "ti,am33xx";
cpus {
cpu@0 {
cpu0-supply = <&dcdc2_reg>;
};
};
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x20000000>; /* 512 MB */
};
chosen {
stdout-path = &uart0;
};
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&led_pins>;
led0 {
label = "sl50:green:usr0";
gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
default-state = "off";
};
led1 {
label = "sl50:red:usr1";
gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
default-state = "off";
};
led2 {
label = "sl50:green:usr2";
gpios = <&gpio1 23 GPIO_ACTIVE_LOW>;
default-state = "off";
};
led3 {
label = "sl50:red:usr3";
gpios = <&gpio1 24 GPIO_ACTIVE_LOW>;
default-state = "off";
};
};
backlight0: disp0 {
compatible = "pwm-backlight";
pwms = <&ehrpwm1 0 500000 0>;
brightness-levels = <0 10 20 30 40 50 60 70 80 90 99>;
default-brightness-level = <6>;
};
backlight1: disp1 {
compatible = "pwm-backlight";
pwms = <&ehrpwm1 1 500000 0>;
brightness-levels = <0 10 20 30 40 50 60 70 80 90 99>;
default-brightness-level = <6>;
};
clocks {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <0>;
/* audio external oscillator */
tlv320aic3x_mclk: oscillator@0 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <24576000>; /* 24.576MHz */
};
};
sound {
compatible = "ti,da830-evm-audio";
ti,model = "AM335x-SL50";
ti,audio-codec = <&audio_codec>;
ti,mcasp-controller = <&mcasp0>;
clocks = <&tlv320aic3x_mclk>;
clock-names = "mclk";
ti,audio-routing =
"Headphone Jack", "HPLOUT",
"Headphone Jack", "HPROUT",
"LINE1R", "Line In",
"LINE1L", "Line In";
};
emmc_pwrseq: pwrseq@0 {
compatible = "mmc-pwrseq-emmc";
pinctrl-names = "default";
pinctrl-0 = <&emmc_pwrseq_pins>;
reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
};
vmmcsd_fixed: fixedregulator0 {
compatible = "regulator-fixed";
regulator-name = "vmmcsd_fixed";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
};
&am33xx_pinmux {
pinctrl-names = "default";
pinctrl-0 = <&lwb_pins>;
led_pins: pinmux_led_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE7) /* gpmc_a5.gpio1_21 */
AM33XX_IOPAD(0x858, PIN_OUTPUT | MUX_MODE7) /* gpmc_a6.gpio1_22 */
AM33XX_IOPAD(0x85c, PIN_OUTPUT | MUX_MODE7) /* gpmc_a7.gpio1_23 */
AM33XX_IOPAD(0x860, PIN_OUTPUT | MUX_MODE7) /* gpmc_a8.gpio1_24 */
>;
};
uart0_pins: pinmux_uart0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
>;
};
uart4_pins: pinmux_uart4_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE6) /* gpmc_wait0.uart4_rxd */
AM33XX_IOPAD(0x874, PIN_OUTPUT_PULLDOWN | MUX_MODE6) /* gpmc_wpn.uart4_txd */
>;
};
i2c0_pins: pinmux_i2c0_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */
AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */
>;
};
i2c1_pins: pinmux_i2c1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_rxd.i2c1_sda */
AM33XX_IOPAD(0x984, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_txdi2c1_scl */
>;
};
i2c2_pins: pinmux_i2c2_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_ctsn.i2c2_sda */
AM33XX_IOPAD(0x97c, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_rtsn.i2c2_scl */
>;
};
cpsw_default: cpsw_default {
pinctrl-single,pins = <
/* Slave 1 */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxerr.mii1_rxerr */
AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txen.mii1_txen */
AM33XX_IOPAD(0x918, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxdv.mii1_rxdv */
AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd3.mii1_txd3 */
AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd2.mii1_txd2 */
AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd1.mii1_txd1 */
AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd0.mii1_txd0 */
AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_txclk.mii1_txclk */
AM33XX_IOPAD(0x930, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxclk.mii1_rxclk */
AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd3.mii1_rxd3 */
AM33XX_IOPAD(0x938, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd2.mii1_rxd2 */
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd1.mii1_rxd1 */
AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd0.mii1_rxd0 */
>;
};
cpsw_sleep: cpsw_sleep {
pinctrl-single,pins = <
/* Slave 1 reset value */
AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
davinci_mdio_default: davinci_mdio_default {
pinctrl-single,pins = <
/* MDIO */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */
AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */
>;
};
davinci_mdio_sleep: davinci_mdio_sleep {
pinctrl-single,pins = <
/* MDIO reset value */
AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7)
AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7)
>;
};
mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
>;
};
emmc_pwrseq_pins: pinmux_emmc_pwrseq_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a4.gpio1_20 */
>;
};
emmc_pins: pinmux_emmc_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */
AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
>;
};
audio_pins: pinmux_audio_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
AM33XX_IOPAD(0x994, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */
AM33XX_IOPAD(0x990, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */
AM33XX_IOPAD(0x998, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_axr0.mcasp0_axr0 */
AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2 */
>;
};
ehrpwm1_pins: pinmux_ehrpwm1a_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x848, PIN_OUTPUT | MUX_MODE6) /* gpmc_a2.ehrpwm1a */
AM33XX_IOPAD(0x84c, PIN_OUTPUT | MUX_MODE6) /* gpmc_a3.ehrpwm1b */
>;
};
lwb_pins: pinmux_lwb_pins {
pinctrl-single,pins = <
AM33XX_IOPAD(0x9a4, PIN_OUTPUT | MUX_MODE7) /* SoundPA_en - mcasp0_fsr.gpio3_19 */
AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE7) /* nKbdOnC - gpmc_ad10.gpio0_26 */
AM33XX_IOPAD(0x830, PIN_INPUT_PULLUP | MUX_MODE7) /* nKbdInt - gpmc_ad12.gpio1_12 */
AM33XX_IOPAD(0x834, PIN_INPUT_PULLUP | MUX_MODE7) /* nKbdReset - gpmc_ad13.gpio1_13 */
AM33XX_IOPAD(0x838, PIN_INPUT_PULLUP | MUX_MODE7) /* nDispReset - gpmc_ad14.gpio1_14 */
AM33XX_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE7) /* USB1_enPower - gpmc_a1.gpio1_17 */
/* AVR Programming - SPI Bus (bit bang) - Screen and Keyboard */
AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE7) /* Kbd/Disp/BattMOSI spi0_d0.gpio0_3 */
AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE7) /* Kbd/Disp/BattMISO spi0_d1.gpio0_4 */
AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE7) /* Kbd/Disp/BattSCLK spi0_clk.gpio0_2 */
/* PDI Bus - Battery system */
AM33XX_IOPAD(0x840, PIN_INPUT_PULLUP | MUX_MODE7) /* nBattReset gpmc_a0.gpio1_16 */
AM33XX_IOPAD(0x83c, PIN_INPUT_PULLUP | MUX_MODE7) /* BattPDIData gpmc_ad15.gpio1_15 */
>;
};
};
&i2c0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins>;
clock-frequency = <400000>;
tps: tps@24 {
reg = <0x24>;
};
eeprom: eeprom@50 {
compatible = "at,24c256";
reg = <0x50>;
};
};
&i2c1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
};
&i2c2 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c2_pins>;
clock-frequency = <400000>;
audio_codec: tlv320aic3106@1b {
status = "okay";
compatible = "ti,tlv320aic3106";
reg = <0x1b>;
AVDD-supply = <&ldo4_reg>;
IOVDD-supply = <&ldo4_reg>;
DRVDD-supply = <&ldo4_reg>;
DVDD-supply = <&ldo3_reg>;
};
};
&usb {
status = "okay";
};
&usb_ctrl_mod {
status = "okay";
};
&usb0_phy {
status = "okay";
};
&usb1_phy {
status = "okay";
};
&usb0 {
status = "okay";
dr_mode = "peripheral";
};
&usb1 {
status = "okay";
dr_mode = "host";
};
&cppi41dma {
status = "okay";
};
&mmc1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mmc1_pins>;
bus-width = <4>;
cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
vmmc-supply = <&vmmcsd_fixed>;
};
&mmc2 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&emmc_pins>;
bus-width = <8>;
vmmc-supply = <&vmmcsd_fixed>;
mmc-pwrseq = <&emmc_pwrseq>;
};
&mcasp0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&audio_pins>;
op-mode = <0>; /* MCASP_ISS_MODE */
tdm-slots = <2>;
serial-dir = <
2 0 1 0
0 0 0 0
0 0 0 0
0 0 0 0
>;
tx-num-evt = <1>;
rx-num-evt = <1>;
};
&uart0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins>;
};
&uart4 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins>;
};
#include "tps65217.dtsi"
&tps {
ti,pmic-shutdown-controller;
interrupt-parent = <&intc>;
interrupts = <7>; /* NNMI */
regulators {
dcdc1_reg: regulator@0 {
/* VDDS_DDR */
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <1500000>;
regulator-always-on;
};
dcdc2_reg: regulator@1 {
/* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
regulator-name = "vdd_mpu";
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <1325000>;
regulator-boot-on;
regulator-always-on;
};
dcdc3_reg: regulator@2 {
/* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
regulator-name = "vdd_core";
regulator-min-microvolt = <925000>;
regulator-max-microvolt = <1150000>;
regulator-boot-on;
regulator-always-on;
};
ldo1_reg: regulator@3 {
/* VRTC / VIO / VDDS*/
regulator-always-on;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
ldo2_reg: regulator@4 {
/* VDD_3V3AUX */
regulator-always-on;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
ldo3_reg: regulator@5 {
/* VDD_1V8 */
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
ldo4_reg: regulator@6 {
/* VDD_3V3A */
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
};
};
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <0>;
phy-mode = "mii";
};
&cpsw_emac1 {
phy_id = <&davinci_mdio>, <1>;
phy-mode = "mii";
};
&mac {
status = "okay";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
};
&davinci_mdio {
status = "okay";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
};
&sham {
status = "okay";
};
&aes {
status = "okay";
};
&epwmss1 {
status = "okay";
};
&ehrpwm1 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&ehrpwm1_pins>;
};

Some files were not shown because too many files have changed in this diff Show More