source: rtems/bsps/lm32/shared/milkymist_flash/flash.c @ 21978523

5
Last change on this file since 21978523 was 21978523, checked in by Sebastian Huber <sebastian.huber@…>, on 04/23/18 at 11:31:18

bsps/lm32: Move shared drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 5.0 KB
Line 
1/*  flash.c
2 *
3 *  Milkymist flash driver for RTEMS
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.rtems.org/license/LICENSE.
8 *
9 *  COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq
10 */
11
12#define RTEMS_STATUS_CHECKS_USE_PRINTK
13
14#include <rtems.h>
15#include <stdio.h>
16#include <bsp.h>
17#include <string.h>
18#include <rtems/libio.h>
19#include <rtems/status-checks.h>
20#include "../include/system_conf.h"
21#include <bsp/milkymist_flash.h>
22
23static struct flash_partition partitions[FLASH_PARTITION_COUNT]
24  = FLASH_PARTITIONS;
25
26static rtems_id flash_lock;
27
28rtems_device_driver flash_initialize(
29  rtems_device_major_number major,
30  rtems_device_minor_number minor,
31  void *arg
32)
33{
34  rtems_status_code sc;
35  int i;
36  char devname[16];
37
38  for (i=0;i<FLASH_PARTITION_COUNT;i++) {
39    sprintf(devname, "/dev/flash%d", i+1);
40    sc = rtems_io_register_name(devname, major, i);
41    RTEMS_CHECK_SC(sc, "Create flash device");
42  }
43
44  sc = rtems_semaphore_create(
45    rtems_build_name('F', 'L', 'S', 'H'),
46    1,
47    RTEMS_SIMPLE_BINARY_SEMAPHORE,
48    0,
49    &flash_lock
50  );
51  RTEMS_CHECK_SC(sc, "create semaphore");
52
53  return RTEMS_SUCCESSFUL;
54}
55
56rtems_device_driver flash_read(
57  rtems_device_major_number major,
58  rtems_device_minor_number minor,
59  void *arg
60)
61{
62  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
63  void *startaddr;
64  int len;
65
66  if (minor >= FLASH_PARTITION_COUNT)
67    return RTEMS_UNSATISFIED;
68
69  startaddr = (void *)(partitions[minor].start_address
70    + (unsigned int)rw_args->offset);
71  len = partitions[minor].length - rw_args->offset;
72  if (len > rw_args->count)
73    len = rw_args->count;
74  if (len <= 0) {
75    rw_args->bytes_moved = 0;
76    return RTEMS_SUCCESSFUL;
77  }
78 
79  rtems_semaphore_obtain(flash_lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
80  memcpy(rw_args->buffer, startaddr, len);
81  rtems_semaphore_release(flash_lock);
82
83  rw_args->bytes_moved = len;
84  return RTEMS_SUCCESSFUL;
85}
86
87rtems_device_driver flash_write(
88  rtems_device_major_number major,
89  rtems_device_minor_number minor,
90  void *arg
91)
92{
93  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
94  volatile unsigned short *startaddr;
95  unsigned short *srcdata;
96  int len;
97  int this_time;
98  int remaining;
99  int i;
100
101  if (minor >= FLASH_PARTITION_COUNT)
102    return RTEMS_UNSATISFIED;
103
104  startaddr = (unsigned short *)(partitions[minor].start_address
105    + (unsigned int)rw_args->offset);
106  len = partitions[minor].length - rw_args->offset;
107  if (len > rw_args->count)
108    len = rw_args->count;
109  if (len <= 2) {
110    rw_args->bytes_moved = 0;
111    return RTEMS_SUCCESSFUL;
112  }
113  len /= 2;
114  srcdata = (unsigned short *)rw_args->buffer;
115  remaining = len;
116
117  rtems_semaphore_obtain(flash_lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
118  while (remaining > 0) {
119    this_time = remaining;
120    if (this_time > 256)
121      this_time = 256;
122    /* Issue "Buffered Programming Setup" command
123     * and wait for buffer available.
124     */
125    do {
126      *startaddr = 0x00e8;
127    } while (!(*startaddr & 0x0080));
128    /* Load word count */
129    *startaddr = this_time-1;
130    /* Fill buffer */
131    for(i=0;i<this_time;i++)
132      startaddr[i] = srcdata[i];
133    /* Issue "Buffer Programming Confirm" command */
134    *startaddr = 0x00d0;
135    while (!(*startaddr & 0x0080)); /* read status register, wait for ready */
136    *startaddr = 0x0050; /* clear status register */
137    /* update state */
138    startaddr += this_time;
139    srcdata += this_time;
140    remaining -= this_time;
141  }
142  *startaddr = 0x00ff; /* back to read array mode */
143  rtems_semaphore_release(flash_lock);
144
145  rw_args->bytes_moved = 2*len;
146  return RTEMS_SUCCESSFUL;
147}
148
149rtems_device_driver flash_control(
150  rtems_device_major_number major,
151  rtems_device_minor_number minor,
152  void *arg
153)
154{
155  rtems_libio_ioctl_args_t *args = arg;
156  unsigned int eraseaddr_i;
157  volatile unsigned short *eraseaddr;
158
159  if (minor >= FLASH_PARTITION_COUNT) {
160    args->ioctl_return = -1;
161    return RTEMS_UNSATISFIED;
162  }
163
164  switch (args->command) {
165    case FLASH_GET_SIZE:
166      *((unsigned int *)args->buffer) = partitions[minor].length;
167      break;
168    case FLASH_GET_BLOCKSIZE:
169      *((unsigned int *)args->buffer) = 128*1024;
170      break;
171    case FLASH_ERASE_BLOCK:
172      eraseaddr_i = (unsigned int)args->buffer;
173      if (eraseaddr_i >= partitions[minor].length) {
174        args->ioctl_return = -1;
175        return RTEMS_UNSATISFIED;
176      }
177      eraseaddr_i = eraseaddr_i + partitions[minor].start_address;
178      eraseaddr = (unsigned short *)eraseaddr_i;
179      rtems_semaphore_obtain(flash_lock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
180      *eraseaddr = 0x0020; /* erase */
181      *eraseaddr = 0x00d0;
182      while(!(*eraseaddr & 0x0080)); /* read status register, wait for ready */
183      *eraseaddr = 0x0050; /* clear status register */
184      *eraseaddr = 0x00ff; /* back to read array mode */
185      rtems_semaphore_release(flash_lock);
186      break;
187    default:
188      args->ioctl_return = -1;
189      return RTEMS_UNSATISFIED;
190  }
191  args->ioctl_return = 0;
192  return RTEMS_SUCCESSFUL;
193}
Note: See TracBrowser for help on using the repository browser.