123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-03-28 qiujingbao first version
- */
- #include "drv_spi.h"
- #ifdef RT_USING_SPI
- #define DBG_TAG "drv.spi"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- static struct cv1800_spi cv1800_spi_obj[] =
- {
- #ifdef BSP_USING_SPI
- {
- .spi_id = SPI2,
- .device_name = "spi2",
- .fifo_len = SPI_TXFTLR,
- },
- #endif
- };
- static struct spi_regs *get_spi_base(uint8_t spi_id)
- {
- struct spi_regs *spi_base = NULL;
- switch (spi_id)
- {
- case SPI0:
- spi_base = (struct spi_regs *)SPI0_BASE;
- break;
- case SPI1:
- spi_base = (struct spi_regs *)SPI1_BASE;
- break;
- case SPI2:
- spi_base = (struct spi_regs *)SPI2_BASE;
- break;
- case SPI3:
- spi_base = (struct spi_regs *)SPI3_BASE;
- break;
- }
- return spi_base;
- }
- static rt_err_t drv_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
- {
- rt_err_t ret = RT_EOK;
- struct cv1800_spi *spi_dev = RT_NULL;
- uint32_t mode;
- spi_dev = (struct cv1800_spi *)(device->bus->parent.user_data);
- spi_dev->data_width = configuration->data_width;
- /* disable spi */
- spi_enable(spi_dev->reg, 0);
- /* clear irq */
- spi_clear_irq(spi_dev->reg, SPI_IRQ_MSAK);
- /* set clk */
- ret = spi_set_frequency(spi_dev->reg, configuration->max_hz);
- if (ret)
- return ret;
- /* set mode */
- ret = gen_spi_mode(configuration, &mode);
- if (ret)
- return ret;
- spi_set_mode(spi_dev->reg, mode);
- /* set cs */
- spi_enable_cs(spi_dev->reg, 0x1);
- spi_enable(spi_dev->reg, 0x1);
- mode = mmio_read_32((uintptr_t)&spi_dev->reg->spi_ctrl0);
- LOG_D("mode: %x", mode);
- mode = mmio_read_32((uintptr_t)&spi_dev->reg->spi_baudr);
- LOG_D("spi_baudr: %x", mode);
- return ret;
- }
- int hw_spi_recv(struct cv1800_spi *dev) {
- uint32_t rever;
- uint32_t tem;
- int ret;
- rever = mmio_read_32((uintptr_t)&dev->reg->spi_rxflr);
- ret = (int)rever;
- while (rever)
- {
- tem = mmio_read_32((uintptr_t)&dev->reg->spi_dr);
- if (dev->recv_buf < dev->recv_end)
- {
- if (dev->data_width == 8)
- *(uint8_t *)(dev->recv_buf) = tem;
- else
- *(uint16_t *)(dev->recv_buf) = tem;
- }
- else
- {
- return 0;
- }
- rever--;
- dev->recv_buf += dev->data_width >> 3;
- }
- return ret;
- }
- int hw_spi_send(struct cv1800_spi *dev) {
- uint32_t txflr;
- uint32_t max;
- uint16_t value;
- txflr = mmio_read_32((uintptr_t)&dev->reg->spi_txflr);
- max = dev->fifo_len - txflr;
- while (max)
- {
- if (dev->send_end - dev->send_buf)
- {
- if (dev->data_width == 8)
- value = *(uint8_t *)(dev->send_buf);
- else
- value = *(uint16_t *)(dev->send_buf);
- }
- else
- {
- return 0;
- }
- mmio_write_32((uintptr_t)&dev->reg->spi_dr, value);
- dev->send_buf += dev->data_width >> 3;
- max--;
- }
- return 0;
- }
- static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message) {
- int ret = 0;
- struct cv1800_spi *spi_dev;
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(device->bus != RT_NULL);
- RT_ASSERT(message != RT_NULL);
- spi_dev = (struct cv1800_spi *)(device->bus->parent.user_data);
- if (message->send_buf != RT_NULL)
- {
- spi_dev->send_buf = message->send_buf;
- spi_dev->send_end = (void *)((uint8_t *)spi_dev->send_buf + message->length);
- }
- if (message->recv_buf != RT_NULL)
- {
- spi_dev->recv_buf = message->recv_buf;
- spi_dev->recv_end = (void *)((uint8_t *)spi_dev->recv_buf + message->length);
- }
- /* if user use their cs */
- if (message->cs_take && device->cs_pin != PIN_NONE)
- rt_pin_write(device->cs_pin, PIN_LOW);
- if (message->send_buf)
- {
- while (spi_dev->send_buf != spi_dev->send_end)
- {
- hw_spi_send(spi_dev);
- }
- /* wait for complete */
- while (mmio_read_32((uintptr_t)&spi_dev->reg->spi_txflr)) {}
- ret = message->length;
- }
- if (message->recv_buf)
- {
- while (spi_dev->recv_buf != spi_dev->recv_end)
- {
- hw_spi_recv(spi_dev);
- }
- ret = message->length;
- }
- if (message->cs_release && device->cs_pin != PIN_NONE)
- rt_pin_write(device->cs_pin, PIN_HIGH);
- return ret;
- }
- const static struct rt_spi_ops drv_spi_ops =
- {
- drv_spi_configure,
- spixfer,
- };
- int rt_hw_spi_init(void)
- {
- rt_err_t ret = RT_EOK;
- struct spi_regs *reg = NULL;
- for (rt_size_t i = 0; i < sizeof(cv1800_spi_obj) / sizeof(struct cv1800_spi); i++) {
- /* set reg base addr */
- reg = get_spi_base(cv1800_spi_obj[i].spi_id);
- if (!reg)
- return -RT_ERROR;
- cv1800_spi_obj[i].reg = reg;
- cv1800_spi_obj[i].spi_bus.parent.user_data = &cv1800_spi_obj[i];
- /* register spix bus */
- ret = rt_spi_bus_register(&cv1800_spi_obj[i].spi_bus, cv1800_spi_obj[i].device_name, &drv_spi_ops);
- }
- return ret;
- }
- INIT_BOARD_EXPORT(rt_hw_spi_init);
- #endif /* RT_USING_SPI */
|