1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-02-22     airm2m       first version
9  */
10 
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include "board.h"
14 
15 #ifdef RT_USING_SPI
16 
17 #if !defined(BSP_USING_HSPI0) && !defined(BSP_USING_SPI0) && !defined(BSP_USING_SPI1) && !defined(BSP_USING_SPI2) && !defined(BSP_USING_SPI0S)
18     #error "Please define at least one BSP_USING_SPIx"
19     /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
20 #endif
21 
22 #include "drv_spi.h"
23 #include "drv_config.h"
24 //#define DRV_DEBUG
25 #define LOG_TAG              "drv.spi"
26 #include <drv_log.h>
27 
28 static struct air_spi spi_config[] =
29 {
30 #ifdef BSP_USING_HSPI0
31     HSPI0_BUS_CONFIG,
32 #endif
33 #ifdef BSP_USING_SPI0
34     SPI0_BUS_CONFIG,
35 #endif
36 #ifdef BSP_USING_SPI1
37     SPI1_BUS_CONFIG,
38 #endif
39 #ifdef BSP_USING_SPI2
40     SPI2_BUS_CONFIG,
41 #endif
42 #ifdef BSP_USING_SPI0S
43     SPI0S_BUS_CONFIG,
44 #endif
45 };
46 
spixfer(struct rt_spi_device * device,struct rt_spi_message * message)47 static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
48 {
49 
50     RT_ASSERT(device != RT_NULL);
51     RT_ASSERT(device->bus != RT_NULL);
52     RT_ASSERT(message != RT_NULL);
53 
54     rt_uint32_t spi_id = device->bus->parent.user_data;
55     rt_uint32_t cs_pin = device->parent.user_data;
56     if (message->cs_take && !(device->config.mode & RT_SPI_NO_CS))
57     {
58         if (device->config.mode & RT_SPI_CS_HIGH)
59             GPIO_Output(cs_pin, 1);
60         else
61             GPIO_Output(cs_pin, 0);
62     }
63 
64 
65     if (message->length)
66     {
67         LOG_D("spi%d 0x%X, 0x%X, %d",
68                 spi_id,
69               (uint32_t)message->send_buf,
70               (uint32_t)message->recv_buf, message->length);
71         if (!message->send_buf)
72         {
73             SPI_BlockTransfer(spi_id, message->recv_buf, message->recv_buf, message->length);
74         }
75         else
76         {
77             SPI_BlockTransfer(spi_id, message->send_buf, message->recv_buf, message->length);
78         }
79         LOG_D("spi%d done", spi_id);
80     }
81     if (message->cs_release && !(device->config.mode & RT_SPI_NO_CS))
82     {
83         if (device->config.mode & RT_SPI_CS_HIGH)
84             GPIO_Output(cs_pin, 0);
85         else
86             GPIO_Output(cs_pin, 1);
87     }
88 
89     return message->length;
90 }
91 
spi_configure(struct rt_spi_device * device,struct rt_spi_configuration * configuration)92 static rt_err_t spi_configure(struct rt_spi_device *device,
93                               struct rt_spi_configuration *configuration)
94 {
95     RT_ASSERT(device != RT_NULL);
96     RT_ASSERT(configuration != RT_NULL);
97     rt_uint32_t spi_id = device->bus->parent.user_data;
98     rt_uint8_t mode = configuration->mode & (RT_SPI_CPHA | RT_SPI_CPOL);
99     if (configuration->mode & RT_SPI_SLAVE) return -RT_EINVAL;
100     switch(spi_id)
101     {
102     case 0:
103         GPIO_Iomux(GPIOC_12,3);
104         GPIO_Iomux(GPIOC_13,3);
105         GPIO_Iomux(GPIOC_15,3);
106         break;
107     case 1:
108         GPIO_Iomux(GPIOB_12, 0);
109         GPIO_Iomux(GPIOB_14, 0);
110         GPIO_Iomux(GPIOB_15, 0);
111         break;
112     case 2:
113         GPIO_Iomux(GPIOA_06,3);
114         GPIO_Iomux(GPIOA_08,3);
115         GPIO_Iomux(GPIOA_09,3);
116 
117         break;
118     case 3:
119         GPIO_Iomux(GPIOB_02,0);
120         GPIO_Iomux(GPIOB_04,0);
121         GPIO_Iomux(GPIOB_05,0);
122         break;
123     }
124     SPI_MasterInit(spi_id, configuration->data_width, mode, configuration->max_hz, RT_NULL, RT_NULL);
125 
126     return RT_EOK;
127 }
128 
129 static const struct rt_spi_ops air105_spi_ops =
130 {
131     .configure = spi_configure,
132     .xfer = spixfer,
133 };
134 
135 /**
136   * Attach the spi device to SPI bus, this function must be used after initialization.
137   */
rt_hw_spi_device_attach(const char * bus_name,const char * device_name,rt_uint8_t cs_pin)138 rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint8_t cs_pin)
139 {
140     RT_ASSERT(bus_name != RT_NULL);
141     RT_ASSERT(device_name != RT_NULL);
142 
143     rt_err_t result;
144     struct rt_spi_device *spi_device;
145 
146     /* attach the device to spi bus*/
147     spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
148     RT_ASSERT(spi_device != RT_NULL);
149     GPIO_Config(cs_pin, 0, 1);
150 
151     result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
152 
153     if (result != RT_EOK)
154     {
155         LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result);
156     }
157 
158     RT_ASSERT(result == RT_EOK);
159 
160     LOG_D("%s attach to %s done", device_name, bus_name);
161 
162     return result;
163 }
164 
165 
rt_hw_spi_init(void)166 int rt_hw_spi_init(void)
167 {
168     rt_err_t result;
169     rt_size_t obj_num = sizeof(spi_config) / sizeof(struct air_spi);
170     for (int spi_index = 0; spi_index < obj_num ; spi_index++)
171     {
172         result = rt_spi_bus_register(&(spi_config[spi_index].bus), spi_config[spi_index].bus_name, &air105_spi_ops);
173         RT_ASSERT(result == RT_EOK);
174         spi_config[spi_index].bus.parent.user_data = spi_config[spi_index].id;
175     }
176     return RT_EOK;
177 }
178 INIT_BOARD_EXPORT(rt_hw_spi_init);
179 
180 
181 #endif /* RT_USING_SPI */
182