File indexing completed on 2025-05-11 08:24:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #include <rtems.h>
0039 #include <rtems/libi2c.h>
0040
0041 #include <libchip/spi-memdrv.h>
0042 #include <rtems/libio.h>
0043
0044 #define SPI_MEM_CMD_WREN 0x06
0045 #define SPI_MEM_CMD_WRDIS 0x04
0046 #define SPI_MEM_CMD_RDID 0x9F
0047 #define SPI_MEM_CMD_RDSR 0x05
0048 #define SPI_MEM_CMD_WRSR 0x01
0049 #define SPI_MEM_CMD_READ 0x03
0050 #define SPI_MEM_CMD_PP 0x02
0051 #define SPI_MEM_CMD_SE 0xD8
0052 #define SPI_MEM_CMD_BE 0xC7
0053 #define SPI_MEM_CMD_DP 0xB9
0054 #define SPI_MEM_CMD_RES 0xAB
0055
0056
0057
0058
0059 static rtems_status_code spi_memdrv_minor2param_ptr
0060 (
0061
0062
0063
0064
0065
0066
0067 rtems_device_minor_number minor,
0068 spi_memdrv_param_t **param_ptr
0069 )
0070
0071
0072
0073
0074 {
0075 rtems_status_code rc = RTEMS_SUCCESSFUL;
0076 spi_memdrv_t *drv_ptr;
0077
0078 if (rc == RTEMS_SUCCESSFUL) {
0079 rc = -rtems_libi2c_ioctl(minor,
0080 RTEMS_LIBI2C_IOCTL_GET_DRV_T,
0081 &drv_ptr);
0082 }
0083 if ((rc == RTEMS_SUCCESSFUL) &&
0084 (drv_ptr->libi2c_drv_entry.size != sizeof(spi_memdrv_t))) {
0085 rc = RTEMS_INVALID_SIZE;
0086 }
0087 if (rc == RTEMS_SUCCESSFUL) {
0088 *param_ptr = &(drv_ptr->spi_memdrv_param);
0089 }
0090 return rc;
0091 }
0092
0093
0094
0095
0096 static rtems_status_code spi_memdrv_wait_ms
0097 (
0098
0099
0100
0101
0102
0103
0104 int ms
0105 )
0106
0107
0108
0109
0110 {
0111 rtems_interval ticks_per_second;
0112
0113 ticks_per_second = rtems_clock_get_ticks_per_second();
0114 (void) rtems_task_wake_after(ticks_per_second * ms / 1000);
0115 return 0;
0116 }
0117
0118
0119
0120
0121 rtems_status_code spi_memdrv_write
0122 (
0123
0124
0125
0126
0127
0128
0129 rtems_device_major_number major,
0130 rtems_device_minor_number minor,
0131 void *arg
0132 )
0133
0134
0135
0136
0137 {
0138 rtems_status_code rc = RTEMS_SUCCESSFUL;
0139 rtems_libio_rw_args_t *rwargs = arg;
0140 off_t off = rwargs->offset;
0141 int cnt = rwargs->count;
0142 unsigned char *buf = (unsigned char *)rwargs->buffer;
0143 int bytes_sent = 0;
0144 int curr_cnt;
0145 unsigned char cmdbuf[4];
0146 int ret_cnt = 0;
0147 int cmd_size;
0148 spi_memdrv_param_t *mem_param_ptr;
0149 rtems_libi2c_tfr_mode_t tfr_mode = {
0150 .baudrate = 20000000,
0151 .bits_per_char = 8,
0152 .lsb_first = FALSE,
0153 .clock_inv = FALSE,
0154 .clock_phs = FALSE
0155 } ;
0156
0157
0158
0159
0160 if (rc == RTEMS_SUCCESSFUL) {
0161 rc = spi_memdrv_minor2param_ptr(minor,&mem_param_ptr);
0162 }
0163
0164
0165
0166 if (rc == RTEMS_SUCCESSFUL) {
0167 if ((cnt <= 0) ||
0168 (cnt > mem_param_ptr->mem_size) ||
0169 (off > (mem_param_ptr->mem_size-cnt))) {
0170 rc = RTEMS_INVALID_SIZE;
0171 }
0172 else if (buf == NULL) {
0173 rc = RTEMS_INVALID_ADDRESS;
0174 }
0175 }
0176 while ((rc == RTEMS_SUCCESSFUL) &&
0177 (cnt > bytes_sent)) {
0178 curr_cnt = cnt - bytes_sent;
0179 if ((mem_param_ptr->page_size > 0) &&
0180 (off / mem_param_ptr->page_size) !=
0181 ((off+curr_cnt+1) / mem_param_ptr->page_size)) {
0182 curr_cnt = mem_param_ptr->page_size - (off % mem_param_ptr->page_size);
0183 }
0184
0185
0186
0187 if (rc == RTEMS_SUCCESSFUL) {
0188 rc = rtems_libi2c_send_start(minor);
0189 }
0190
0191
0192
0193 if (rc == RTEMS_SUCCESSFUL) {
0194 tfr_mode.baudrate = mem_param_ptr->baudrate;
0195 rc = -rtems_libi2c_ioctl(minor,
0196 RTEMS_LIBI2C_IOCTL_SET_TFRMODE,
0197 &tfr_mode);
0198 }
0199
0200
0201
0202
0203 if (rc == RTEMS_SUCCESSFUL) {
0204 rc = rtems_libi2c_send_addr(minor,TRUE);
0205 }
0206
0207
0208
0209
0210 if (rc == RTEMS_SUCCESSFUL) {
0211 cmdbuf[0] = SPI_MEM_CMD_WREN;
0212 ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,1);
0213 if (ret_cnt < 0) {
0214 rc = -ret_cnt;
0215 }
0216 }
0217
0218
0219
0220 if (rc == RTEMS_SUCCESSFUL) {
0221 rc = rtems_libi2c_send_stop(minor);
0222 }
0223
0224
0225
0226 if (rc == RTEMS_SUCCESSFUL) {
0227 rc = rtems_libi2c_send_start(minor);
0228 }
0229
0230
0231
0232
0233 if (rc == RTEMS_SUCCESSFUL) {
0234 rc = rtems_libi2c_send_addr(minor,TRUE);
0235 }
0236
0237
0238
0239
0240 if (rc == RTEMS_SUCCESSFUL) {
0241 rc = -rtems_libi2c_ioctl(minor,
0242 RTEMS_LIBI2C_IOCTL_SET_TFRMODE,
0243 &tfr_mode);
0244 }
0245
0246
0247
0248 if (rc == RTEMS_SUCCESSFUL) {
0249 cmdbuf[0] = SPI_MEM_CMD_PP;
0250 if (mem_param_ptr->mem_size > 0x10000 ) {
0251 cmdbuf[1] = (off >> 16) & 0xff;
0252 cmdbuf[2] = (off >> 8) & 0xff;
0253 cmdbuf[3] = (off >> 0) & 0xff;
0254 cmd_size = 4;
0255 }
0256 else if (mem_param_ptr->mem_size > 256) {
0257 cmdbuf[1] = (off >> 8) & 0xff;
0258 cmdbuf[2] = (off >> 0) & 0xff;
0259 cmd_size = 3;
0260 }
0261 else {
0262 cmdbuf[1] = (off >> 0) & 0xff;
0263 cmd_size = 1;
0264 }
0265
0266 ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,cmd_size);
0267 if (ret_cnt < 0) {
0268 rc = -ret_cnt;
0269 }
0270 }
0271
0272
0273
0274 if (rc == RTEMS_SUCCESSFUL) {
0275 ret_cnt = rtems_libi2c_write_bytes(minor,buf,curr_cnt);
0276 if (ret_cnt < 0) {
0277 rc = -ret_cnt;
0278 }
0279 }
0280
0281
0282
0283 if (rc == RTEMS_SUCCESSFUL) {
0284 rc = rtems_libi2c_send_stop(minor);
0285 }
0286
0287
0288
0289
0290 if (rc == RTEMS_SUCCESSFUL) {
0291 rc = spi_memdrv_wait_ms(5);
0292 }
0293
0294
0295
0296 bytes_sent += curr_cnt;
0297 off += curr_cnt;
0298 buf += curr_cnt;
0299 }
0300 rwargs->bytes_moved = bytes_sent;
0301 return rc;
0302 }
0303
0304
0305
0306
0307 rtems_status_code spi_memdrv_read
0308 (
0309
0310
0311
0312
0313
0314
0315 rtems_device_major_number major,
0316 rtems_device_minor_number minor,
0317 void *arg
0318 )
0319
0320
0321
0322
0323 {
0324 rtems_status_code rc = RTEMS_SUCCESSFUL;
0325 rtems_libio_rw_args_t *rwargs = arg;
0326 off_t off = rwargs->offset;
0327 int cnt = rwargs->count;
0328 unsigned char *buf = (unsigned char *)rwargs->buffer;
0329 unsigned char cmdbuf[4];
0330 int ret_cnt = 0;
0331 int cmd_size;
0332 spi_memdrv_param_t *mem_param_ptr;
0333 rtems_libi2c_tfr_mode_t tfr_mode = {
0334 .baudrate = 20000000,
0335 .bits_per_char = 8,
0336 .lsb_first = FALSE,
0337 .clock_inv = FALSE,
0338 .clock_phs = FALSE
0339 };
0340
0341
0342
0343
0344 if (rc == RTEMS_SUCCESSFUL) {
0345 rc = spi_memdrv_minor2param_ptr(minor,&mem_param_ptr);
0346 }
0347
0348
0349
0350 if (rc == RTEMS_SUCCESSFUL) {
0351 if ((cnt <= 0) ||
0352 (cnt > mem_param_ptr->mem_size) ||
0353 (off > (mem_param_ptr->mem_size-cnt))) {
0354 rc = RTEMS_INVALID_SIZE;
0355 }
0356 else if (buf == NULL) {
0357 rc = RTEMS_INVALID_ADDRESS;
0358 }
0359 }
0360
0361
0362
0363 if (rc == RTEMS_SUCCESSFUL) {
0364 rc = rtems_libi2c_send_start(minor);
0365 }
0366
0367
0368
0369 if (rc == RTEMS_SUCCESSFUL) {
0370 tfr_mode.baudrate = mem_param_ptr->baudrate;
0371 rc = -rtems_libi2c_ioctl(minor,
0372 RTEMS_LIBI2C_IOCTL_SET_TFRMODE,
0373 &tfr_mode);
0374 }
0375
0376
0377
0378 if (rc == RTEMS_SUCCESSFUL) {
0379 rc = rtems_libi2c_send_addr(minor,TRUE);
0380 }
0381
0382 if (rc == RTEMS_SUCCESSFUL) {
0383
0384
0385
0386 if (off >= mem_param_ptr->mem_size) {
0387
0388
0389
0390 cmdbuf[0] = SPI_MEM_CMD_RDSR;
0391 ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,1);
0392 if (ret_cnt < 0) {
0393 rc = -ret_cnt;
0394 }
0395 } else {
0396
0397
0398
0399 cmdbuf[0] = SPI_MEM_CMD_READ;
0400 if (mem_param_ptr->mem_size > 0x10000 ) {
0401 cmdbuf[1] = (off >> 16) & 0xff;
0402 cmdbuf[2] = (off >> 8) & 0xff;
0403 cmdbuf[3] = (off >> 0) & 0xff;
0404 cmd_size = 4;
0405 }
0406 else if (mem_param_ptr->mem_size > 256) {
0407 cmdbuf[1] = (off >> 8) & 0xff;
0408 cmdbuf[2] = (off >> 0) & 0xff;
0409 cmd_size = 3;
0410 }
0411 else {
0412 cmdbuf[1] = (off >> 0) & 0xff;
0413 cmd_size = 1;
0414 }
0415 ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,cmd_size);
0416 if (ret_cnt < 0) {
0417 rc = -ret_cnt;
0418 }
0419 }
0420 }
0421
0422
0423
0424 if (rc == RTEMS_SUCCESSFUL) {
0425 ret_cnt = rtems_libi2c_read_bytes (minor,buf,cnt);
0426 if (ret_cnt < 0) {
0427 rc = -ret_cnt;
0428 }
0429 }
0430
0431
0432
0433
0434 if (rc == RTEMS_SUCCESSFUL) {
0435 rc = rtems_libi2c_send_stop(minor);
0436 }
0437 rwargs->bytes_moved = (rc == RTEMS_SUCCESSFUL) ? ret_cnt : 0;
0438
0439 return rc;
0440 }
0441
0442
0443
0444
0445 rtems_driver_address_table spi_memdrv_rw_ops = {
0446 .read_entry = spi_memdrv_read,
0447 .write_entry = spi_memdrv_write
0448 };
0449
0450 rtems_driver_address_table spi_memdrv_ro_ops = {
0451 .read_entry = spi_memdrv_read,
0452 };
0453