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  * 2017-11-02     勤为本       first version
9  * 2018-06-09     zhuangwei    add spi0 cs0 support,remove msd_init
10  */
11 
12 #include <rtthread.h>
13 #include "drivers/dev_spi.h"
14 #include <rthw.h>
15 #include "drv_spi.h"
16 #include "ls1c_public.h"
17 #include "dev_spi_msd.h"
18 #include "dfs_fs.h"
19 #include "../libraries/ls1c_pin.h"
20 
21 #ifdef RT_USING_SPI
22 #ifdef DEBUG
23 #define DEBUG_PRINTF(...)           rt_kprintf(__VA_ARGS__)
24 #else
25 #define DEBUG_PRINTF(...)
26 #endif
27 
28 
29 static rt_err_t configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration);
30 static rt_uint32_t xfer(struct rt_spi_device *device, struct rt_spi_message *message);
31 
32 
33 static struct rt_spi_ops ls1c_spi_ops =
34 {
35     .configure  = configure,
36     .xfer       = xfer
37 };
38 
39 
configure(struct rt_spi_device * device,struct rt_spi_configuration * configuration)40 static rt_err_t configure(struct rt_spi_device *device,
41                           struct rt_spi_configuration *configuration)
42 {
43     struct rt_spi_bus *spi_bus = NULL;
44     struct ls1c_spi *ls1c_spi = NULL;
45     unsigned char SPIx = 0;
46     void *spi_base = NULL;
47     unsigned char cpol = 0;
48     unsigned char cpha = 0;
49     unsigned char val = 0;
50 
51     RT_ASSERT(NULL != device);
52     RT_ASSERT(NULL != configuration);
53 
54     spi_bus = device->bus;
55     ls1c_spi = (struct ls1c_spi *)spi_bus->parent.user_data;
56     SPIx = ls1c_spi->SPIx;
57     spi_base = ls1c_spi_get_base(SPIx);
58 
59     {
60         // 使能SPI控制器,master模式,关闭中断
61         reg_write_8(0x53, spi_base + LS1C_SPI_SPCR_OFFSET);
62 
63         // 清空状态寄存器
64         reg_write_8(0xc0, spi_base + LS1C_SPI_SPSR_OFFSET);
65 
66         // 1字节产生中断,采样(读)与发送(写)时机同时
67         reg_write_8(0x03, spi_base + LS1C_SPI_SPER_OFFSET);
68 
69         // 关闭SPI flash
70         val = reg_read_8(spi_base + LS1C_SPI_SFC_PARAM_OFFSET);
71         val &= 0xfe;
72         reg_write_8(val, spi_base + LS1C_SPI_SFC_PARAM_OFFSET);
73 
74         // spi flash时序控制寄存器
75         reg_write_8(0x05, spi_base + LS1C_SPI_SFC_TIMING_OFFSET);
76     }
77 
78     // baudrate
79     ls1c_spi_set_clock(spi_base, configuration->max_hz);
80 
81     // 设置通信模式(时钟极性和相位)
82     if (configuration->mode & RT_SPI_CPOL)      // cpol
83     {
84         cpol = SPI_CPOL_1;
85     }
86     else
87     {
88         cpol = SPI_CPOL_0;
89     }
90     if (configuration->mode & RT_SPI_CPHA)      // cpha
91     {
92         cpha = SPI_CPHA_1;
93     }
94     else
95     {
96         cpha = SPI_CPHA_0;
97     }
98     ls1c_spi_set_mode(spi_base, cpol, cpha);
99 
100     DEBUG_PRINTF("ls1c spi%d configuration\n", SPIx);
101 
102     return RT_EOK;
103 }
104 
105 
xfer(struct rt_spi_device * device,struct rt_spi_message * message)106 static rt_uint32_t xfer(struct rt_spi_device *device,
107                         struct rt_spi_message *message)
108 {
109     struct rt_spi_bus *spi_bus = NULL;
110     struct ls1c_spi *ls1c_spi = NULL;
111     void *spi_base = NULL;
112     unsigned char SPIx = 0;
113     struct ls1c_spi_cs *ls1c_spi_cs = NULL;
114     unsigned char cs = 0;
115     rt_uint32_t size = 0;
116     const rt_uint8_t *send_ptr = NULL;
117     rt_uint8_t *recv_ptr = NULL;
118     rt_uint8_t data = 0;
119 
120     RT_ASSERT(NULL != device);
121     RT_ASSERT(NULL != message);
122 
123     spi_bus = device->bus;
124     ls1c_spi = spi_bus->parent.user_data;
125     SPIx = ls1c_spi->SPIx;
126     spi_base = ls1c_spi_get_base(SPIx);
127     ls1c_spi_cs = device->parent.user_data;
128     cs = ls1c_spi_cs->cs;
129     size = message->length;
130 
131     DEBUG_PRINTF("[%s] SPIx=%d, cs=%d\n", __FUNCTION__, SPIx, cs);
132 
133     // take cs
134     if (message->cs_take)
135     {
136         ls1c_spi_set_cs(spi_base, cs, 0);
137     }
138 
139     // 收发数据
140     send_ptr = message->send_buf;
141     recv_ptr = message->recv_buf;
142     while (size--)
143     {
144         data = 0xFF;
145         if (NULL != send_ptr)
146         {
147             data = *send_ptr++;
148         }
149 
150         if (NULL != recv_ptr)
151         {
152             *recv_ptr++ = ls1c_spi_txrx_byte(spi_base, data);
153         }
154         else
155         {
156             ls1c_spi_txrx_byte(spi_base, data);
157         }
158     }
159 
160     // release cs
161     if (message->cs_release)
162     {
163         ls1c_spi_set_cs(spi_base, cs, 1);
164     }
165 
166     return message->length;
167 }
168 
169 
170 #ifdef RT_USING_SPI0
171 struct ls1c_spi ls1c_spi0 =
172 {
173     .SPIx = LS1C_SPI_0,
174 };
175 
176 static struct rt_spi_bus spi0_bus;
177 #endif
178 
179 
180 #ifdef RT_USING_SPI1
181 struct ls1c_spi ls1c_spi1 =
182 {
183     .SPIx = LS1C_SPI_1,
184 };
185 
186 static struct rt_spi_bus spi1_bus;
187 #endif
188 
189 
190 /*
191  * 初始化并注册龙芯1c的spi总线
192  * @SPI SPI总线,比如LS1C_SPI_0, LS1C_SPI_1
193  * @spi_bus_name 总线名字
194  * @ret
195  */
ls1c_spi_bus_register(rt_uint8_t SPI,const char * spi_bus_name)196 rt_err_t ls1c_spi_bus_register(rt_uint8_t SPI, const char *spi_bus_name)
197 {
198     struct rt_spi_bus *spi_bus = NULL;
199 
200 #ifdef RT_USING_SPI0
201     if (LS1C_SPI_0 == SPI)
202     {
203         spi_bus = &spi0_bus;
204         spi_bus->parent.user_data = &ls1c_spi0;
205     }
206 #endif
207 
208 #ifdef RT_USING_SPI1
209     if (LS1C_SPI_1 == SPI)
210     {
211         spi_bus = &spi1_bus;
212         spi_bus->parent.user_data = &ls1c_spi1;
213     }
214 #endif
215 
216     return rt_spi_bus_register(spi_bus, spi_bus_name, &ls1c_spi_ops);
217 }
218 
ls1c_hw_spi_init(void)219 int ls1c_hw_spi_init(void)
220 {
221 #ifdef RT_USING_SPI0
222     pin_set_purpose(78, PIN_PURPOSE_OTHER);
223     pin_set_purpose(79, PIN_PURPOSE_OTHER);
224     pin_set_purpose(80, PIN_PURPOSE_OTHER);
225     pin_set_purpose(83, PIN_PURPOSE_OTHER);//cs2 - SD card
226     pin_set_purpose(82, PIN_PURPOSE_OTHER);//cs1
227     pin_set_purpose(81, PIN_PURPOSE_OTHER);//cs0
228 
229     pin_set_remap(78, PIN_REMAP_DEFAULT);
230     pin_set_remap(79, PIN_REMAP_DEFAULT);
231     pin_set_remap(80, PIN_REMAP_DEFAULT);
232     pin_set_remap(83, PIN_REMAP_DEFAULT);//cs2 - SD card
233     pin_set_remap(82, PIN_REMAP_DEFAULT);//CS1
234     pin_set_remap(81, PIN_REMAP_DEFAULT);//cs0
235     ls1c_spi_bus_register(LS1C_SPI_0, "spi0");
236 #endif
237 
238 #ifdef RT_USING_SPI1
239     pin_set_purpose(46, PIN_PURPOSE_OTHER);
240     pin_set_purpose(47, PIN_PURPOSE_OTHER);
241     pin_set_purpose(48, PIN_PURPOSE_OTHER);
242     pin_set_purpose(49, PIN_PURPOSE_OTHER);//CS0 - touch screen
243     pin_set_remap(46, PIN_REMAP_THIRD);
244     pin_set_remap(47, PIN_REMAP_THIRD);
245     pin_set_remap(48, PIN_REMAP_THIRD);
246     pin_set_remap(49, PIN_REMAP_THIRD);//CS0 - touch screen
247     ls1c_spi_bus_register(LS1C_SPI_1, "spi1");
248 
249 #endif
250 
251 
252 #ifdef RT_USING_SPI0
253     /* attach cs */
254     {
255      static struct rt_spi_device spi_device0;
256      static struct rt_spi_device spi_device1;
257      static struct rt_spi_device spi_device2;
258      static struct rt_spi_device spi_device3;
259      static struct ls1c_spi_cs  spi_cs0;
260      static struct ls1c_spi_cs  spi_cs1;
261      static struct ls1c_spi_cs  spi_cs2;
262      static struct ls1c_spi_cs  spi_cs3;
263      /* spi02: CS2  SD Card*/
264      spi_cs2.cs = LS1C_SPI_CS_2;
265      rt_spi_bus_attach_device(&spi_device2, "spi02", "spi0", (void *)&spi_cs2);
266      spi_cs1.cs = LS1C_SPI_CS_1;
267      rt_spi_bus_attach_device(&spi_device1, "spi01", "spi0", (void *)&spi_cs1);
268      spi_cs0.cs = LS1C_SPI_CS_0;
269      rt_spi_bus_attach_device(&spi_device0, "spi00", "spi0", (void *)&spi_cs0);
270      spi_cs3.cs = LS1C_SPI_CS_3;
271      rt_spi_bus_attach_device(&spi_device3, "spi03", "spi0", (void*)&spi_cs3);
272      msd_init("sd0", "spi02");
273     }
274 #endif
275 #ifdef RT_USING_SPI1
276     {
277         static struct rt_spi_device spi_device;
278         static struct ls1c_spi_cs  spi_cs;
279 
280         /* spi10: CS0  Touch*/
281         spi_cs.cs = LS1C_SPI_CS_0;
282         rt_spi_bus_attach_device(&spi_device, "spi10", "spi1", (void *)&spi_cs);
283     }
284 #endif
285 }
286 
287 
288 INIT_BOARD_EXPORT(ls1c_hw_spi_init);
289 
board_sd_init(void)290 static int board_sd_init(void)
291 {
292     #if defined(RT_USING_DFS) && defined(RT_USING_DFS_ELMFAT)
293         /* mount sd card fat partition 1 as root directory */
294         if( dfs_mount("sd0", "/", "elm", 0, 0) == 0)
295         {
296             rt_kprintf("File System initialized!\n");
297         }
298         else
299         {
300             rt_kprintf("File System initialzation failed!\n");
301         }
302     #endif /* RT_USING_DFS && RT_USING_DFS_ELMFAT */
303 }
304 INIT_APP_EXPORT(board_sd_init);
305 
306 #endif
307 
308