diff options
Diffstat (limited to 'bsps/lm32/shared/milkymist_versions/versions.c')
-rw-r--r-- | bsps/lm32/shared/milkymist_versions/versions.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/bsps/lm32/shared/milkymist_versions/versions.c b/bsps/lm32/shared/milkymist_versions/versions.c new file mode 100644 index 0000000000..84b2b5d2fb --- /dev/null +++ b/bsps/lm32/shared/milkymist_versions/versions.c @@ -0,0 +1,132 @@ +/* versions.c + * + * Milkymist versioning driver for RTEMS + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * COPYRIGHT (c) 2010, 2011 Sebastien Bourdeauducq + */ + +#define RTEMS_STATUS_CHECKS_USE_PRINTK + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <rtems.h> +#include <rtems/status-checks.h> +#include <bsp.h> +#include <rtems/libio.h> +#include "../include/system_conf.h" +#include <bsp/milkymist_versions.h> + +#define SOC_DEVICE_NAME "/dev/soc" +#define PCB_DEVICE_NAME "/dev/pcb" +#define PCBREV_DEVICE_NAME "/dev/pcb_rev" + +rtems_device_driver versions_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code sc; + + sc = rtems_io_register_name(SOC_DEVICE_NAME, major, 0); + RTEMS_CHECK_SC(sc, "create SoC version device"); + sc = rtems_io_register_name(PCB_DEVICE_NAME, major, 1); + RTEMS_CHECK_SC(sc, "create PCB type device"); + sc = rtems_io_register_name(PCBREV_DEVICE_NAME, major, 2); + RTEMS_CHECK_SC(sc, "create PCB revision device"); + + return RTEMS_SUCCESSFUL; +} + +static int get_soc_version(char *buffer) +{ + char fmt[13]; + char *version; + int len; + unsigned int id; + unsigned int major, minor, subminor, rc; + + id = MM_READ(MM_SYSTEM_ID); + major = (id & 0xf0000000) >> 28; + minor = (id & 0x0f000000) >> 24; + subminor = (id & 0x00f00000) >> 20; + rc = (id & 0x000f0000) >> 16; + + version = fmt; + version += sprintf(version, "%u.%u", major, minor); + if (subminor != 0) + version += sprintf(version, ".%u", subminor); + if (rc != 0) + version += sprintf(version, "RC%u", rc); + + len = version - fmt; + memcpy(buffer, fmt, len); + return len; +} + +static int get_pcb_type(char *buffer) +{ + unsigned int id; + + id = MM_READ(MM_SYSTEM_ID); + buffer[0] = (id & 0x0000ff00) >> 8; + buffer[1] = id & 0x000000ff; + return 2; +} + +static int get_pcb_revision(char *buffer) +{ + unsigned int v; + + v = MM_READ(MM_GPIO_IN); + v = (v & 0x78) >> 3; + buffer[0] = '0' + v; + return 1; +} + +rtems_device_driver versions_read( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg; + + if(rw_args->offset != 0) { + rw_args->bytes_moved = 0; + return RTEMS_SUCCESSFUL; + } + + switch (minor) { + case 0: + if (rw_args->count < 12) { + rw_args->bytes_moved = 0; + return RTEMS_UNSATISFIED; + } + rw_args->bytes_moved = get_soc_version((char *)rw_args->buffer); + return RTEMS_SUCCESSFUL; + case 1: + if (rw_args->count < 2) { + rw_args->bytes_moved = 0; + return RTEMS_UNSATISFIED; + } + rw_args->bytes_moved = get_pcb_type((char *)rw_args->buffer); + return RTEMS_SUCCESSFUL; + case 2: + if (rw_args->count < 1) { + rw_args->bytes_moved = 0; + return RTEMS_UNSATISFIED; + } + rw_args->bytes_moved = get_pcb_revision((char *)rw_args->buffer); + return RTEMS_SUCCESSFUL; + } + + rw_args->bytes_moved = 0; + return RTEMS_UNSATISFIED; +} |