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