Commit Graph

39 Commits

Author SHA1 Message Date
Florent Kermarrec d165418719 CHANGES.md: Update. 2023-09-12 09:35:53 +02:00
Florent Kermarrec fbae6e8e37 CHANGES.md: Update. 2023-09-07 14:27:12 +02:00
Florent Kermarrec 57faa9102f CHANGES: Update. 2023-09-01 12:40:03 +02:00
Florent Kermarrec 9854c9f322 CHANGES: Update. 2023-08-30 18:11:11 +02:00
Florent Kermarrec 9528f89d45 CHANGES: Update. 2023-08-29 17:15:45 +02:00
Florent Kermarrec 70e52b76fa CHANGES: Update. 2023-08-28 16:04:43 +02:00
Florent Kermarrec 688dae0112 cores/spi: Add new SPIMMAP core allowing doing SPI accesses directly from MMAP.
Implements a new SPIMMAP module, allowing accessing multiple SPI peripherals directly
from MMAP. It allows configurable SPI transactions: mode, bit order, and data width.

Developed and funded through a collaboration with MoTeC.

Example of integration:

# SPI MMAP ---------------------------------------------------------------------------------
spi_pads = Record([("clk", 1), ("cs_n", 8), ("mosi", 1), ("miso", 1)])
spi_mmap_tx_region = SoCRegion(origin=0x8000_0000, size=4096, cached=False)
spi_mmap_rx_region = SoCRegion(origin=0x8000_1000, size=4096, cached=False)
self.spi_mmap = SPIMMAP(
    pads          = spi_pads,
    data_width    = 32,
    sys_clk_freq  = sys_clk_freq,
    tx_origin     = spi_mmap_tx_region.origin,
    rx_origin     = spi_mmap_rx_region.origin,
    tx_fifo_depth = 32,
    rx_fifo_depth = 32,
)

self.bus.add_slave(name="spi_tx",
    slave  = self.spi_mmap.tx_mmap.bus,
    region = spi_mmap_tx_region,
)
self.bus.add_slave(name="spi_rx",
    slave  = self.spi_mmap.rx_mmap.bus,
    region = spi_mmap_rx_region,
)
self.irq.add("spi_mmap", use_loc_if_exists=True)


Example of use from CPU C firmware:

/* SPI TX Offsets */
#define SPI_TX_CTRL_ENABLE    (1 << 0)
#define SPI_TX_CTRL_THRESHOLD (1 << 16)

#define SPI_TX_STAT_ONGOING   (1 << 0)
#define SPI_TX_STAT_EMPTY     (1 << 1)
#define SPI_TX_STAT_FULL      (1 << 2)
#define SPI_TX_STAT_LEVEL     (1 << 16)

/* SPI RX Offsets */
#define SPI_RX_CTRL_ENABLE    (1 << 0)
#define SPI_RX_CTRL_THRESHOLD (1 << 16)

#define SPI_RX_STAT_ONGOING   (1 << 0)
#define SPI_RX_STAT_EMPTY     (1 << 1)
#define SPI_RX_STAT_FULL      (1 << 2)
#define SPI_RX_STAT_LEVEL     (1 << 16)

/* SPI TX/RX Engine */
#define SPI_TX_RX_ENGINE_ENABLE (1 << 0)

/* SPI SLOT Offsets */
#define SPI_SLOT_ENABLE   (1 <<  0)
#define SPI_SLOT_MODE     (1 <<  1)
#define SPI_SLOT_LENGTH   (1 <<  3)
#define SPI_SLOT_BITORDER (1 <<  5)
#define SPI_SLOT_LOOPBACK (1 <<  6)
#define SPI_SLOT_DIVIDER  (1 << 16)

/* SPI SLOT Values */
#define SPI_SLOT_MODE_0 0b00
#define SPI_SLOT_MODE_3 0b11

#define SPI_SLOT_LENGTH_32B 0b00
#define SPI_SLOT_LENGTH_16B 0b01
#define SPI_SLOT_LENGTH_8B  0b10

#define SPI_SLOT_BITORDER_MSB_FIRST 0b0
#define SPI_SLOT_BITORDER_LSB_FIRST 0b1

#define SPI_SLOT_EV_TX (1 << 0)
#define SPI_SLOT_EV_RX (1 << 1)


/* Test SPI with various length (BE) */
void test_spi_length_8_16_32(void) {
	volatile unsigned char  *spi_tx_8  = (unsigned char  *)SPI_TX_BASE;
	volatile unsigned short *spi_tx_16 = (unsigned short *)SPI_TX_BASE;
	volatile unsigned int   *spi_tx_32 = (unsigned int   *)SPI_TX_BASE;

	volatile unsigned char  *spi_rx_8  = (unsigned char  *)SPI_RX_BASE;
	volatile unsigned short *spi_rx_16 = (unsigned short *)SPI_RX_BASE;
	volatile unsigned int   *spi_rx_32 = (unsigned int   *)SPI_RX_BASE;

	int errors = 0;

	printf("Test SPI with various length (BE): 8, 16 and 32-bit...\n");

	/* Configure Slots */
	spi_mmap_ctrl_slot_control0_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								  4 * SPI_SLOT_DIVIDER
	);
	spi_mmap_ctrl_slot_control1_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								  4 * SPI_SLOT_DIVIDER
	);
	spi_mmap_ctrl_slot_control2_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								  4 * SPI_SLOT_DIVIDER
	);
	spi_mmap_ctrl_slot_control3_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								  4 * SPI_SLOT_DIVIDER
	);

	/* Enable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(1 * SPI_TX_RX_ENGINE_ENABLE);

	/* TX 8-bit transfers */
	spi_tx_8[0]  = 0x5a;
	spi_tx_8[4]  = 0x01;
	spi_tx_8[8]  = 0x5a;
	spi_tx_8[12] = 0x01;

	/* TX 16-bit transfers */
	spi_tx_16[0] = 0x5aa5;
	spi_tx_16[2] = 0x0102;
	spi_tx_16[4] = 0x5aa5;
	spi_tx_16[6] = 0x0102;

	/* TX 32-bit transfers */
	spi_tx_32[0] = 0x5aa55aa5;
	spi_tx_32[1] = 0x01020304;
	spi_tx_32[2] = 0x5aa55aa5;
	spi_tx_32[3] = 0x01020304;

	/* Small delay */
	busy_wait(1);

	/* Read RX 8-bit transfers */
	if (spi_rx_8[ 0] != 0x5a)
		errors++;
	if (spi_rx_8[ 4] != 0x01)
		errors++;
	if (spi_rx_8[ 8] != 0x5a)
		errors++;
	if (spi_rx_8[12] != 0x01)
		errors++;

	/* Read RX 16-bit transfers */
	if (spi_rx_16[0] != 0x5aa5)
		errors++;
	if (spi_rx_16[2] != 0x0102)
		errors++;
	if (spi_rx_16[4] != 0x5aa5)
		errors++;
	if (spi_rx_16[6] != 0x0102)
		errors++;

	/* Read RX 32-bit tranfers */
	if (spi_rx_32[0] != 0x5aa55aa5)
		errors++;
	if (spi_rx_32[1] != 0x01020304)
		errors++;
	if (spi_rx_32[2] != 0x5aa55aa5)
		errors++;
	if (spi_rx_32[3] != 0x01020304)
		errors++;

	/* Disable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(0 * SPI_TX_RX_ENGINE_ENABLE);

	/* Result */
	printf("errors: %d\n", errors);
}

/* Test SPI with various clk divider */
void test_spi_clk_divider(void) {
	volatile unsigned int *spi_tx_32 = (unsigned int *)SPI_TX_BASE;
	volatile unsigned int *spi_rx_32 = (unsigned int *)SPI_RX_BASE;

	int errors = 0;

	printf("Test SPI with various clk divider: 4, 8, 16 and 32...\n");

	/* Configure Slots */
	spi_mmap_ctrl_slot_control0_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								  4 * SPI_SLOT_DIVIDER
	);
	spi_mmap_ctrl_slot_control1_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								  8 * SPI_SLOT_DIVIDER
	);
	spi_mmap_ctrl_slot_control2_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								 16 * SPI_SLOT_DIVIDER
	);
	spi_mmap_ctrl_slot_control3_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								 32 * SPI_SLOT_DIVIDER
	);

	/* Enable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(1 * SPI_TX_RX_ENGINE_ENABLE);

	/* TX 32-bit transfers */
	spi_tx_32[0] = 0x01020304;
	spi_tx_32[1] = 0x5aa55aa5;
	spi_tx_32[2] = 0x01020304;
	spi_tx_32[3] = 0x5aa55aa5;

	/* Small delay */
	busy_wait(1);

	/* Read RX 32-bit tranfers */
	if (spi_rx_32[0] != 0x01020304)
		errors++;
	if (spi_rx_32[1] != 0x5aa55aa5)
		errors++;
	if (spi_rx_32[2] != 0x01020304)
		errors++;
	if (spi_rx_32[3] != 0x5aa55aa5)
		errors++;

	/* Disable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(0 * SPI_TX_RX_ENGINE_ENABLE);

	/* Result */
	printf("errors: %d\n", errors);
}

/* Test SPI with various SPI modes */
void test_spi_modes(void) {
	volatile unsigned int *spi_tx_32 = (unsigned int *)SPI_TX_BASE;
	volatile unsigned int *spi_rx_32 = (unsigned int *)SPI_RX_BASE;

	int errors = 0;

	printf("Test SPI with various SPI modes: 0 and 3...\n");

	/* Configure Slots */
	spi_mmap_ctrl_slot_control0_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								  4 * SPI_SLOT_DIVIDER
	);
	spi_mmap_ctrl_slot_control1_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_3 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								  4 * SPI_SLOT_DIVIDER
	);

	/* Enable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(1 * SPI_TX_RX_ENGINE_ENABLE);

	/* TX 32-bit transfers */
	spi_tx_32[0] = 0x5aa55aa5;
	spi_tx_32[1] = 0x5aa55aa5;

	/* Small delay */
	busy_wait(1);

	/* Read RX 32-bit tranfers */
	if (spi_rx_32[0] != 0x5aa55aa5)
		errors++;
	if (spi_rx_32[1] != 0x5aa55aa5)
		errors++;

	/* Disable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(0 * SPI_TX_RX_ENGINE_ENABLE);

	/* Result */
	printf("errors: %d\n", errors);
}

/* Test SPI with various bitorders */
void test_spi_bitorders(void) {
	volatile unsigned int *spi_tx_32 = (unsigned int *)SPI_TX_BASE;
	volatile unsigned int *spi_rx_32 = (unsigned int *)SPI_RX_BASE;

	int errors = 0;

	printf("Test SPI with various bitorders: MSB and LSB first...\n");

	/* Configure Slots */
	spi_mmap_ctrl_slot_control0_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								  4 * SPI_SLOT_DIVIDER
	);
	spi_mmap_ctrl_slot_control1_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_LSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								  4 * SPI_SLOT_DIVIDER
	);

	/* Enable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(1 * SPI_TX_RX_ENGINE_ENABLE);

	/* TX 32-bit transfers */
	spi_tx_32[0] = 0xff000000;
	spi_tx_32[1] = 0xff000000;

	/* Small delay */
	busy_wait(1);

	/* Read RX 32-bit tranfers */
	if (spi_rx_32[0] != 0xff000000)
		errors++;
	if (spi_rx_32[1] != 0xff000000)
		errors++;

	/* Disable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(0 * SPI_TX_RX_ENGINE_ENABLE);

	/* Result */
	printf("errors: %d\n", errors);
}

/* Test SPI TX/RX levels */
void test_spi_tx_rx_levels(void) {
	volatile unsigned int *spi_tx_32 = (unsigned int *)SPI_TX_BASE;
	volatile unsigned int *spi_rx_32 = (unsigned int *)SPI_RX_BASE;

	int i;
	int errors = 0;
	int pattern;

	printf("Test SPI TX/RX levels...\n");

	/* Configure Slots */
	spi_mmap_ctrl_slot_control0_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								128 * SPI_SLOT_DIVIDER
	);

	/* Enable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(1 * SPI_TX_RX_ENGINE_ENABLE);

	/* TX 32-bit transfers */
	pattern = 0x00000001;
	for (i=0; i<16; i++){
		if ((spi_mmap_ctrl_tx_status_read() >> 16) != i)
			errors++;
		spi_tx_32[0] = pattern;
	}

	/* Small delay */
	busy_wait(1);

	/* Read RX 32-bit tranfers */
	for (i=0; i<16; i++){
		pattern = spi_rx_32[0];
		if ((spi_mmap_ctrl_rx_status_read() >> 16) != (16-1-i))
			errors++;
	}

	if ((spi_mmap_ctrl_tx_status_read() >> 16) != 0)
		errors++;
	if ((spi_mmap_ctrl_rx_status_read() >> 16) != 0)
		errors++;

	/* Disable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(0 * SPI_TX_RX_ENGINE_ENABLE);

	/* Result */
	printf("errors: %d\n", errors);
}

/* Test SPI TX/RX IRQs */
void test_spi_tx_rx_irqs(void) {
	volatile unsigned int *spi_tx_32 = (unsigned int *)SPI_TX_BASE;
	volatile unsigned int *spi_rx_32 = (unsigned int *)SPI_RX_BASE;

	int errors = 0;
	int data __attribute__((unused));

	printf("Test SPI TX/RX IRQs...\n");

	/* Configure Slots */
	spi_mmap_ctrl_slot_control0_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								128 * SPI_SLOT_DIVIDER
	);

	/* Enable TX/RX EventManager */
	spi_mmap_ev_enable_write(0);
	spi_mmap_ev_pending_write(spi_mmap_ev_pending_read());
	spi_mmap_ev_enable_write(SPI_SLOT_EV_TX | SPI_SLOT_EV_RX);

	/* Enable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(1 * SPI_TX_RX_ENGINE_ENABLE);

	/* TX 32-bit transfers */
	spi_tx_32[0] = 0x00000001;

	/* Small delay */
	busy_wait(1);

	/* Verify TX/RX events */
	if (spi_mmap_ev_pending_read() != (SPI_SLOT_EV_TX | SPI_SLOT_EV_RX))
		errors++;

	/* Read RX 32-bit tranfers */
	data = spi_rx_32[0];

	/* Clear events */
	spi_mmap_ev_pending_write(spi_mmap_ev_pending_read());

	/* Verify TX/RX events */
	if (spi_mmap_ev_pending_read() != 0)
		errors++;

	/* Disable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(0 * SPI_TX_RX_ENGINE_ENABLE);

	/* Result */
	printf("errors: %d\n", errors);
}


/* Test SPI Back-to-Back */
void test_spi_back_to_back(void) {
	volatile unsigned int *spi_tx_32 = (unsigned int *)SPI_TX_BASE;
	volatile unsigned int *spi_rx_32 = (unsigned int *)SPI_RX_BASE;

	int errors = 0;

	printf("Test SPI Back-to-Back...\n");

	/* Configure Slots */
	spi_mmap_ctrl_slot_control0_write(
								  1 * SPI_SLOT_ENABLE   |
					SPI_SLOT_MODE_0 * SPI_SLOT_MODE     |
				SPI_SLOT_LENGTH_32B * SPI_SLOT_LENGTH   |
		SPI_SLOT_BITORDER_MSB_FIRST * SPI_SLOT_BITORDER |
								  1 * SPI_SLOT_LOOPBACK |
								  8 * SPI_SLOT_DIVIDER
	);

	/* Enable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(1 * SPI_TX_RX_ENGINE_ENABLE);

	/* TX 32-bit transfers */
	spi_tx_32[0] = 0x00000001;
	spi_tx_32[0] = 0x00000002;

	/* Small delay */
	busy_wait(1);

	/* Read RX 32-bit tranfers */
	if (spi_rx_32[0] != 0x00000001)
		errors++;
	if (spi_rx_32[0] != 0x00000002)
		errors++;

	/* Disable SPI Engine */
	spi_mmap_tx_rx_engine_control_write(0 * SPI_TX_RX_ENGINE_ENABLE);

	/* Result */
	printf("errors: %d\n", errors);
}
2023-08-04 17:44:54 +02:00
Florent Kermarrec 036193d046 CHANGES: Update. 2023-08-04 16:08:00 +02:00
Florent Kermarrec 87e2456274 CHANGES.md: Update. 2023-07-31 18:00:43 +02:00
Florent Kermarrec b2e4b22145 soc/add_pcie: Add with_ptm parameter and update CHANGES. 2023-07-30 15:12:01 +02:00
Florent Kermarrec 74401d6f03 CHANGES: Update. 2023-07-27 13:58:45 +02:00
Florent Kermarrec 66b44ecd60 soc/add_uart: Fix stub behavior (sink/source swap), thanks @zyp. 2023-07-26 12:26:16 +02:00
Florent Kermarrec 0f1fdea893 build/xilinx/vivado: Also generate design checkpoint after synthesis and placement.
This help exploring/constraining complex designs by using Vivado GUI and design checkpoint.
2023-07-21 19:53:28 +02:00
Florent Kermarrec 35cd744adc CHANGES: Update. 2023-07-21 15:16:42 +02:00
Florent Kermarrec 330d61d2bd soc/add_pcie: Remove MSI workaround on Ultrascale(+) now that root cause is understood/fixed (thanks @smunaut). 2023-07-21 14:50:38 +02:00
Florent Kermarrec aae15737cd CHANGES: Update. 2023-07-20 16:30:48 +02:00
Florent Kermarrec f995d74e55 soc/add_uartbone: Rename name parameter to uart_name to allow multiple uartbone (also for consistency with other cores) and other minor cleanups. 2023-07-20 15:42:03 +02:00
Florent Kermarrec f6da67fb38 soc/add_pcie: Add optional data_width parameter. 2023-07-20 10:35:10 +02:00
Florent Kermarrec 6e46710678 gen/fhdl/module: Fix CSR clock domain renaming to cores converted to LiteXModule, thanks @smunaut. 2023-07-14 10:01:32 +02:00
Florent Kermarrec f9e32eb3eb CHANGES: Update. 2023-07-11 16:42:21 +02:00
Florent Kermarrec 26732f626f CHANGES: Update. 2023-07-10 11:24:49 +02:00
Florent Kermarrec c58f46bb79 CHANGES: Update. 2023-07-03 18:09:56 +02:00
Florent Kermarrec a2d44370bd CHANGES: Update. 2023-07-03 10:56:29 +02:00
Florent Kermarrec 648c70de82 cmd_litesata: Fix help printf and update CHANGES. 2023-06-28 23:07:17 +02:00
Florent Kermarrec a9d6a0c6c9 CHANGES: Update. 2023-06-22 17:40:41 +02:00
Florent Kermarrec fbe3fcf76a CHANGES: Update. 2023-06-21 12:46:16 +02:00
Florent Kermarrec d2aae18957 soc/add_pcie/MSI-X: Pass csr_ordering to LitePCIeMSIX. 2023-06-19 19:21:05 +02:00
Florent Kermarrec 94a0a5b0d8 soc/add_pcie: Add msi_width parameter to select MSI width. 2023-06-19 09:54:56 +02:00
Florent Kermarrec a9cbb16785 soc/add_pcie: Add msi_type parameter to select MSI, MSI-Multi-Vector or MSI-X. 2023-06-19 09:45:21 +02:00
Florent Kermarrec 6e5651b320 CHANGES: Update. 2023-06-16 08:33:23 +02:00
Florent Kermarrec 7a4fa58cbf CHANGES: Update. 2023-06-13 18:37:34 +02:00
Florent Kermarrec c6adf703a3 CHANGES.md: Update. 2023-06-06 11:09:44 +02:00
Florent Kermarrec 3ab7ebe536 CHANGES.md: Release 2023.04. 2023-05-08 10:59:17 +02:00
Florent Kermarrec 0f1ad8dcfc CHANGES.md: Update. 2023-05-05 10:08:11 +02:00
Florent Kermarrec ab8d906827 CHANGES.md: Update. 2023-03-30 10:13:56 +02:00
Florent Kermarrec c307bf28eb CHANGES.md: Prepare 2022.12 release. 2023-01-02 08:53:19 +01:00
Florent Kermarrec e186d151fc CHANGES.md: Add recent changes. 2022-12-22 13:18:14 +01:00
Florent Kermarrec 7c94741a69 CHANGES.md: Classify by Fixed/Added/Changed. 2022-12-22 13:18:11 +01:00
Florent Kermarrec 30f5c1d5bf CHANGES: Switch to markdown. 2022-12-06 16:02:11 +01:00