Skip to content

Commit

Permalink
arch/risc-v/src/mpfs: Generate an unique locally administrated MAC ad…
Browse files Browse the repository at this point in the history
…dress

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 <[email protected]>
  • Loading branch information
jlaitine committed Sep 5, 2023
1 parent d4720bf commit b08c6da
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 2 deletions.
2 changes: 1 addition & 1 deletion arch/risc-v/src/mpfs/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
154 changes: 154 additions & 0 deletions arch/risc-v/src/mpfs/mpfs_dsn.c
Original file line number Diff line number Diff line change
@@ -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 100

/****************************************************************************
* 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, -1 on error
*
****************************************************************************/

size_t 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-- > 0);

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-- > 0);

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;
}
81 changes: 81 additions & 0 deletions arch/risc-v/src/mpfs/mpfs_dsn.h
Original file line number Diff line number Diff line change
@@ -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
*
****************************************************************************/

size_t mpfs_read_dsn(uint8_t *dsn, size_t len);

#ifdef __cplusplus
}
#endif
#undef EXTERN

#endif /* __ASSEMBLY__ */
#endif /* __ARCH_RISCV_SRC_MPFS_MPFS_DSN_H */
13 changes: 12 additions & 1 deletion arch/risc-v/src/mpfs/mpfs_ethernet.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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
Expand Down

0 comments on commit b08c6da

Please sign in to comment.