1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author         Notes
8  * 2019-07-29     zdzn           first version
9  */
10 #include "drv_spi.h"
11 #include "raspi.h"
12 
13 #ifdef RT_USING_SPI
14 
15 #define RPI_CORE_CLK_HZ        250000000
16 #define BSP_SPI_MAX_HZ (30* 1000 *1000)
17 #define SPITIMEOUT 0x0FFF
18 
spi_gpio_write(rt_uint8_t pin,rt_uint8_t val)19 void spi_gpio_write(rt_uint8_t pin, rt_uint8_t val)
20 {
21     if (val)
22         BCM283X_GPIO_GPSET((pin / 32)) = 1 << (pin % 32);
23     else
24         BCM283X_GPIO_GPCLR((pin / 32)) = 1 << (pin % 32);
25 }
26 
27 struct raspi_spi_hw_config
28 {
29     rt_uint8_t spi_num;
30     raspi_gpio_pin sclk_pin;
31     raspi_pin_select sclk_mode;
32     raspi_gpio_pin mosi_pin;
33     raspi_pin_select mosi_mode;
34     raspi_gpio_pin miso_pin;
35     raspi_pin_select miso_mode;
36 #if defined (BSP_USING_SPI0_DEVICE0) || defined (BSP_USING_SPI1_DEVICE0)
37     raspi_gpio_pin ce0_pin;
38     raspi_pin_select ce0_mode;
39 #endif
40 
41 #if defined (BSP_USING_SPI0_DEVICE1) || defined (BSP_USING_SPI1_DEVICE1)
42     raspi_gpio_pin ce1_pin;
43     raspi_pin_select ce1_mode;
44 #endif
45 
46 #if defined (BSP_USING_SPI1_DEVICE2)
47     raspi_gpio_pin ce2_pin;
48     raspi_pin_select ce2_mode;
49 #endif
50 };
51 
52 struct raspi_spi_device
53 {
54     char *device_name;
55     struct rt_spi_bus *spi_bus;
56     struct rt_spi_device *spi_device;
57     raspi_gpio_pin cs_pin;
58 };
59 
raspi_spi_configure(struct rt_spi_device * device,struct rt_spi_configuration * cfg)60 static rt_err_t raspi_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
61 {
62     RT_ASSERT(cfg != RT_NULL);
63     RT_ASSERT(device != RT_NULL);
64     rt_uint16_t divider;
65 
66     // spi clear fifo
67     BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CLEAR;
68 
69     if (cfg->mode & RT_SPI_CPOL)
70         BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CPOL;
71 
72     if (cfg->mode & RT_SPI_CPHA)
73         BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CPHA;
74 
75     if (cfg->mode & RT_SPI_CS_HIGH)
76         BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CSPOL;
77 
78     //set clk
79     if (cfg->max_hz > BSP_SPI_MAX_HZ)
80         cfg->max_hz = BSP_SPI_MAX_HZ;
81 
82     divider = (rt_uint16_t) ((rt_uint32_t) RPI_CORE_CLK_HZ / cfg->max_hz);
83     divider &= 0xFFFE;
84 
85     BCM283X_SPI0_CLK(BCM283X_SPI0_BASE) = divider;
86 
87     return RT_EOK;
88 }
89 
correct_order(rt_uint8_t b,rt_uint8_t flag)90 rt_uint8_t correct_order(rt_uint8_t b, rt_uint8_t flag)
91 {
92     if (flag)
93         return raspi_byte_reverse_table[b];
94     else
95         return b;
96 }
97 
spi_transfernb(rt_uint8_t * tbuf,rt_uint8_t * rbuf,rt_uint32_t len,rt_uint8_t flag)98 static rt_err_t spi_transfernb(rt_uint8_t* tbuf, rt_uint8_t* rbuf, rt_uint32_t len, rt_uint8_t flag)
99 {
100     rt_uint32_t TXCnt=0;
101     rt_uint32_t RXCnt=0;
102 
103     /* Clear TX and RX fifos */
104     BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (BCM283X_SPI0_CS_CLEAR & BCM283X_SPI0_CS_CLEAR);
105 
106     /* Set TA = 1 */
107     BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (BCM283X_SPI0_CS_TA & BCM283X_SPI0_CS_TA);
108 
109 
110     /* Use the FIFO's to reduce the interbyte times */
111     while ((TXCnt < len) || (RXCnt < len))
112     {
113         /* TX fifo not full, so add some more bytes */
114         while (((BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_TXD)) && (TXCnt < len))
115         {
116             BCM283X_SPI0_FIFO(BCM283X_SPI0_BASE) = correct_order(tbuf[TXCnt],flag);
117             TXCnt++;
118         }
119         /* Rx fifo not empty, so get the next received bytes */
120         while (((BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_RXD)) && (RXCnt < len))
121         {
122             rbuf[RXCnt] = correct_order(BCM283X_SPI0_FIFO(BCM283X_SPI0_BASE),flag);
123             RXCnt++;
124         }
125     }
126     /* Wait for DONE to be set */
127     while (!(BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_DONE));
128 
129     /* Set TA = 0, and also set the barrier */
130     BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (0 & BCM283X_SPI0_CS_TA);
131     return RT_EOK;
132 }
133 
raspi_spi_xfer(struct rt_spi_device * device,struct rt_spi_message * message)134 static rt_ssize_t raspi_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
135 {
136 
137     RT_ASSERT(device != RT_NULL);
138     RT_ASSERT(device->bus != RT_NULL);
139     RT_ASSERT(device->parent.user_data != RT_NULL);
140     RT_ASSERT(message->send_buf != RT_NULL || message->recv_buf != RT_NULL);
141 
142     rt_err_t res;
143     rt_uint8_t flag;
144     struct rt_spi_configuration config = device->config;
145     raspi_gpio_pin cs_pin = (raspi_gpio_pin)device->parent.user_data;
146 
147     if (config.mode & RT_SPI_MSB)
148         flag = 0;
149     else
150         flag = 1;
151     if (message->cs_take);
152       //  (config.mode & RT_SPI_CS_HIGH)?
153       //          spi_gpio_write(cs_pin, 1):
154       //          spi_gpio_write(cs_pin, 0);
155 
156     /* deal data */
157     res = spi_transfernb((rt_uint8_t *)message->send_buf, (rt_uint8_t *)message->recv_buf,
158             (rt_int32_t)message->length, flag);
159 
160     if (message->cs_release)
161         (config.mode & RT_SPI_CS_HIGH)?
162                 spi_gpio_write(cs_pin, 0):
163                 spi_gpio_write(cs_pin, 1);
164 
165     if (res != RT_EOK)
166            return res;
167 
168     return message->length;
169 }
170 
raspi_spi_bus_attach_device(const char * bus_name,struct raspi_spi_device * device)171 rt_err_t raspi_spi_bus_attach_device(const char *bus_name, struct raspi_spi_device *device)
172 {
173     rt_err_t ret;
174     RT_ASSERT(device != RT_NULL);
175     ret = rt_spi_bus_attach_device(device->spi_device, device->device_name, bus_name, (void *)(device->cs_pin));
176     return ret;
177 }
178 
raspi_spi_hw_init(struct raspi_spi_hw_config * hwcfg)179 rt_err_t raspi_spi_hw_init(struct raspi_spi_hw_config *hwcfg)
180 {
181     GPIO_FSEL(hwcfg->sclk_pin, hwcfg->sclk_mode);
182     GPIO_FSEL(hwcfg->miso_pin, hwcfg->miso_mode);
183     GPIO_FSEL(hwcfg->mosi_pin, hwcfg->mosi_mode);
184 
185 #if defined (BSP_USING_SPI0_DEVICE0)
186     GPIO_FSEL(hwcfg->ce0_pin, hwcfg->ce0_mode);
187 #endif
188 
189 #if defined (BSP_USING_SPI0_DEVICE1)
190     GPIO_FSEL(hwcfg->ce1_pin, hwcfg->ce1_mode);
191 #endif
192 
193     BCM283X_SPI0_CS(BCM283X_SPI0_BASE) = 0;
194     BCM283X_SPI0_CS(BCM283X_SPI0_BASE) = BCM283X_SPI0_CS_CLEAR;
195 
196     //enable chip select
197 #if defined (BSP_USING_SPI0_DEVICE0)
198     BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= 0;
199 #endif
200 
201 #if defined (BSP_USING_SPI0_DEVICE1)
202     BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= 0x2;
203 #endif
204 
205 #if defined (BSP_USING_SPI0_DEVICE0) && defined (BSP_USING_SPI0_DEVICE1)
206     BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CS;
207 #endif
208     return RT_EOK;
209 }
210 
211 static struct rt_spi_ops raspi_spi_ops =
212 {
213     .configure = raspi_spi_configure,
214     .xfer = raspi_spi_xfer
215 };
216 
217 #if defined (BSP_USING_SPI0_BUS)
218 #define SPI0_BUS_NAME  "spi0"
219 #define SPI0_DEVICE0_NAME  "spi0.0"
220 #define SPI0_DEVICE1_NAME  "spi0.1"
221 
222 struct rt_spi_bus spi0_bus;
223 
224 #if defined (BSP_USING_SPI0_DEVICE0)
225 struct rt_spi_device spi0_device0;
226 #endif
227 
228 #if defined (BSP_USING_SPI0_DEVICE1)
229 static struct rt_spi_device spi0_device1;
230 #endif
231 
232 struct raspi_spi_hw_config raspi_spi0_hw =
233 {
234     .spi_num = 0,
235     .sclk_pin = RPI_GPIO_P1_23,
236     .sclk_mode = BCM283X_GPIO_FSEL_ALT0,
237     .mosi_pin = RPI_GPIO_P1_19,
238     .mosi_mode = BCM283X_GPIO_FSEL_ALT0,
239     .miso_pin = RPI_GPIO_P1_21,
240     .miso_mode = BCM283X_GPIO_FSEL_ALT0,
241 
242 #if defined (BSP_USING_SPI0_DEVICE0)
243     .ce0_pin = RPI_GPIO_P1_24,
244     .ce0_mode = BCM283X_GPIO_FSEL_ALT0,
245 #endif
246 
247 #if defined (BSP_USING_SPI0_DEVICE1)
248     .ce1_pin = RPI_GPIO_P1_26,
249     .ce1_mode = BCM283X_GPIO_FSEL_ALT0,
250 #endif
251 };
252 #endif
253 
rt_hw_spi_init(void)254 int rt_hw_spi_init(void)
255 {
256 
257 #if defined (BSP_USING_SPI0_BUS)
258     raspi_spi_hw_init(&raspi_spi0_hw);
259     rt_spi_bus_register(&spi0_bus, SPI0_BUS_NAME, &raspi_spi_ops);
260 
261 #if defined (BSP_USING_SPI0_DEVICE0)
262     struct raspi_spi_device raspi_spi0_device0 =
263     {
264         .device_name = SPI0_DEVICE0_NAME,
265         .spi_bus = &spi0_bus,
266         .spi_device = &spi0_device0,
267         .cs_pin = raspi_spi0_hw.ce0_pin,
268     };
269     raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device0);
270 #endif
271 
272 #if defined (BSP_USING_SPI0_DEVICE1)
273     struct raspi_spi_device raspi_spi0_device1 =
274     {
275         .device_name = SPI0_DEVICE1_NAME,
276         .spi_bus = &spi0_bus,
277         .spi_device = &spi0_device1,
278         .cs_pin = raspi_spi0_hw.ce1_pin,
279     };
280     raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device1);
281 #endif
282 #endif
283     return RT_EOK;
284 }
285 INIT_DEVICE_EXPORT(rt_hw_spi_init);
286 
287 #endif
288