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

Last change on this file since 7ef0876 was 0332481, checked in by Joel Sherrill <joel.sherrill@…>, on 03/12/07 at 11:21:23

2007-03-12 Joel Sherrill <joel@…>

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