From: Benjamin Herrenschmidt Date: Wed, 17 Jun 2020 11:51:16 +0000 (+1000) Subject: xics: ICP should be big endian ! X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0fa14f6decff1abd43f2bff87f10ad59c5aef754;p=microwatt.git xics: ICP should be big endian ! That's how Linux expects it. This also simplifies the register access implementation since the bit fields now align properly regardless of the access size. Signed-off-by: Benjamin Herrenschmidt --- diff --git a/tests/xics/xics.h b/tests/xics/xics.h index bbb1f99..ce83ab2 100644 --- a/tests/xics/xics.h +++ b/tests/xics/xics.h @@ -1,5 +1,4 @@ #include - #include "microwatt_soc.h" #include "io.h" @@ -8,6 +7,8 @@ #define XICS_RESV 0x8 #define XICS_MFRR 0xC +#define bswap32(x) (uint32_t)__builtin_bswap32((uint32_t)(x)) + uint8_t xics_read8(int offset) { return readb(XICS_BASE + offset); @@ -20,10 +21,11 @@ void xics_write8(int offset, uint8_t val) uint32_t xics_read32(int offset) { - return readl(XICS_BASE + offset); + return bswap32(readl(XICS_BASE + offset)); } void xics_write32(int offset, uint32_t val) { - writel(val, XICS_BASE + offset); + writel(bswap32(val), XICS_BASE + offset); } + diff --git a/xics.vhdl b/xics.vhdl index eb41c32..413fdd9 100644 --- a/xics.vhdl +++ b/xics.vhdl @@ -86,6 +86,19 @@ begin variable v : reg_internal_t; variable xirr_accept_rd : std_ulogic; variable irq_eoi : std_ulogic; + + function bswap(v : in std_ulogic_vector(31 downto 0)) return std_ulogic_vector is + variable r : std_ulogic_vector(31 downto 0); + begin + r( 7 downto 0) := v(31 downto 24); + r(15 downto 8) := v(23 downto 16); + r(23 downto 16) := v(15 downto 8); + r(31 downto 24) := v( 7 downto 0); + return r; + end function; + + variable be_in : std_ulogic_vector(31 downto 0); + variable be_out : std_ulogic_vector(31 downto 0); begin v := r; @@ -94,72 +107,55 @@ begin xirr_accept_rd := '0'; irq_eoi := '0'; + be_in := bswap(wb_in.dat); + be_out := (others => '0'); + if wb_in.cyc = '1' and wb_in.stb = '1' then v.wb_ack := '1'; -- always ack if wb_in.we = '1' then -- write -- writes to both XIRR are the same case wb_in.adr(7 downto 0) is when XIRR_POLL => - report "XICS XIRR_POLL write"; - if wb_in.sel = x"f" then -- 4 bytes - v.cppr := wb_in.dat(31 downto 24); - elsif wb_in.sel = x"1" then -- 1 byte - v.cppr := wb_in.dat(7 downto 0); - end if; + report "ICP XIRR_POLL write"; + v.cppr := be_in(31 downto 24); when XIRR => + v.cppr := be_in(31 downto 24); if wb_in.sel = x"f" then -- 4 byte - report "XICS XIRR write word:" & to_hstring(wb_in.dat); - v.cppr := wb_in.dat(31 downto 24); + report "ICP XIRR write word (EOI) :" & to_hstring(be_in); irq_eoi := '1'; elsif wb_in.sel = x"1" then -- 1 byte - report "XICS XIRR write byte:" & to_hstring(wb_in.dat(7 downto 0)); - v.cppr := wb_in.dat(7 downto 0); + report "ICP XIRR write byte (CPPR):" & to_hstring(be_in(31 downto 24)); else - report "XICS XIRR UNSUPPORTED write ! sel=" & to_hstring(wb_in.sel); + report "ICP XIRR UNSUPPORTED write ! sel=" & to_hstring(wb_in.sel); end if; when MFRR => + v.mfrr := be_in(31 downto 24); + v.mfrr_pending := '1'; if wb_in.sel = x"f" then -- 4 bytes - report "XICS MFRR write word:" & to_hstring(wb_in.dat); - v.mfrr_pending := '1'; - v.mfrr := wb_in.dat(31 downto 24); + report "ICP MFRR write word:" & to_hstring(be_in); elsif wb_in.sel = x"1" then -- 1 byte - report "XICS MFRR write byte:" & to_hstring(wb_in.dat(7 downto 0)); - v.mfrr_pending := '1'; - v.mfrr := wb_in.dat(7 downto 0); + report "ICP MFRR write byte:" & to_hstring(be_in(31 downto 24)); else - report "XICS MFRR UNSUPPORTED write ! sel=" & to_hstring(wb_in.sel); + report "ICP MFRR UNSUPPORTED write ! sel=" & to_hstring(wb_in.sel); end if; when others => end case; else -- read - v.wb_rd_data := (others => '0'); case wb_in.adr(7 downto 0) is when XIRR_POLL => - report "XICS XIRR_POLL read"; - if wb_in.sel = x"f" then - v.wb_rd_data(23 downto 0) := r.xisr; - v.wb_rd_data(31 downto 24) := r.cppr; - elsif wb_in.sel = x"1" then - v.wb_rd_data(7 downto 0) := r.cppr; - end if; + report "ICP XIRR_POLL read"; + be_out := r.cppr & r.xisr; when XIRR => - report "XICS XIRR read"; + report "ICP XIRR read"; + be_out := r.cppr & r.xisr; if wb_in.sel = x"f" then - v.wb_rd_data(23 downto 0) := r.xisr; - v.wb_rd_data(31 downto 24) := r.cppr; xirr_accept_rd := '1'; - elsif wb_in.sel = x"1" then - v.wb_rd_data(7 downto 0) := r.cppr; end if; when MFRR => - report "XICS MFRR read"; - if wb_in.sel = x"f" then -- 4 bytes - v.wb_rd_data(31 downto 24) := r.mfrr; - elsif wb_in.sel = x"1" then -- 1 byte - v.wb_rd_data( 7 downto 0) := r.mfrr; - end if; + report "ICP MFRR read"; + be_out(31 downto 24) := r.mfrr; when others => end case; end if; @@ -203,6 +199,8 @@ begin v.cppr := r.pending_priority; end if; + v.wb_rd_data := bswap(be_out); + if irq_eoi = '1' then v.irq := '0'; end if;