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