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