source: rtems/c/src/lib/libbsp/powerpc/gen5200/nvram/nvram.c @ ca680bc5

4.104.114.84.95
Last change on this file since ca680bc5 was ca680bc5, checked in by Ralf Corsepius <ralf.corsepius@…>, on 12/31/05 at 05:09:26

New (CVS import Thomas Doerfler <Thomas.Doerfler@…>'s
submission).

  • Property mode set to 100644
File size: 14.4 KB
Line 
1/*===============================================================*\
2| Project: RTEMS generic MPC5200 BSP                              |
3+-----------------------------------------------------------------+
4| File: nvram.c
5+-----------------------------------------------------------------+
6| Partially based on the code references which are named below.   |
7| Adaptions, modifications, enhancements and any recent parts of  |
8| the code are:                                                   |
9|                    Copyright (c) 2005                           |
10|                    Embedded Brains GmbH                         |
11|                    Obere Lagerstr. 30                           |
12|                    D-82178 Puchheim                             |
13|                    Germany                                      |
14|                    rtems@embedded-brains.de                     |
15+-----------------------------------------------------------------+
16| The license and distribution terms for this file may be         |
17| found in the file LICENSE in this distribution or at            |
18|                                                                 |
19| http://www.rtems.com/license/LICENSE.                           |
20|                                                                 |
21+-----------------------------------------------------------------+
22| this file contains the nvram functions                          |
23+-----------------------------------------------------------------+
24|   date                      history                        ID   |
25| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
26| 01.12.05  creation                                         doe  |
27|*****************************************************************|
28|*CVS information:                                                |
29|*(the following information is created automatically,            |
30|*do not edit here)                                               |
31|*****************************************************************|
32|* $Log$
33|* Revision 1.4  2005/12/09 08:57:03  thomas
34|* added/modifed file headers
35|*
36 *
37|*****************************************************************|
38\*===============================================================*/
39/***********************************************************************/
40/*                                                                     */
41/*   Module:       nvram.c                                             */
42/*   Date:         07/17/2003                                          */
43/*   Purpose:      RTEMS M93C64-based NV memory device driver          */
44/*                                                                     */
45/*---------------------------------------------------------------------*/
46/*                                                                     */
47/*   Description:  M93C46 is a serial microwire EEPROM which contains  */
48/*                 1Kbit (128 bytes/64 words) of non-volatile memory.  */
49/*                 The device can be coigured for byte- or word-       */
50/*                 access. The driver provides a file-like interface   */
51/*                 to this memory.                                     */
52/*                                                                     */
53/*                 MPC5x00 PIN settings:                               */
54/*                                                                     */
55/*                 PSC3_6 (output) -> MC93C46 serial data in    (D)    */
56/*                 PSC3_7 (input)  -> MC93C46 serial data out   (Q)    */
57/*                 PSC3_8 (output) -> MC93C46 chip select input (S)    */
58/*                 PSC3_9 (output) -> MC93C46 serial clock      (C)    */
59/*                                                                     */
60/*---------------------------------------------------------------------*/
61/*                                                                     */
62/*   Code                                                              */
63/*   References:   DS1307-based Non-Volatile memory device driver      */
64/*   Module:       nvram.c                                             */
65/*   Project:      RTEMS 4.6.0pre1 / MCF5206Elite BSP                  */
66/*   Version       1.2                                                 */
67/*   Date:         11/04/2002                                          */
68/*   Author:       Victor V. Vengerov                                  */
69/*   Copyright:    Copyright (C) 2000 OKTET Ltd.,St.-Petersburg,Russia */
70/*                                                                     */
71/*   The license and distribution terms for this file may be           */
72/*   found in the file LICENSE in this distribution or at              */
73/*   http://www.OARcorp.com/rtems/license.html.                        */
74/*                                                                     */
75/*---------------------------------------------------------------------*/
76/*                                                                     */
77/*   Partially based on the code references which are named above.     */
78/*   Adaptions, modifications, enhancements and any recent parts of    */
79/*   the code are under the right of                                   */
80/*                                                                     */
81/*         IPR Engineering, Dachauer Straße 38, D-80335 München        */
82/*                        Copyright(C) 2003                            */
83/*                                                                     */
84/*---------------------------------------------------------------------*/
85/*                                                                     */
86/*   IPR Engineering makes no representation or warranties with        */
87/*   respect to the performance of this computer program, and          */
88/*   specifically disclaims any responsibility for any damages,        */
89/*   special or consequential, connected with the use of this program. */
90/*                                                                     */
91/*---------------------------------------------------------------------*/
92/*                                                                     */
93/*   Version history:  1.0                                             */
94/*                                                                     */
95/***********************************************************************/
96
97#include <rtems.h>
98#include <rtems/libio.h>
99#include <errno.h>
100#include <string.h>
101/*#include "../include/bsp.h"*/
102#include "../include/bsp.h"
103#include "../include/mpc5200.h"
104/*#include "../nvram/nvram.h"*/
105#include "../nvram/nvram.h"
106#include "../nvram/m93cxx.h"
107#include <stdio.h>
108
109/*
110 * Simple usec delay function using lower half of HARPO Time Base Register
111 */
112void wait_usec(unsigned long usec)
113  {
114  unsigned long start_count = 0, update_count;
115  unsigned long delay_count;
116
117  if(TMBASE_CLOCK < 1000000)
118    delay_count = (TMBASE_CLOCK * usec )/1000000;
119  else
120    delay_count = (TMBASE_CLOCK / 1000000) * usec;
121
122  TBL_READ(start_count);
123
124  update_count = start_count;
125
126  while((update_count - start_count) < delay_count)
127    TBL_READ(update_count);
128
129  }
130
131
132/*
133 * Enable M93Cxx chip-write
134 */
135static void m93cxx_enable_write()
136  {
137  uint32_t header, i;
138
139  ENABLE_CHIP_SELECT;
140
141  WAIT(1);
142
143  header = M93C46_EWEN;
144
145  for(i = 0; i < M93C46_CLOCK_CYCLES; i++)
146        {
147
148        MASK_HEAD_SHIFT(header);
149
150        WAIT(1);
151
152        DO_CLOCK_CYCLE;
153
154        WAIT(1);
155
156        }
157
158  DISABLE_CHIP_SELECT;
159
160  return;
161
162  }
163
164
165/*
166 * Disable M93Cxx chip-write
167 */
168static void m93cxx_disable_write()
169  {
170  uint32_t header, i;
171
172  ENABLE_CHIP_SELECT;
173
174  WAIT(1);
175
176  header = M93C46_EWDS;
177
178  for(i = 0; i < M93C46_CLOCK_CYCLES; i++)
179        {
180
181        MASK_HEAD_SHIFT(header);
182
183        WAIT(1);
184
185        DO_CLOCK_CYCLE;
186
187        WAIT(1);
188
189        }
190
191  DISABLE_CHIP_SELECT;
192
193  return;
194
195  }
196
197
198/*
199 * Read one byte from specified offset
200 */
201static uint8_t m93cxx_read_byte(uint32_t offset)
202  {
203  uint8_t byte2read;
204  uint32_t header, tmp_offset, i;
205#ifdef M93CXX_MODE_BYTE
206  uint8_t byte_recv = 0;
207#else
208        uint32_t word_recv = 0;
209#endif
210
211  ENABLE_CHIP_SELECT;
212
213  WAIT(1);
214
215#ifdef M93CXX_MODE_BYTE
216
217  header = M93C46_READ(offset);
218
219  for(i = 0; i < M93C46_CLOCK_CYCLES; i++)
220        {
221
222        MASK_HEAD_SHIFT(header);
223
224        WAIT(1);
225
226        DO_CLOCK_CYCLE;
227
228        WAIT(1);
229
230        }
231
232  for(i = 0; i < 8; i++)
233        {
234
235    WAIT(1);
236
237    DO_CLOCK_CYCLE;
238
239    WAIT(1);
240
241    GET_DATA_BYTE_SHIFT(byte_recv);
242
243    }
244
245  byte_recv >>= 1;
246
247  byte2read = byte_recv;
248
249#else
250  tmp_offset = offset/2;
251
252  header = M93C46_READ(tmp_offset);
253
254  for(i = 0; i < M93C46_CLOCK_CYCLES; i++)
255    {
256
257    MASK_HEAD_SHIFT(header);
258
259    WAIT(1);
260
261    DO_CLOCK_CYCLE;
262
263    WAIT(1);
264
265    }
266
267  for(i = 0; i < 16; i++)
268    {
269
270    DO_CLOCK_CYCLE;
271
272    WAIT(1);
273
274    GET_DATA_WORD_SHIFT(word_recv);
275
276    WAIT(1);
277
278    }
279
280  word_recv >>= 1;
281
282  if(offset%2)
283        {
284
285        byte2read = (uint8_t)((word_recv & 0xFF00) >> 8);
286
287#ifdef NVRAM_DEBUG
288        printf("\nbyte_read(o) = %x", byte2read);
289#endif
290
291        }
292  else
293        {
294
295        byte2read = (uint8_t)(word_recv & 0x00FF);
296
297#ifdef NVRAM_DEBUG
298        printf("\nbyte_read(e) = %x", byte2read);
299#endif
300        }
301
302#endif
303
304  WAIT(1);
305
306  DISABLE_CHIP_SELECT;
307
308  return byte2read;
309
310  }
311
312
313/*
314 * Write one byte to specified offset
315 */
316void m93cxx_write_byte(uint32_t offset, uint8_t byte2write)
317  {
318  uint32_t header, tmp_offset, i;
319#ifdef M93CXX_MODE_BYTE
320  uint8_t byte_send;
321#else
322  uint16_t word_send;
323#endif
324
325  ENABLE_CHIP_SELECT;
326
327  WAIT(1);
328
329#ifdef M93CXX_MODE_BYTE
330  header = M93C46_WRITE(offset);
331
332  for(i = 0; i < M93C46_CLOCK_CYCLES; i++)
333        {
334
335        MASK_HEAD_SHIFT(header);
336
337        WAIT(1);
338
339        DO_CLOCK_CYCLE;
340
341        WAIT(1);
342
343        }
344
345  byte_send = byte2write;
346
347  for(i = 0; i < 8; i++)
348        {
349
350        SET_DATA_BYTE_SHIFT(byte_send);
351
352        WAIT(1);
353
354        DO_CLOCK_CYCLE;
355
356        WAIT(1);
357
358        }
359
360  }
361#else
362
363  if(offset%2)
364        {
365
366        word_send  = (uint16_t)m93cxx_read_byte(offset-1);
367        word_send |= (uint16_t)(m93cxx_read_byte(offset) << 8);
368
369        }
370  else
371        {
372
373        word_send  = (uint16_t)m93cxx_read_byte(offset);
374        word_send |= (uint16_t)(m93cxx_read_byte(offset + 1) << 8);
375
376        }
377
378  tmp_offset = offset/2;
379
380  WAIT(1);
381
382  ENABLE_CHIP_SELECT;
383
384  WAIT(1);
385
386  header = M93C46_WRITE(tmp_offset);
387
388  for(i = 0; i < M93C46_CLOCK_CYCLES; i++)
389        {
390
391        MASK_HEAD_SHIFT(header);
392
393        WAIT(1);
394
395        DO_CLOCK_CYCLE;
396
397        WAIT(1);
398
399        }
400
401  if(offset%2)
402        {
403
404        word_send  = (word_send & 0x00FF) | ((uint16_t)(byte2write << 8));
405
406#ifdef NVRAM_DEBUG
407        printf("\nword_send = %x", word_send);
408#endif
409
410        }
411  else
412        {
413
414        word_send  = (word_send & 0xFF00) | (uint16_t)byte2write;
415#ifdef NVRAM_DEBUG
416        printf("\nword_send = %x", word_send);
417#endif
418
419        }
420
421  for(i = 0; i < 16; i++)
422        {
423
424        SET_DATA_WORD_SHIFT(word_send);
425
426        WAIT(1);
427
428        DO_CLOCK_CYCLE;
429
430        WAIT(1);
431
432        }
433
434  DISABLE_CHIP_SELECT;
435
436  WAIT(1);
437
438  ENABLE_CHIP_SELECT;
439
440  WAIT(1);
441
442  CHECK_WRITE_BUSY;
443
444#endif
445
446  WAIT(1);
447
448  DISABLE_CHIP_SELECT;
449
450  return;
451
452  }
453
454
455/* nvram_driver_initialize --
456 *     Non-volatile memory device driver initialization.
457 */
458rtems_device_driver nvram_driver_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
459  {
460  rtems_status_code sc;
461
462  /* enable PSC3_6/PSC3_7 as general purpose pins */
463  mpc5200.gpiosen |= (GPIO_PSC3_6 | GPIO_PSC3_7);
464
465  /* PSC3_6/PSC3_7 has normal CMOS output */
466  mpc5200.gpiosod &= ~(GPIO_PSC3_6 | GPIO_PSC3_7);
467
468  /* switch PSC3_6 (MC93C46 serial data in (D)) to low */
469  mpc5200.gpiosdo &= ~GPIO_PSC3_6;
470
471  /* PSC3_6 is an output (MC93C46 serial data in (D)) and PSC3_7 (MC93C46 serial data out (Q)) is an input pin */
472  mpc5200.gpiosdd |= GPIO_PSC3_6;
473  mpc5200.gpiosdd &= ~GPIO_PSC3_7;
474
475  /* disable PSC3_8 interrupt capabilities */
476  mpc5200.gpiosiie &= ~GPIO_PSC3_8;
477
478  /* enable PSC3_8 as general purpose pin */
479  mpc5200.gpiosie |= GPIO_PSC3_8;
480
481  /* PSC3_8 has normal CMOS output */
482  mpc5200.gpiosiod &= ~GPIO_PSC3_8;
483
484  /* switch PSC3_8 (MC93C46 chip select input (S)) to low (high activ) */
485  mpc5200.gpiosido &= ~GPIO_PSC3_8;
486
487  /* PSC3_8 is an output (MC93C46 chip select input (S)) pin */
488  mpc5200.gpiosidd |= GPIO_PSC3_8;
489
490  /* disable PSC3_9 interrupt capabilities */
491  mpc5200.gpiowue &= ~GPIO_PSC3_9;
492
493  /* enable PSC3_9 as general purpose pins */
494  mpc5200.gpiowe |= GPIO_PSC3_9;
495
496  /* PSC3_9 has normal CMOS output */
497  mpc5200.gpiowod &= ~GPIO_PSC3_9;
498
499  /* switch PSC3_9 (MC93C46 serial clock (C)) to low */
500  mpc5200.gpiowdo &= ~GPIO_PSC3_9;
501
502  /* PSC3_9 is an output (MC93C46 serial clock (C)) pin */
503  mpc5200.gpiowdd |= GPIO_PSC3_9;
504
505  sc = rtems_io_register_name("/dev/nvram", major, 0);
506
507  if(sc != RTEMS_SUCCESSFUL)
508        {
509
510        errno = EIO;
511        /*errno = ENODEV;*/
512        return RTEMS_UNSATISFIED;
513
514        }
515  else
516        return RTEMS_SUCCESSFUL;
517
518  }
519
520
521/* nvram_driver_open --
522 *     Non-volatile memory device driver open primitive.
523 */
524rtems_device_driver nvram_driver_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
525  {
526
527  return RTEMS_SUCCESSFUL;
528
529  }
530
531
532/* nvram_driver_close --
533 *     Non-volatile memory device driver close primitive.
534 */
535rtems_device_driver nvram_driver_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
536  {
537
538  return RTEMS_SUCCESSFUL;
539
540  }
541
542
543/* nvram_driver_read --
544 *     Non-volatile memory device driver read primitive.
545 */
546rtems_device_driver nvram_driver_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
547  {
548  rtems_libio_rw_args_t *args = arg;
549  uint32_t count, i;
550
551#ifdef NVRAM_DEBUG
552  printf("\nread count  = %2x", (int)(args->count));
553  printf("\nread offset = %2x", (int)(args->offset));
554#endif
555
556  if((args->offset >= M93C46_NVRAM_SIZE) || (args->offset + args->count > M93C46_NVRAM_SIZE))
557    {
558
559    args->bytes_moved = 0;
560    errno = EINVAL;
561    return RTEMS_UNSATISFIED;
562
563    }
564  else
565    count = args->count;
566
567  for(i = 0; i < count; i++)
568    {
569
570    (args->buffer)[i] = m93cxx_read_byte((args->offset) + i);
571    (args->bytes_moved) += 1;
572
573    }
574
575  return RTEMS_SUCCESSFUL;
576
577  }
578
579
580/* nvram_driver_write --
581 *     Non-volatile memory device driver write primitive.
582 */
583rtems_device_driver nvram_driver_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
584  {
585  rtems_libio_rw_args_t *args = arg;
586  uint32_t count, i;
587
588#ifdef NVRAM_DEBUG
589  printf("\nwrite count  = %2x", (int)(args->count));
590  printf("\nwrite offset = %2x", (int)(args->offset));
591#endif
592
593  if((args->offset >= M93C46_NVRAM_SIZE) || (args->offset + args->count > M93C46_NVRAM_SIZE))
594    {
595
596    args->bytes_moved = 0;
597    errno = EINVAL;
598    return RTEMS_UNSATISFIED;
599
600    }
601  else
602    count = args->count;
603
604    m93cxx_enable_write();
605
606    WAIT(1);
607
608  for(i = 0; i < count; i++)
609    {
610
611    m93cxx_write_byte((args->offset) + i, (args->buffer)[i]);
612    (args->bytes_moved) += 1;
613
614    }
615
616  WAIT(1);
617
618  m93cxx_disable_write();
619
620  return RTEMS_SUCCESSFUL;
621
622  }
Note: See TracBrowser for help on using the repository browser.