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 <benh@kernel.crashing.org>
pull/210/head
Benjamin Herrenschmidt 4 years ago
parent 311b653d80
commit 0fa14f6dec

@ -1,5 +1,4 @@
#include <stdint.h> #include <stdint.h>

#include "microwatt_soc.h" #include "microwatt_soc.h"
#include "io.h" #include "io.h"


@ -8,6 +7,8 @@
#define XICS_RESV 0x8 #define XICS_RESV 0x8
#define XICS_MFRR 0xC #define XICS_MFRR 0xC


#define bswap32(x) (uint32_t)__builtin_bswap32((uint32_t)(x))

uint8_t xics_read8(int offset) uint8_t xics_read8(int offset)
{ {
return readb(XICS_BASE + offset); return readb(XICS_BASE + offset);
@ -20,10 +21,11 @@ void xics_write8(int offset, uint8_t val)


uint32_t xics_read32(int offset) 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) void xics_write32(int offset, uint32_t val)
{ {
writel(val, XICS_BASE + offset); writel(bswap32(val), XICS_BASE + offset);
} }


@ -86,6 +86,19 @@ begin
variable v : reg_internal_t; variable v : reg_internal_t;
variable xirr_accept_rd : std_ulogic; variable xirr_accept_rd : std_ulogic;
variable irq_eoi : 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 begin
v := r; v := r;


@ -94,72 +107,55 @@ begin
xirr_accept_rd := '0'; xirr_accept_rd := '0';
irq_eoi := '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 if wb_in.cyc = '1' and wb_in.stb = '1' then
v.wb_ack := '1'; -- always ack v.wb_ack := '1'; -- always ack
if wb_in.we = '1' then -- write if wb_in.we = '1' then -- write
-- writes to both XIRR are the same -- writes to both XIRR are the same
case wb_in.adr(7 downto 0) is case wb_in.adr(7 downto 0) is
when XIRR_POLL => when XIRR_POLL =>
report "XICS XIRR_POLL write"; report "ICP XIRR_POLL write";
if wb_in.sel = x"f" then -- 4 bytes v.cppr := be_in(31 downto 24);
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;
when XIRR => when XIRR =>
v.cppr := be_in(31 downto 24);
if wb_in.sel = x"f" then -- 4 byte if wb_in.sel = x"f" then -- 4 byte
report "XICS XIRR write word:" & to_hstring(wb_in.dat); report "ICP XIRR write word (EOI) :" & to_hstring(be_in);
v.cppr := wb_in.dat(31 downto 24);
irq_eoi := '1'; irq_eoi := '1';
elsif wb_in.sel = x"1" then -- 1 byte elsif wb_in.sel = x"1" then -- 1 byte
report "XICS XIRR write byte:" & to_hstring(wb_in.dat(7 downto 0)); report "ICP XIRR write byte (CPPR):" & to_hstring(be_in(31 downto 24));
v.cppr := wb_in.dat(7 downto 0);
else 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; end if;
when MFRR => when MFRR =>
v.mfrr := be_in(31 downto 24);
v.mfrr_pending := '1';
if wb_in.sel = x"f" then -- 4 bytes if wb_in.sel = x"f" then -- 4 bytes
report "XICS MFRR write word:" & to_hstring(wb_in.dat); report "ICP MFRR write word:" & to_hstring(be_in);
v.mfrr_pending := '1';
v.mfrr := wb_in.dat(31 downto 24);
elsif wb_in.sel = x"1" then -- 1 byte elsif wb_in.sel = x"1" then -- 1 byte
report "XICS MFRR write byte:" & to_hstring(wb_in.dat(7 downto 0)); report "ICP MFRR write byte:" & to_hstring(be_in(31 downto 24));
v.mfrr_pending := '1';
v.mfrr := wb_in.dat(7 downto 0);
else 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; end if;
when others => when others =>
end case; end case;


else -- read else -- read
v.wb_rd_data := (others => '0');


case wb_in.adr(7 downto 0) is case wb_in.adr(7 downto 0) is
when XIRR_POLL => when XIRR_POLL =>
report "XICS XIRR_POLL read"; report "ICP XIRR_POLL read";
if wb_in.sel = x"f" then be_out := r.cppr & r.xisr;
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;
when XIRR => when XIRR =>
report "XICS XIRR read"; report "ICP XIRR read";
be_out := r.cppr & r.xisr;
if wb_in.sel = x"f" then 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'; xirr_accept_rd := '1';
elsif wb_in.sel = x"1" then
v.wb_rd_data(7 downto 0) := r.cppr;
end if; end if;
when MFRR => when MFRR =>
report "XICS MFRR read"; report "ICP MFRR read";
if wb_in.sel = x"f" then -- 4 bytes be_out(31 downto 24) := r.mfrr;
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;
when others => when others =>
end case; end case;
end if; end if;
@ -203,6 +199,8 @@ begin
v.cppr := r.pending_priority; v.cppr := r.pending_priority;
end if; end if;


v.wb_rd_data := bswap(be_out);

if irq_eoi = '1' then if irq_eoi = '1' then
v.irq := '0'; v.irq := '0';
end if; end if;

Loading…
Cancel
Save