File indexing completed on 2025-05-11 08:23:44
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #define RTEMS_STATUS_CHECKS_USE_PRINTK
0013
0014 #include <rtems.h>
0015 #include <stdio.h>
0016 #include <bsp.h>
0017 #include <string.h>
0018 #include <rtems/libio.h>
0019 #include <rtems/status-checks.h>
0020 #include "../include/system_conf.h"
0021 #include <bsp/milkymist_flash.h>
0022
0023 static struct flash_partition partitions[FLASH_PARTITION_COUNT]
0024 = FLASH_PARTITIONS;
0025
0026 static rtems_id flash_lock;
0027
0028 rtems_device_driver flash_initialize(
0029 rtems_device_major_number major,
0030 rtems_device_minor_number minor,
0031 void *arg
0032 )
0033 {
0034 rtems_status_code sc;
0035 int i;
0036 char devname[16];
0037
0038 for (i=0;i<FLASH_PARTITION_COUNT;i++) {
0039 sprintf(devname, "/dev/flash%d", i+1);
0040 sc = rtems_io_register_name(devname, major, i);
0041 RTEMS_CHECK_SC(sc, "Create flash device");
0042 }
0043
0044 sc = rtems_semaphore_create(
0045 rtems_build_name('F', 'L', 'S', 'H'),
0046 1,
0047 RTEMS_SIMPLE_BINARY_SEMAPHORE,
0048 0,
0049 &flash_lock
0050 );
0051 RTEMS_CHECK_SC(sc, "create semaphore");
0052
0053 return RTEMS_SUCCESSFUL;
0054 }
0055
0056 rtems_device_driver flash_read(
0057 rtems_device_major_number major,
0058 rtems_device_minor_number minor,
0059 void *arg
0060 )
0061 {
0062 rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
0063 void *startaddr;
0064 int len;
0065
0066 if (minor >= FLASH_PARTITION_COUNT)
0067 return RTEMS_UNSATISFIED;
0068
0069 startaddr = (void *)(partitions[minor].start_address
0070 + (unsigned int)rw_args->offset);
0071 len = partitions[minor].length - rw_args->offset;
0072 if (len > rw_args->count)
0073 len = rw_args->count;
0074 if (len <= 0) {
0075 rw_args->bytes_moved = 0;
0076 return RTEMS_SUCCESSFUL;
0077 }
0078
0079 rtems_semaphore_obtain(flash_lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0080 memcpy(rw_args->buffer, startaddr, len);
0081 rtems_semaphore_release(flash_lock);
0082
0083 rw_args->bytes_moved = len;
0084 return RTEMS_SUCCESSFUL;
0085 }
0086
0087 rtems_device_driver flash_write(
0088 rtems_device_major_number major,
0089 rtems_device_minor_number minor,
0090 void *arg
0091 )
0092 {
0093 rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
0094 volatile unsigned short *startaddr;
0095 unsigned short *srcdata;
0096 int len;
0097 int this_time;
0098 int remaining;
0099 int i;
0100
0101 if (minor >= FLASH_PARTITION_COUNT)
0102 return RTEMS_UNSATISFIED;
0103
0104 startaddr = (unsigned short *)(partitions[minor].start_address
0105 + (unsigned int)rw_args->offset);
0106 len = partitions[minor].length - rw_args->offset;
0107 if (len > rw_args->count)
0108 len = rw_args->count;
0109 if (len <= 2) {
0110 rw_args->bytes_moved = 0;
0111 return RTEMS_SUCCESSFUL;
0112 }
0113 len /= 2;
0114 srcdata = (unsigned short *)rw_args->buffer;
0115 remaining = len;
0116
0117 rtems_semaphore_obtain(flash_lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0118 while (remaining > 0) {
0119 this_time = remaining;
0120 if (this_time > 256)
0121 this_time = 256;
0122
0123
0124
0125 do {
0126 *startaddr = 0x00e8;
0127 } while (!(*startaddr & 0x0080));
0128
0129 *startaddr = this_time-1;
0130
0131 for(i=0;i<this_time;i++)
0132 startaddr[i] = srcdata[i];
0133
0134 *startaddr = 0x00d0;
0135 while (!(*startaddr & 0x0080));
0136 *startaddr = 0x0050;
0137
0138 startaddr += this_time;
0139 srcdata += this_time;
0140 remaining -= this_time;
0141 }
0142 *startaddr = 0x00ff;
0143 rtems_semaphore_release(flash_lock);
0144
0145 rw_args->bytes_moved = 2*len;
0146 return RTEMS_SUCCESSFUL;
0147 }
0148
0149 rtems_device_driver flash_control(
0150 rtems_device_major_number major,
0151 rtems_device_minor_number minor,
0152 void *arg
0153 )
0154 {
0155 rtems_libio_ioctl_args_t *args = arg;
0156 unsigned int eraseaddr_i;
0157 volatile unsigned short *eraseaddr;
0158
0159 if (minor >= FLASH_PARTITION_COUNT) {
0160 args->ioctl_return = -1;
0161 return RTEMS_UNSATISFIED;
0162 }
0163
0164 switch (args->command) {
0165 case FLASH_GET_SIZE:
0166 *((unsigned int *)args->buffer) = partitions[minor].length;
0167 break;
0168 case FLASH_GET_BLOCKSIZE:
0169 *((unsigned int *)args->buffer) = 128*1024;
0170 break;
0171 case FLASH_ERASE_BLOCK:
0172 eraseaddr_i = (unsigned int)args->buffer;
0173 if (eraseaddr_i >= partitions[minor].length) {
0174 args->ioctl_return = -1;
0175 return RTEMS_UNSATISFIED;
0176 }
0177 eraseaddr_i = eraseaddr_i + partitions[minor].start_address;
0178 eraseaddr = (unsigned short *)eraseaddr_i;
0179 rtems_semaphore_obtain(flash_lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
0180 *eraseaddr = 0x0020;
0181 *eraseaddr = 0x00d0;
0182 while(!(*eraseaddr & 0x0080));
0183 *eraseaddr = 0x0050;
0184 *eraseaddr = 0x00ff;
0185 rtems_semaphore_release(flash_lock);
0186 break;
0187 default:
0188 args->ioctl_return = -1;
0189 return RTEMS_UNSATISFIED;
0190 }
0191 args->ioctl_return = 0;
0192 return RTEMS_SUCCESSFUL;
0193 }