Skip to content

Commit 9f4b4e9

Browse files
drivers: mspi: Adding SPI transceive with polling.
Implemented SPI transmit and receive functionality in polling manner for the QSPI module of SAMD5x/SAME5x. Signed-off-by: Shikhar Tandon <Shikhar.Tandon@microchip.com>
1 parent 3e3e0d0 commit 9f4b4e9

File tree

2 files changed

+193
-3
lines changed

2 files changed

+193
-3
lines changed

drivers/mspi/mspi_mchp_qspi_g1.c

Lines changed: 192 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,13 @@ static int mspi_mchp_dev_config(const struct device *controller,
847847
set_serial_memory_mode(q);
848848
LOG_INF("Serial memory mode enabled\n");
849849
}
850+
/*if communicating with SPI device(not serial memory)
851+
1 - set to SPI mode
852+
2 - set CSMODE to 1 to foolproof any CS de-asserts when next byte transfer begins*/
853+
else
854+
{
855+
q->QSPI_CTRLB = (q->QSPI_CTRLB & ~((QSPI_CTRLB_CSMODE_Msk) | (QSPI_CTRLB_MODE_Msk))) | (QSPI_CTRLB_MODE(0) | QSPI_CTRLB_CSMODE(1));
856+
}
850857
/*CTRLB register*/
851858
//DLYCS and DLYBCT to be set by mspi_timing_config() API -current default 0
852859
//DATALEN default to 0 -- 8 bits(1 byte)
@@ -1736,16 +1743,195 @@ static int mspi_pio_serial_transceive(const struct device *controller,
17361743
}
17371744

17381745

1746+
static bool spi_transceive(const struct device *controller,
1747+
const struct mspi_xfer_packet *packet,
1748+
const struct mspi_xfer *xfer)
1749+
{
1750+
bool isRequestAccepted = false;
1751+
bool cmdwriteonly = false;
1752+
1753+
const mspi_sam_qspi_cfg_t *cfg = controller->config;
1754+
mspi_sam_qspi_data_t *data = controller->data;
1755+
qspi_registers_t *q = cfg->reg_cfg.regs;
1756+
1757+
mspi_context_t *ctx = &data->ctx;
1758+
uint32_t dummyData;
1759+
uint16_t dummyLen = packet->num_bytes;
1760+
uint16_t pre_dummy_bytes = 0;
1761+
uint16_t pre_dummy_bytes_tmp = 0;
1762+
1763+
uint32_t rx_drop = 0;
1764+
uint8_t addressLen = xfer->addr_length;
1765+
1766+
uint32_t receivedData;
1767+
uint32_t packets = packet->num_bytes;
1768+
uint32_t blocks = 0;
1769+
1770+
uint32_t index = 0;
1771+
1772+
if(packet->dir == MSPI_RX)
1773+
{
1774+
pre_dummy_bytes = (xfer->rx_dummy + 7) / 8;
1775+
}
1776+
else
1777+
{
1778+
pre_dummy_bytes = (xfer->tx_dummy + 7) / 8;
1779+
}
1780+
pre_dummy_bytes_tmp = pre_dummy_bytes;
1781+
rx_drop = xfer->cmd_length + xfer->addr_length + pre_dummy_bytes;
1782+
1783+
1784+
//take a semaphore(TBD:do the dev_id check later)
1785+
if ((k_sem_count_get(&ctx->lock) != 0) && (k_sem_take(&ctx->lock, K_FOREVER) == 0))
1786+
{
1787+
isRequestAccepted = true;
1788+
1789+
/* Flush out any unread data in SPI read buffer */
1790+
dummyData = (q->QSPI_RXDATA & QSPI_RXDATA_DATA_Msk) >> QSPI_RXDATA_DATA_Pos;
1791+
1792+
if(xfer->cmd_length != 0)
1793+
{
1794+
/*command write only , just break out of loop*/
1795+
if((packet->dir == MSPI_TX) && (xfer->addr_length == 0) && (packet->num_bytes == 0) && (packet->data_buf == NULL))
1796+
{
1797+
LOG_INF("Command write only");
1798+
cmdwriteonly = true;
1799+
}
1800+
LOG_INF("packet cmd = 0x%X",packet->cmd);
1801+
//initiate the transfer
1802+
q->QSPI_TXDATA = (uint8_t)packet->cmd;
1803+
}
1804+
1805+
//TBD:when command is more than 1 byte
1806+
while(blocks < (xfer->cmd_length + xfer->addr_length + packet->num_bytes + pre_dummy_bytes))
1807+
{
1808+
blocks++;
1809+
//wait for received data to come in RXDATA from shifter
1810+
while((q->QSPI_INTFLAG & QSPI_INTFLAG_RXC_Msk) != QSPI_INTFLAG_RXC_Msk)
1811+
{
1812+
}
1813+
1814+
{
1815+
//reading RXDATA clears RXC flag
1816+
receivedData = ((q->QSPI_RXDATA & QSPI_RXDATA_DATA_Msk) >> QSPI_RXDATA_DATA_Pos);
1817+
/*drop cmd,address,pre-dummy cycles*/
1818+
if(rx_drop != 0)
1819+
{
1820+
rx_drop--;
1821+
LOG_INF("rx_drop = %u",rx_drop);
1822+
if(cmdwriteonly == true)
1823+
{
1824+
QSPI_EndTransfer(q);
1825+
goto out;
1826+
}
1827+
}
1828+
else
1829+
{
1830+
if(packet->dir == MSPI_RX)
1831+
{
1832+
packet->data_buf[index++] = receivedData;
1833+
LOG_INF("receivedData = %u",receivedData);
1834+
if((blocks == (xfer->cmd_length + xfer->addr_length + packet->num_bytes + pre_dummy_bytes)) || (dummyLen == 0))
1835+
{
1836+
QSPI_EndTransfer(q);
1837+
LOG_INF("break out");
1838+
break;
1839+
}
1840+
}
1841+
/*for MSPI_TX if addresses and data has been sent , end and exit*/
1842+
else if((addressLen == 0) && (packets == 0))
1843+
{
1844+
/*dont go in DRE check if adress byte and data bytes are 0*/
1845+
QSPI_EndTransfer(q);
1846+
LOG_INF("All address and data packets sent.");
1847+
break;
1848+
}
1849+
}
1850+
}
1851+
1852+
1853+
//wait for data to move from TXDATA to shifter
1854+
while((q->QSPI_INTFLAG & QSPI_INTFLAG_DRE_Msk) != QSPI_INTFLAG_DRE_Msk)
1855+
{
1856+
}
1857+
1858+
{
1859+
/*set LASTXFER before sending out last byte in TXDATA(compare blocks or dummylen(if address bytes have been sent and last dummy byte remains))*/
1860+
if((blocks == (xfer->cmd_length + xfer->addr_length + packet->num_bytes + pre_dummy_bytes)) && (packet->dir == MSPI_TX))
1861+
{
1862+
LOG_INF("here!!!!");
1863+
QSPI_EndTransfer(q);
1864+
goto out;
1865+
}
1866+
1867+
if(addressLen > 0)
1868+
{
1869+
q->QSPI_TXDATA = (uint8_t)(((packet->address & (0x000000FF << (8*(addressLen - 1))))) >> (8*(addressLen - 1)));
1870+
addressLen--;
1871+
}
1872+
/*for dummy cycles if needed before transmitting bogus 0xFF to read in or clock in data*/
1873+
else if(pre_dummy_bytes_tmp > 0)
1874+
{
1875+
q->QSPI_TXDATA = (uint8_t)0xFF;
1876+
pre_dummy_bytes_tmp--;
1877+
}
1878+
else if(dummyLen > 0 && packet->dir == MSPI_RX)
1879+
{
1880+
if(dummyLen == 1)
1881+
{
1882+
//QSPI_EndTransfer(q);
1883+
LOG_INF("last dummy");
1884+
}
1885+
q->QSPI_TXDATA = (uint8_t)0xFF;
1886+
dummyLen--;
1887+
}
1888+
else
1889+
{
1890+
q->QSPI_TXDATA = packet->data_buf[index++];
1891+
packets--;
1892+
LOG_INF("packets = %u,addressLen = %u,rx_drop = %u,blocks = %u",packets,addressLen,rx_drop,blocks);
1893+
}
1894+
1895+
}
1896+
1897+
}
1898+
}
1899+
else
1900+
{
1901+
LOG_INF("semaphore not init");
1902+
return false;
1903+
}
1904+
1905+
out:
1906+
//semaphore be released
1907+
k_sem_give(&ctx->lock);
1908+
LOG_INF("Write Read Completed!");
1909+
//check for txdummy in writeread if it matches num_bytes - (opcode+address)
1910+
return isRequestAccepted;
1911+
}
1912+
17391913
static int mspi_pio_spi_transceive(const struct device *controller,
17401914
const struct mspi_xfer *xfer)
17411915
{
17421916

17431917
const struct mspi_xfer_packet *packet = NULL;
1918+
const mspi_sam_qspi_cfg_t *cfg = controller->config;
1919+
qspi_registers_t *q = cfg->reg_cfg.regs;
17441920

17451921
uint32_t num_packets = xfer->num_packet;
1922+
LOG_INF("num of packets = %u",num_packets);
17461923
uint32_t packets_done = 0;
17471924
int ret = 0;
17481925

1926+
1927+
while(packets_done < num_packets)
1928+
{
1929+
packet = &xfer->packets[packets_done];
1930+
spi_transceive(controller,packet,xfer);
1931+
packets_done++;
1932+
}
1933+
1934+
17491935
out:
17501936
return ret;
17511937

@@ -1801,7 +1987,6 @@ static int mspi_mchp_transceive(const struct device *controller,
18011987
if(((q->QSPI_STATUS & QSPI_STATUS_CSSTATUS_Msk) == 0) || ((q->QSPI_STATUS & QSPI_STATUS_ENABLE_Msk) == 0))
18021988
{
18031989
LOG_ERR("QSPI module not enabled or CS line not de-asserted");
1804-
//return -EIO;
18051990
ret = -EIO;
18061991
goto out;
18071992
}
@@ -1817,7 +2002,12 @@ static int mspi_mchp_transceive(const struct device *controller,
18172002
if(find_serial_mode_of_child(cfg->child_desc,dev_id->dev_idx,cfg->num_children) == false)
18182003
{
18192004
/*SPI mode implementation*/
1820-
q->QSPI_CTRLB |= QSPI_CTRLB_MODE(0);
2005+
2006+
/*re-doing mode 0(SPI mode) and phase=0 polarity=0 for now*/
2007+
// q->QSPI_CTRLB |= QSPI_CTRLB_MODE(0);
2008+
// q->QSPI_BAUD |= (q->QSPI_BAUD & ~(QSPI_BAUD_CPOL_Msk | QSPI_BAUD_CPHA_Msk)) |
2009+
// (QSPI_BAUD_CPOL(0) | QSPI_BAUD_CPHA(0));
2010+
18212011
LOG_INF("Implementing in SPI mode");
18222012
mspi_pio_spi_transceive(controller,xfer);
18232013
}

drivers/mspi/mspi_mchp_qspi_g1.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ static inline void set_address_len(qspi_registers_t *q, uint32_t addr_len)
219219
*/
220220
static inline void set_serial_memory_mode(qspi_registers_t *q)
221221
{
222-
q->QSPI_CTRLB |= QSPI_CTRLB_MODE(1);
222+
q->QSPI_CTRLB = (q->QSPI_CTRLB & ~((QSPI_CTRLB_CSMODE_Msk) | (QSPI_CTRLB_MODE_Msk))) | (QSPI_CTRLB_MODE(1) | QSPI_CTRLB_CSMODE(0));
223223
}
224224

225225
/**

0 commit comments

Comments
 (0)