mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-04-14 07:29:47 +00:00
spi: Send dummy clocks at boot
When using an FPGA which routes the SPI clock via STARTUPE2 as is done on the Nexys Video (or optionally on Arty), the HW needs at least 3 beats of that clock to complete the switch from the internal config clock to the one we provide. This works around it by having the SPI controller send 8 dummy clocks at boot time with CS held high. Without this, flash identification will fail those boards Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
@@ -11,6 +11,9 @@ entity spi_flash_ctrl is
|
||||
DEF_CLK_DIV : natural := 2; -- Clock divider SCK = CLK/((CLK_DIV+1)*2)
|
||||
DEF_QUAD_READ : boolean := false; -- Use quad read with 8 clk dummy
|
||||
|
||||
-- Dummy clocks after boot
|
||||
BOOT_CLOCKS : boolean := true; -- Send 8 dummy clocks after boot
|
||||
|
||||
-- Number of data lines (1=MISO/MOSI, otherwise 2 or 4)
|
||||
DATA_LINES : positive := 1
|
||||
);
|
||||
@@ -103,7 +106,7 @@ architecture rtl of spi_flash_ctrl is
|
||||
constant DEFAULT_CS_TIMEOUT : integer := 32;
|
||||
|
||||
-- Automatic mode state
|
||||
type auto_state_t is (AUTO_IDLE, AUTO_CS_ON, AUTO_CMD,
|
||||
type auto_state_t is (AUTO_BOOT, AUTO_IDLE, AUTO_CS_ON, AUTO_CMD,
|
||||
AUTO_ADR0, AUTO_ADR1, AUTO_ADR2, AUTO_ADR3,
|
||||
AUTO_DUMMY,
|
||||
AUTO_DAT0, AUTO_DAT1, AUTO_DAT2, AUTO_DAT3,
|
||||
@@ -125,7 +128,7 @@ architecture rtl of spi_flash_ctrl is
|
||||
-- Automatic mode latches
|
||||
signal auto_data : std_ulogic_vector(wb_out.dat'left downto 0) := (others => '0');
|
||||
signal auto_cnt : integer range 0 to 63 := 0;
|
||||
signal auto_state : auto_state_t := AUTO_IDLE;
|
||||
signal auto_state : auto_state_t := AUTO_BOOT;
|
||||
signal auto_last_addr : std_ulogic_vector(31 downto 0);
|
||||
|
||||
begin
|
||||
@@ -176,7 +179,7 @@ begin
|
||||
-- in practice.
|
||||
--
|
||||
if cmd_valid = '1' and cmd_ready = '1' then
|
||||
pending_read <= '1';
|
||||
pending_read <= not wb_req.we;
|
||||
elsif bus_idle = '1' then
|
||||
pending_read <= '0';
|
||||
end if;
|
||||
@@ -396,21 +399,29 @@ begin
|
||||
if rst = '1' or ctrl_reset = '1' then
|
||||
auto_cs <= '0';
|
||||
auto_cnt_next <= 0;
|
||||
auto_next <= AUTO_IDLE;
|
||||
auto_next <= AUTO_BOOT;
|
||||
else
|
||||
-- Run counter
|
||||
if auto_cnt /= 0 then
|
||||
auto_cnt_next <= auto_cnt - 1;
|
||||
end if;
|
||||
|
||||
-- Automatic CS is set whenever state isn't IDLE or RECOVERY
|
||||
if auto_state /= AUTO_IDLE and
|
||||
auto_state /= AUTO_RECOVERY then
|
||||
-- Automatic CS is set whenever state isn't IDLE or RECOVERY or BOOT
|
||||
if auto_state /= AUTO_IDLE and
|
||||
auto_state /= AUTO_RECOVERY and
|
||||
auto_state /= AUTO_BOOT then
|
||||
auto_cs <= '1';
|
||||
end if;
|
||||
|
||||
-- State machine
|
||||
case auto_state is
|
||||
when AUTO_BOOT =>
|
||||
if BOOT_CLOCKS then
|
||||
auto_cmd_valid <= '1';
|
||||
if cmd_ready = '1' then
|
||||
auto_next <= AUTO_IDLE;
|
||||
end if;
|
||||
end if;
|
||||
when AUTO_IDLE =>
|
||||
-- Access to the memory map only when manual CS isn't set
|
||||
if wb_map_valid = '1' and ctrl_cs = '0' then
|
||||
@@ -599,3 +610,4 @@ begin
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user