1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2012-01-08 bernard first version. 9 * 2012-02-03 bernard add const attribute to the ops. 10 * 2012-05-15 dzzxzz fixed the return value in attach_device. 11 * 2012-05-18 bernard Changed SPI message to message list. 12 * Added take/release SPI device/bus interface. 13 * 2012-09-28 aozima fixed rt_spi_release_bus assert error. 14 */ 15 16 #include <drivers/spi.h> 17 18 extern rt_err_t rt_spi_bus_device_init(struct rt_spi_bus *bus, const char *name); 19 extern rt_err_t rt_spidev_device_init(struct rt_spi_device *dev, const char *name); 20 21 rt_err_t rt_spi_bus_register(struct rt_spi_bus *bus, 22 const char *name, 23 const struct rt_spi_ops *ops) 24 { 25 rt_err_t result; 26 27 result = rt_spi_bus_device_init(bus, name); 28 if (result != RT_EOK) 29 return result; 30 31 /* initialize mutex lock */ 32 rt_mutex_init(&(bus->lock), name, RT_IPC_FLAG_FIFO); 33 /* set ops */ 34 bus->ops = ops; 35 /* initialize owner */ 36 bus->owner = RT_NULL; 37 /* set bus mode */ 38 bus->mode = RT_SPI_BUS_MODE_SPI; 39 40 return RT_EOK; 41 } 42 43 rt_err_t rt_spi_bus_attach_device(struct rt_spi_device *device, 44 const char *name, 45 const char *bus_name, 46 void *user_data) 47 { 48 rt_err_t result; 49 rt_device_t bus; 50 51 /* get physical spi bus */ 52 bus = rt_device_find(bus_name); 53 if (bus != RT_NULL && bus->type == RT_Device_Class_SPIBUS) 54 { 55 device->bus = (struct rt_spi_bus *)bus; 56 57 /* initialize spidev device */ 58 result = rt_spidev_device_init(device, name); 59 if (result != RT_EOK) 60 return result; 61 62 rt_memset(&device->config, 0, sizeof(device->config)); 63 device->parent.user_data = user_data; 64 65 return RT_EOK; 66 } 67 68 /* not found the host bus */ 69 return -RT_ERROR; 70 } 71 72 rt_err_t rt_spi_configure(struct rt_spi_device *device, 73 struct rt_spi_configuration *cfg) 74 { 75 rt_err_t result; 76 77 RT_ASSERT(device != RT_NULL); 78 79 /* set configuration */ 80 device->config.data_width = cfg->data_width; 81 device->config.mode = cfg->mode & RT_SPI_MODE_MASK ; 82 device->config.max_hz = cfg->max_hz ; 83 84 if (device->bus != RT_NULL) 85 { 86 result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER); 87 if (result == RT_EOK) 88 { 89 if (device->bus->owner == device) 90 { 91 device->bus->ops->configure(device, &device->config); 92 } 93 94 /* release lock */ 95 rt_mutex_release(&(device->bus->lock)); 96 } 97 } 98 99 return RT_EOK; 100 } 101 102 rt_err_t rt_spi_send_then_send(struct rt_spi_device *device, 103 const void *send_buf1, 104 rt_size_t send_length1, 105 const void *send_buf2, 106 rt_size_t send_length2) 107 { 108 rt_err_t result; 109 struct rt_spi_message message; 110 111 RT_ASSERT(device != RT_NULL); 112 RT_ASSERT(device->bus != RT_NULL); 113 114 result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER); 115 if (result == RT_EOK) 116 { 117 if (device->bus->owner != device) 118 { 119 /* not the same owner as current, re-configure SPI bus */ 120 result = device->bus->ops->configure(device, &device->config); 121 if (result == RT_EOK) 122 { 123 /* set SPI bus owner */ 124 device->bus->owner = device; 125 } 126 else 127 { 128 /* configure SPI bus failed */ 129 result = -RT_EIO; 130 goto __exit; 131 } 132 } 133 134 /* send data1 */ 135 message.send_buf = send_buf1; 136 message.recv_buf = RT_NULL; 137 message.length = send_length1; 138 message.cs_take = 1; 139 message.cs_release = 0; 140 message.next = RT_NULL; 141 142 result = device->bus->ops->xfer(device, &message); 143 if (result == 0) 144 { 145 result = -RT_EIO; 146 goto __exit; 147 } 148 149 /* send data2 */ 150 message.send_buf = send_buf2; 151 message.recv_buf = RT_NULL; 152 message.length = send_length2; 153 message.cs_take = 0; 154 message.cs_release = 1; 155 message.next = RT_NULL; 156 157 result = device->bus->ops->xfer(device, &message); 158 if (result == 0) 159 { 160 result = -RT_EIO; 161 goto __exit; 162 } 163 164 result = RT_EOK; 165 } 166 else 167 { 168 return -RT_EIO; 169 } 170 171 __exit: 172 rt_mutex_release(&(device->bus->lock)); 173 174 return result; 175 } 176 177 rt_err_t rt_spi_send_then_recv(struct rt_spi_device *device, 178 const void *send_buf, 179 rt_size_t send_length, 180 void *recv_buf, 181 rt_size_t recv_length) 182 { 183 rt_err_t result; 184 struct rt_spi_message message; 185 186 RT_ASSERT(device != RT_NULL); 187 RT_ASSERT(device->bus != RT_NULL); 188 189 result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER); 190 if (result == RT_EOK) 191 { 192 if (device->bus->owner != device) 193 { 194 /* not the same owner as current, re-configure SPI bus */ 195 result = device->bus->ops->configure(device, &device->config); 196 if (result == RT_EOK) 197 { 198 /* set SPI bus owner */ 199 device->bus->owner = device; 200 } 201 else 202 { 203 /* configure SPI bus failed */ 204 result = -RT_EIO; 205 goto __exit; 206 } 207 } 208 209 /* send data */ 210 message.send_buf = send_buf; 211 message.recv_buf = RT_NULL; 212 message.length = send_length; 213 message.cs_take = 1; 214 message.cs_release = 0; 215 message.next = RT_NULL; 216 217 result = device->bus->ops->xfer(device, &message); 218 if (result == 0) 219 { 220 result = -RT_EIO; 221 goto __exit; 222 } 223 224 /* recv data */ 225 message.send_buf = RT_NULL; 226 message.recv_buf = recv_buf; 227 message.length = recv_length; 228 message.cs_take = 0; 229 message.cs_release = 1; 230 message.next = RT_NULL; 231 232 result = device->bus->ops->xfer(device, &message); 233 if (result == 0) 234 { 235 result = -RT_EIO; 236 goto __exit; 237 } 238 239 result = RT_EOK; 240 } 241 else 242 { 243 return -RT_EIO; 244 } 245 246 __exit: 247 rt_mutex_release(&(device->bus->lock)); 248 249 return result; 250 } 251 252 rt_size_t rt_spi_transfer(struct rt_spi_device *device, 253 const void *send_buf, 254 void *recv_buf, 255 rt_size_t length) 256 { 257 rt_err_t result; 258 struct rt_spi_message message; 259 260 RT_ASSERT(device != RT_NULL); 261 RT_ASSERT(device->bus != RT_NULL); 262 263 result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER); 264 if (result == RT_EOK) 265 { 266 if (device->bus->owner != device) 267 { 268 /* not the same owner as current, re-configure SPI bus */ 269 result = device->bus->ops->configure(device, &device->config); 270 if (result == RT_EOK) 271 { 272 /* set SPI bus owner */ 273 device->bus->owner = device; 274 } 275 else 276 { 277 /* configure SPI bus failed */ 278 rt_set_errno(-RT_EIO); 279 result = 0; 280 goto __exit; 281 } 282 } 283 284 /* initial message */ 285 message.send_buf = send_buf; 286 message.recv_buf = recv_buf; 287 message.length = length; 288 message.cs_take = 1; 289 message.cs_release = 1; 290 message.next = RT_NULL; 291 292 /* transfer message */ 293 result = device->bus->ops->xfer(device, &message); 294 if (result == 0) 295 { 296 rt_set_errno(-RT_EIO); 297 goto __exit; 298 } 299 } 300 else 301 { 302 rt_set_errno(-RT_EIO); 303 304 return 0; 305 } 306 307 __exit: 308 rt_mutex_release(&(device->bus->lock)); 309 310 return result; 311 } 312 313 struct rt_spi_message *rt_spi_transfer_message(struct rt_spi_device *device, 314 struct rt_spi_message *message) 315 { 316 rt_err_t result; 317 struct rt_spi_message *index; 318 319 RT_ASSERT(device != RT_NULL); 320 321 /* get first message */ 322 index = message; 323 if (index == RT_NULL) 324 return index; 325 326 result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER); 327 if (result != RT_EOK) 328 { 329 rt_set_errno(-RT_EBUSY); 330 331 return index; 332 } 333 334 /* reset errno */ 335 rt_set_errno(RT_EOK); 336 337 /* configure SPI bus */ 338 if (device->bus->owner != device) 339 { 340 /* not the same owner as current, re-configure SPI bus */ 341 result = device->bus->ops->configure(device, &device->config); 342 if (result == RT_EOK) 343 { 344 /* set SPI bus owner */ 345 device->bus->owner = device; 346 } 347 else 348 { 349 /* configure SPI bus failed */ 350 rt_set_errno(-RT_EIO); 351 goto __exit; 352 } 353 } 354 355 /* transmit each SPI message */ 356 while (index != RT_NULL) 357 { 358 /* transmit SPI message */ 359 result = device->bus->ops->xfer(device, index); 360 if (result == 0) 361 { 362 rt_set_errno(-RT_EIO); 363 break; 364 } 365 366 index = index->next; 367 } 368 369 __exit: 370 /* release bus lock */ 371 rt_mutex_release(&(device->bus->lock)); 372 373 return index; 374 } 375 376 rt_err_t rt_spi_take_bus(struct rt_spi_device *device) 377 { 378 rt_err_t result = RT_EOK; 379 380 RT_ASSERT(device != RT_NULL); 381 RT_ASSERT(device->bus != RT_NULL); 382 383 result = rt_mutex_take(&(device->bus->lock), RT_WAITING_FOREVER); 384 if (result != RT_EOK) 385 { 386 rt_set_errno(-RT_EBUSY); 387 388 return -RT_EBUSY; 389 } 390 391 /* reset errno */ 392 rt_set_errno(RT_EOK); 393 394 /* configure SPI bus */ 395 if (device->bus->owner != device) 396 { 397 /* not the same owner as current, re-configure SPI bus */ 398 result = device->bus->ops->configure(device, &device->config); 399 if (result == RT_EOK) 400 { 401 /* set SPI bus owner */ 402 device->bus->owner = device; 403 } 404 else 405 { 406 /* configure SPI bus failed */ 407 rt_set_errno(-RT_EIO); 408 /* release lock */ 409 rt_mutex_release(&(device->bus->lock)); 410 411 return -RT_EIO; 412 } 413 } 414 415 return result; 416 } 417 418 rt_err_t rt_spi_release_bus(struct rt_spi_device *device) 419 { 420 RT_ASSERT(device != RT_NULL); 421 RT_ASSERT(device->bus != RT_NULL); 422 RT_ASSERT(device->bus->owner == device); 423 424 /* release lock */ 425 rt_mutex_release(&(device->bus->lock)); 426 427 return RT_EOK; 428 } 429 430 rt_err_t rt_spi_take(struct rt_spi_device *device) 431 { 432 rt_err_t result; 433 struct rt_spi_message message; 434 435 RT_ASSERT(device != RT_NULL); 436 RT_ASSERT(device->bus != RT_NULL); 437 438 rt_memset(&message, 0, sizeof(message)); 439 message.cs_take = 1; 440 441 result = device->bus->ops->xfer(device, &message); 442 443 return result; 444 } 445 446 rt_err_t rt_spi_release(struct rt_spi_device *device) 447 { 448 rt_err_t result; 449 struct rt_spi_message message; 450 451 RT_ASSERT(device != RT_NULL); 452 RT_ASSERT(device->bus != RT_NULL); 453 454 rt_memset(&message, 0, sizeof(message)); 455 message.cs_release = 1; 456 457 result = device->bus->ops->xfer(device, &message); 458 459 return result; 460 } 461