arch/risc-v/src/mpfs: Generate an unique locally administrated MAC address

Add a function to read PolarFire's serial number from system controller, and use the first five digits as device's mac address

Signed-off-by: Jukka Laitinen <jukkax@ssrc.tii.ae>
This commit is contained in:
Jukka Laitinen 2023-04-03 14:30:03 +03:00 committed by Xiang Xiao
parent ef18d2b599
commit b750f94896
4 changed files with 248 additions and 2 deletions

View File

@ -32,7 +32,7 @@ CHIP_CSRCS += mpfs_irq.c mpfs_irq_dispatch.c
CHIP_CSRCS += mpfs_lowputc.c mpfs_serial.c
CHIP_CSRCS += mpfs_start.c mpfs_timerisr.c
CHIP_CSRCS += mpfs_gpio.c mpfs_systemreset.c
CHIP_CSRCS += mpfs_plic.c
CHIP_CSRCS += mpfs_plic.c mpfs_dsn.c
ifeq ($(CONFIG_MPFS_DMA),y)
CHIP_CSRCS += mpfs_dma.c

View File

@ -0,0 +1,154 @@
/****************************************************************************
* arch/risc-v/src/mpfs/mpfs_dsn.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <errno.h>
#include <unistd.h>
#include "mpfs_dsn.h"
#include "riscv_internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define MPFS_SCBCTRL_BASE 0x37020000ul
#define SERVICES_CR_OFFSET 0x50
#define SERVICES_SR_OFFSET 0x54
#define SERVICES_CR (MPFS_SCBCTRL_BASE + SERVICES_CR_OFFSET)
#define SERVICES_SR (MPFS_SCBCTRL_BASE + SERVICES_SR_OFFSET)
/* Command bits */
#define SCBCTRL_SERVICESCR_REQ (1 << 0)
/* Status bits */
#define SCBCTRL_SERVICESSR_BUSY (1 << 1)
/* 2kB long mailbox. */
#define MSS_SCBMAILBOX 0x37020800ul
/* Retry count */
#define RETRIES 500
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mpfs_read_dsn
*
* Description:
* Read n bytes of the device serial number. Full serial number is 16 bytes
*
* Parameters:
* dsn - A pointer to the destination buffer
* len - Number of bytes to read
*
* Returned Value:
* Number of bytes read, -ETIMEDOUT on error
*
****************************************************************************/
int mpfs_read_dsn(uint8_t *dsn, size_t len)
{
uint32_t reg;
uint8_t *p = (uint8_t *)MSS_SCBMAILBOX;
irqstate_t flags = enter_critical_section();
unsigned retries = RETRIES;
/* Wait until the system controller is not busy.
* Read the SN inside critical section, just in case someone else is
* using the system controller services
*/
while ((getreg32(SERVICES_SR) & SCBCTRL_SERVICESSR_BUSY) && --retries > 0)
{
leave_critical_section(flags);
usleep(1000);
flags = enter_critical_section();
}
if (retries == 0)
{
goto out;
}
/* Read at max MPFS_DSN_LENGTH bytes, set the rest to 0 */
if (len > MPFS_DSN_LENGTH)
{
len = MPFS_DSN_LENGTH;
}
/* Command: bits 0 to 6 is the opcode, bits 7 to 15 is the Mailbox
* offset. In this case, opcode == 0 and offset == 0.
*/
putreg32(SCBCTRL_SERVICESCR_REQ, SERVICES_CR);
/* Wait until the system controller has started processing the command */
retries = RETRIES;
do
{
reg = getreg32(SERVICES_CR);
}
while ((reg & SCBCTRL_SERVICESCR_REQ) && --retries);
if (retries == 0)
{
goto out;
}
/* Wait for the completion of the command */
retries = RETRIES;
do
{
reg = getreg32(SERVICES_SR);
}
while ((reg & SCBCTRL_SERVICESSR_BUSY) && --retries);
if (retries == 0)
{
goto out;
}
/* Read the bytes of serial from service mailbox */
for (uint8_t i = 0; i < len; i++)
{
dsn[i] = getreg8(p++);
}
out:
leave_critical_section(flags);
return retries > 0 ? len : -ETIMEDOUT;
}

View File

@ -0,0 +1,81 @@
/****************************************************************************
* arch/risc-v/src/mpfs/mpfs_dsn.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#ifndef __ARCH_RISCV_SRC_MPFS_MPFS_DSN_H
#define __ARCH_RISCV_SRC_MPFS_MPFS_DSN_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include <stddef.h>
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Pre-Processor Declarations
****************************************************************************/
/* This is the length of the serial number */
#define MPFS_DSN_LENGTH 16
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: mpfs_read_dsn
*
* Description:
* Read n bytes of the device serial number. Full serial number is 16 bytes
*
* Parameters:
* dsn - A pointer to the destination buffer
* len - Number of bytes to read
*
* Returned Value:
* Number of bytes read or negated errno
*
****************************************************************************/
int mpfs_read_dsn(uint8_t *dsn, size_t len);
#ifdef __cplusplus
}
#endif
#undef EXTERN
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_RISCV_SRC_MPFS_MPFS_DSN_H */

View File

@ -53,6 +53,7 @@
#include "riscv_internal.h"
#include "mpfs_memorymap.h"
#include "mpfs_ethernet.h"
#include "mpfs_dsn.h"
#if defined(CONFIG_NET) && defined(CONFIG_MPFS_ETHMAC)
@ -1482,7 +1483,7 @@ static int mpfs_ifup(struct net_driver_s *dev)
return ret;
}
/* Set the MAC address (should have been configured while we were down) */
/* Set the MAC address */
mpfs_macaddress(priv);
@ -3542,6 +3543,16 @@ int mpfs_ethinitialize(int intf)
priv->queue[2].dma_rxbuf_size = (uint32_t *)(base + DMA_RXBUF_SIZE_Q2);
priv->queue[3].dma_rxbuf_size = (uint32_t *)(base + DMA_RXBUF_SIZE_Q3);
/* Generate a locally administrated MAC address for this ethernet if */
/* Set first byte to 0x02 or 0x06 acc. to the intf */
priv->dev.d_mac.ether.ether_addr_octet[0] = 0x02 | ((intf & 1) << 2);
/* Read the next 5 bytes from the S/N */
mpfs_read_dsn(&priv->dev.d_mac.ether.ether_addr_octet[1], 5);
/* MPU hack for ETH DMA if not enabled by bootloader */
#ifdef CONFIG_MPFS_MPU_DMA_ENABLE