123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /*
- * Copyright (c) 2006-2019, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-07-29 zdzn first version
- */
- #include "drv_spi.h"
- #ifdef RT_USING_SPI
- #define RPI_CORE_CLK_HZ 250000000
- #define BSP_SPI_MAX_HZ (30* 1000 *1000)
- #define SPITIMEOUT 0x0FFF
- void spi_gpio_write(rt_uint8_t pin, rt_uint8_t val)
- {
- if (val)
- BCM283X_GPIO_GPSET(pin / 32) = 1 << (pin % 32);
- else
- BCM283X_GPIO_GPCLR(pin / 32) = 0 << (pin % 32);
- }
- struct raspi_spi_hw_config
- {
- rt_uint8_t spi_num;
- raspi_gpio_pin sclk_pin;
- raspi_pin_select sclk_mode;
- raspi_gpio_pin mosi_pin;
- raspi_pin_select mosi_mode;
- raspi_gpio_pin miso_pin;
- raspi_pin_select miso_mode;
- #if defined (BSP_USING_SPI0_DEVICE0) || defined (BSP_USING_SPI1_DEVICE0)
- raspi_gpio_pin ce0_pin;
- raspi_pin_select ce0_mode;
- #endif
- #if defined (BSP_USING_SPI0_DEVICE1) || defined (BSP_USING_SPI1_DEVICE1)
- raspi_gpio_pin ce1_pin;
- raspi_pin_select ce1_mode;
- #endif
- #if defined (BSP_USING_SPI1_DEVICE2)
- raspi_gpio_pin ce2_pin;
- raspi_pin_select ce2_mode;
- #endif
- };
- struct raspi_spi_device
- {
- char *device_name;
- struct rt_spi_bus *spi_bus;
- struct rt_spi_device *spi_device;
- raspi_gpio_pin cs_pin;
- };
- static rt_err_t raspi_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
- {
- RT_ASSERT(cfg != RT_NULL);
- RT_ASSERT(device != RT_NULL);
- rt_uint16_t divider;
- // spi clear fifo
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CLEAR;
- if (cfg->mode & RT_SPI_CPOL)
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CPOL;
- if (cfg->mode & RT_SPI_CPHA)
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CPHA;
- if (cfg->mode & RT_SPI_CS_HIGH)
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CSPOL;
- //set clk
- if (cfg->max_hz > BSP_SPI_MAX_HZ)
- cfg->max_hz = BSP_SPI_MAX_HZ;
- divider = (rt_uint16_t) ((rt_uint32_t) RPI_CORE_CLK_HZ / cfg->max_hz);
- divider &= 0xFFFE;
- BCM283X_SPI0_CLK(BCM283X_SPI0_BASE) = divider;
- return RT_EOK;
- }
- rt_uint8_t correct_order(rt_uint8_t b, rt_uint8_t flag)
- {
- if (flag)
- return raspi_byte_reverse_table[b];
- else
- return b;
- }
- static rt_err_t spi_transfernb(rt_uint8_t* tbuf, rt_uint8_t* rbuf, rt_uint32_t len, rt_uint8_t flag)
- {
- rt_uint32_t TXCnt=0;
- rt_uint32_t RXCnt=0;
- /* Clear TX and RX fifos */
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (BCM283X_SPI0_CS_CLEAR & BCM283X_SPI0_CS_CLEAR);
- /* Set TA = 1 */
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (BCM283X_SPI0_CS_TA & BCM283X_SPI0_CS_TA);
- /* Use the FIFO's to reduce the interbyte times */
- while ((TXCnt < len) || (RXCnt < len))
- {
- /* TX fifo not full, so add some more bytes */
- while (((BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_TXD)) && (TXCnt < len))
- {
- BCM283X_SPI0_FIFO(BCM283X_SPI0_BASE) = correct_order(tbuf[TXCnt],flag);
- TXCnt++;
- }
- /* Rx fifo not empty, so get the next received bytes */
- while (((BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_RXD)) && (RXCnt < len))
- {
- rbuf[RXCnt] = correct_order(BCM283X_SPI0_FIFO(BCM283X_SPI0_BASE),flag);
- RXCnt++;
- }
- }
- /* Wait for DONE to be set */
- while (!(BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_DONE));
- /* Set TA = 0, and also set the barrier */
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (0 & BCM283X_SPI0_CS_TA);
- return RT_EOK;
- }
- static rt_uint32_t raspi_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
- {
- RT_ASSERT(device != RT_NULL);
- RT_ASSERT(device->bus != RT_NULL);
- RT_ASSERT(device->parent.user_data != RT_NULL);
- RT_ASSERT(message->send_buf != RT_NULL || message->recv_buf != RT_NULL);
- rt_err_t res;
- rt_uint8_t flag;
- struct rt_spi_configuration config = device->config;
- raspi_gpio_pin cs_pin = (raspi_gpio_pin)device->parent.user_data;
- if (config.mode & RT_SPI_MSB)
- flag = 0;
- else
- flag = 1;
- if (message->cs_take)
- (config.mode & RT_SPI_CS_HIGH)?
- spi_gpio_write(cs_pin, 1):
- spi_gpio_write(cs_pin, 0);
- /* deal data */
- res = spi_transfernb((rt_uint8_t *)message->send_buf, (rt_uint8_t *)message->recv_buf,
- (rt_int32_t)message->length, flag);
- if (message->cs_release)
- (config.mode & RT_SPI_CS_HIGH)?
- spi_gpio_write(cs_pin, 0):
- spi_gpio_write(cs_pin, 1);
- if (res != RT_EOK)
- return RT_ERROR;
- return message->length;
- }
- rt_err_t raspi_spi_bus_attach_device(const char *bus_name, struct raspi_spi_device *device)
- {
- rt_err_t ret;
- RT_ASSERT(device != RT_NULL);
- ret = rt_spi_bus_attach_device(device->spi_device, device->device_name, bus_name, (void *)(device->cs_pin));
- return ret;
- }
- rt_err_t raspi_spi_hw_init(struct raspi_spi_hw_config *hwcfg)
- {
- GPIO_FSEL(hwcfg->sclk_pin, hwcfg->sclk_mode);
- GPIO_FSEL(hwcfg->miso_pin, hwcfg->miso_mode);
- GPIO_FSEL(hwcfg->mosi_pin, hwcfg->mosi_mode);
- #if defined (BSP_USING_SPI0_DEVICE0)
- GPIO_FSEL(hwcfg->ce0_pin, hwcfg->ce0_mode);
- #endif
- #if defined (BSP_USING_SPI0_DEVICE1)
- GPIO_FSEL(hwcfg->ce1_pin, hwcfg->ce1_mode);
- #endif
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) = 0;
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) = BCM283X_SPI0_CS_CLEAR;
- //enable chip select
- #if defined (BSP_USING_SPI0_DEVICE0)
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= 0;
- #endif
- #if defined (BSP_USING_SPI0_DEVICE1)
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= 0x2;
- #endif
- #if defined (BSP_USING_SPI0_DEVICE0) && defined (BSP_USING_SPI0_DEVICE1)
- BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CS;
- #endif
- return RT_EOK;
- }
- static struct rt_spi_ops raspi_spi_ops =
- {
- .configure = raspi_spi_configure,
- .xfer = raspi_spi_xfer
- };
- #if defined (BSP_USING_SPI0_BUS)
- #define SPI0_BUS_NAME "spi0"
- #define SPI0_DEVICE0_NAME "spi0.0"
- #define SPI0_DEVICE1_NAME "spi0.1"
- struct rt_spi_bus spi0_bus;
- #if defined (BSP_USING_SPI0_DEVICE0)
- struct rt_spi_device spi0_device0;
- #endif
- #if defined (BSP_USING_SPI0_DEVICE1)
- static struct rt_spi_device spi0_device1;
- #endif
- struct raspi_spi_hw_config raspi_spi0_hw =
- {
- .spi_num = 0,
- .sclk_pin = RPI_GPIO_P1_23,
- .sclk_mode = BCM283X_GPIO_FSEL_ALT0,
- .mosi_pin = RPI_GPIO_P1_19,
- .mosi_mode = BCM283X_GPIO_FSEL_ALT0,
- .miso_pin = RPI_GPIO_P1_21,
- .miso_mode = BCM283X_GPIO_FSEL_ALT0,
- #if defined (BSP_USING_SPI0_DEVICE0)
- .ce0_pin = RPI_GPIO_P1_24,
- .ce0_mode = BCM283X_GPIO_FSEL_ALT0,
- #endif
- #if defined (BSP_USING_SPI0_DEVICE1)
- .ce1_pin = RPI_GPIO_P1_26,
- .ce1_mode = BCM283X_GPIO_FSEL_ALT0,
- #endif
- };
- #endif
- int rt_hw_spi_init(void)
- {
- #if defined (BSP_USING_SPI0_BUS)
- raspi_spi_hw_init(&raspi_spi0_hw);
- rt_spi_bus_register(&spi0_bus, SPI0_BUS_NAME, &raspi_spi_ops);
- #if defined (BSP_USING_SPI0_DEVICE0)
- struct raspi_spi_device raspi_spi0_device0 =
- {
- .device_name = SPI0_DEVICE0_NAME,
- .spi_bus = &spi0_bus,
- .spi_device = &spi0_device0,
- .cs_pin = raspi_spi0_hw.ce0_pin,
- };
- raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device0);
- #endif
- #if defined (BSP_USING_SPI0_DEVICE1)
- struct raspi_spi_device raspi_spi0_device1 =
- {
- .device_name = SPI0_DEVICE1_NAME,
- .spi_bus = &spi0_bus,
- .spi_device = &spi0_device1,
- .cs_pin = raspi_spi0_hw.ce1_pin,
- };
- raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device1);
- #endif
- #endif
- return RT_EOK;
- }
- INIT_DEVICE_EXPORT(rt_hw_spi_init);
- #endif
|