uboot/board/v38b/ethaddr.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2006
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <mpc5xxx.h>
  10
  11/* For the V38B board the pin is GPIO_PSC_6 */
  12#define GPIO_PIN        GPIO_PSC6_0
  13
  14#define NO_ERROR        0
  15#define ERR_NO_NUMBER   1
  16#define ERR_BAD_NUMBER  2
  17
  18static int is_high(void);
  19static int check_device(void);
  20static void io_out(int value);
  21static void io_input(void);
  22static void io_output(void);
  23static void init_gpio(void);
  24static void read_byte(unsigned char *data);
  25static void write_byte(unsigned char command);
  26
  27void read_2501_memory(unsigned char *psernum, unsigned char *perr);
  28void board_get_enetaddr(uchar *enetaddr);
  29
  30
  31static int is_high()
  32{
  33        return (*((vu_long *) MPC5XXX_WU_GPIO_DATA_I) & GPIO_PIN);
  34}
  35
  36static void io_out(int value)
  37{
  38        if (value)
  39                *((vu_long *) MPC5XXX_WU_GPIO_DATA_O) |= GPIO_PIN;
  40        else
  41                *((vu_long *) MPC5XXX_WU_GPIO_DATA_O) &= ~GPIO_PIN;
  42}
  43
  44static void io_input()
  45{
  46        *((vu_long *) MPC5XXX_WU_GPIO_DIR) &= ~GPIO_PIN;
  47        udelay(3);      /* allow input to settle */
  48}
  49
  50static void io_output()
  51{
  52        *((vu_long *) MPC5XXX_WU_GPIO_DIR) |= GPIO_PIN;
  53}
  54
  55static void init_gpio()
  56{
  57        *((vu_long *) MPC5XXX_WU_GPIO_ENABLE) |= GPIO_PIN;      /* Enable appropriate pin */
  58}
  59
  60void read_2501_memory(unsigned char *psernum, unsigned char *perr)
  61{
  62#define NBYTES 28
  63        unsigned char crcval, i;
  64        unsigned char buf[NBYTES];
  65
  66        *perr = 0;
  67        crcval = 0;
  68
  69        for (i = 0; i < NBYTES; i++)
  70                buf[i] = 0;
  71
  72        if (!check_device())
  73                *perr = ERR_NO_NUMBER;
  74        else {
  75                *perr = NO_ERROR;
  76                write_byte(0xCC);               /* skip ROM (0xCC) */
  77                write_byte(0xF0);               /* Read memory command 0xF0 */
  78                write_byte(0x00);               /* Address TA1=0, TA2=0 */
  79                write_byte(0x00);
  80                read_byte(&crcval);             /* Read CRC of address and command */
  81
  82                for (i = 0; i < NBYTES; i++)
  83                        read_byte(&buf[i]);
  84        }
  85        if (strncmp((const char *) &buf[11], "MAREL IEEE 802.3", 16)) {
  86                *perr = ERR_BAD_NUMBER;
  87                psernum[0] = 0x00;
  88                psernum[1] = 0xE0;
  89                psernum[2] = 0xEE;
  90                psernum[3] = 0xFF;
  91                psernum[4] = 0xFF;
  92                psernum[5] = 0xFF;
  93        } else {
  94                psernum[0] = 0x00;
  95                psernum[1] = 0xE0;
  96                psernum[2] = 0xEE;
  97                psernum[3] = buf[7];
  98                psernum[4] = buf[6];
  99                psernum[5] = buf[5];
 100        }
 101}
 102
 103static int check_device()
 104{
 105        int found;
 106
 107        io_output();
 108        io_out(0);
 109        udelay(500);  /* must be at least 480 us low pulse */
 110
 111        io_input();
 112        udelay(60);
 113
 114        found = (is_high() == 0) ? 1 : 0;
 115        udelay(500);  /* must be at least 480 us low pulse */
 116
 117        return found;
 118}
 119
 120static void write_byte(unsigned char command)
 121{
 122        char i;
 123
 124        for (i = 0; i < 8; i++) {
 125                /* 1 us to 15 us low pulse starts bit slot */
 126                /* Start with high pulse for 3 us */
 127                io_input();
 128                udelay(3);
 129
 130                io_out(0);
 131                io_output();
 132                udelay(3);
 133
 134                if (command & 0x01) {
 135                        /* 60 us high for 1-bit */
 136                        io_input();
 137                        udelay(60);
 138                } else
 139                        /* 60 us low for 0-bit */
 140                        udelay(60);
 141                /*  Leave pin as input */
 142                io_input();
 143
 144                command = command >> 1;
 145        }
 146}
 147
 148static void read_byte(unsigned char *data)
 149{
 150        unsigned char i, rdat = 0;
 151
 152        for (i = 0; i < 8; i++) {
 153                /* read one bit from one-wire device */
 154
 155                /* 1 - 15 us low starts bit slot */
 156                io_out(0);
 157                io_output();
 158                udelay(0);
 159
 160                /* allow line to be pulled high */
 161                io_input();
 162
 163                /* delay 10 us */
 164                udelay(10);
 165
 166                /* now sample input status */
 167                if (is_high())
 168                        rdat = (rdat >> 1) | 0x80;
 169                else
 170                        rdat = rdat >> 1;
 171
 172                udelay(60);     /* at least 60 us */
 173        }
 174        /* copy the return value */
 175        *data = rdat;
 176}
 177
 178void board_get_enetaddr(uchar *enetaddr)
 179{
 180        unsigned char sn[6], err = NO_ERROR;
 181
 182        init_gpio();
 183
 184        read_2501_memory(sn, &err);
 185
 186        if (err == NO_ERROR) {
 187                sprintf((char *)enetaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
 188                                sn[0], sn[1], sn[2], sn[3], sn[4], sn[5]);
 189                printf("MAC address: %s\n", enetaddr);
 190                setenv("ethaddr", (char *)enetaddr);
 191        } else {
 192                sprintf((char *)enetaddr, "00:01:02:03:04:05");
 193                printf("Error reading MAC address.\n");
 194                printf("Setting default to %s\n", enetaddr);
 195                setenv("ethaddr", (char *)enetaddr);
 196        }
 197}
 198