uboot/board/atmel/common/mac-spi-nor.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2019 Microchip Technology Inc. and its subsidiaries
   4 *
   5 * Author: Tudor Ambarus <tudor.ambarus@microchip.com>
   6 */
   7
   8#include <common.h>
   9#include <dm.h>
  10#include <env.h>
  11#include <net.h>
  12#include <linux/mtd/spi-nor.h>
  13#include <netdev.h>
  14
  15#define ETH_ADDR_SIZE                   6
  16
  17#ifdef CONFIG_SPI_FLASH_SST
  18#define SFDP_MICROCHIP_MANUF_ID         0xbf
  19#define SFDP_MICROCHIP_MEM_TYPE         0x26
  20#define SFDP_MICROCHIP_DEV_ID           0x43
  21
  22#define SFDP_MICROCHIP_EUI_OFFSET       0x60
  23#define SFDP_MICROCHIP_EUI48            0x30
  24
  25struct sst26vf064beui {
  26        u8 manufacturer_id;
  27        u8 memory_type;
  28        u8 device_id;
  29        u8 reserved;
  30};
  31
  32/**
  33 * sst26vf064beui_check() - Check the validity of the EUI-48 information from
  34 * the sst26vf064beui SPI NOR Microchip SFDP table.
  35 * @manufacturer_sfdp:  pointer to the Microchip manufacturer specific SFDP
  36 *                      table.
  37 *
  38 * Return: 0 on success, -errno otherwise.
  39 */
  40static int sst26vf064beui_check(const u8 *manufacturer_sfdp)
  41{
  42        struct sst26vf064beui *sst26vf064beui =
  43                (struct sst26vf064beui *)manufacturer_sfdp;
  44
  45        if (sst26vf064beui->manufacturer_id != SFDP_MICROCHIP_MANUF_ID)
  46                return -EINVAL;
  47
  48        if (sst26vf064beui->memory_type != SFDP_MICROCHIP_MEM_TYPE)
  49                return -EINVAL;
  50
  51        if (sst26vf064beui->device_id != SFDP_MICROCHIP_DEV_ID)
  52                return -EINVAL;
  53
  54        /*
  55         * Check if the EUI-48 MAC address is programmed in the next six address
  56         * locations.
  57         */
  58        if (manufacturer_sfdp[SFDP_MICROCHIP_EUI_OFFSET] !=
  59            SFDP_MICROCHIP_EUI48)
  60                return -EINVAL;
  61
  62        return 0;
  63}
  64
  65/**
  66 * sst26vf064beui_get_ethaddr() - Get the ethernet address from the
  67 * sst26vf064beui SPI NOR Microchip SFDP table.
  68 * @manufacturer_sfdp:  pointer to the Microchip manufacturer specific SFDP
  69 *                      table.
  70 * @ethaddr:            pointer where to fill the ethernet address
  71 * @size:               size of the ethernet address.
  72 *
  73 * Return: 0 on success, -errno otherwise.
  74 */
  75static int sst26vf064beui_get_ethaddr(const u8 *manufacturer_sfdp,
  76                                      u8 *ethaddr, size_t size)
  77{
  78        u64 eui_table[2];
  79        u64 *p = (u64 *)&manufacturer_sfdp[SFDP_MICROCHIP_EUI_OFFSET];
  80        int i, ret;
  81
  82        ret = sst26vf064beui_check(manufacturer_sfdp);
  83        if (ret)
  84                return ret;
  85
  86        for (i = 0; i < 2; i++)
  87                eui_table[i] = le64_to_cpu(p[i]);
  88
  89        /* Ethaddr starts at offset one. */
  90        memcpy(ethaddr, &((u8 *)eui_table)[1], size);
  91
  92        return 0;
  93}
  94#endif
  95
  96/**
  97 * at91_spi_nor_set_ethaddr() - Retrieve and set the ethernet address from the
  98 * SPI NOR manufacturer specific SFDP table.
  99 */
 100void at91_spi_nor_set_ethaddr(void)
 101{
 102        struct udevice *dev;
 103        struct spi_nor *nor;
 104        const char *ethaddr_name = "ethaddr";
 105        u8 ethaddr[ETH_ADDR_SIZE] = {0};
 106
 107        if (env_get(ethaddr_name))
 108                return;
 109
 110        if (uclass_first_device_err(UCLASS_SPI_FLASH, &dev))
 111                return;
 112
 113        nor = dev_get_uclass_priv(dev);
 114        if (!nor)
 115                return;
 116
 117        if (!nor->manufacturer_sfdp)
 118                return;
 119
 120#ifdef CONFIG_SPI_FLASH_SST
 121        if (sst26vf064beui_get_ethaddr(nor->manufacturer_sfdp, ethaddr,
 122                                       ETH_ADDR_SIZE))
 123                return;
 124#endif
 125
 126        if (is_valid_ethaddr(ethaddr))
 127                eth_env_set_enetaddr(ethaddr_name, ethaddr);
 128}
 129