xics: ICP should be big endian !
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Wed, 17 Jun 2020 11:51:16 +0000 (21:51 +1000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 19 Jun 2020 10:28:03 +0000 (20:28 +1000)
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 <benh@kernel.crashing.org>
tests/xics/xics.h
xics.vhdl

index bbb1f996586984b3179e4f66c3b468e59e1abdd6..ce83ab2d7e2fa1c131f693aae6e4d5351f4b8dc9 100644 (file)
@@ -1,5 +1,4 @@
 #include <stdint.h>
-
 #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);
 }
+
index eb41c326d75d26ed6b0a98862b9719bc6c4bd509..413fdd931591b217cdd7b344eb1b8d429a453c3b 100644 (file)
--- 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;