From b750f94896587b99d8b0f2b19b468e59b252de4c Mon Sep 17 00:00:00 2001 From: Jukka Laitinen Date: Mon, 3 Apr 2023 14:30:03 +0300 Subject: [PATCH] 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 --- arch/risc-v/src/mpfs/Make.defs | 2 +- arch/risc-v/src/mpfs/mpfs_dsn.c | 154 +++++++++++++++++++++++++++ arch/risc-v/src/mpfs/mpfs_dsn.h | 81 ++++++++++++++ arch/risc-v/src/mpfs/mpfs_ethernet.c | 13 ++- 4 files changed, 248 insertions(+), 2 deletions(-) create mode 100644 arch/risc-v/src/mpfs/mpfs_dsn.c create mode 100644 arch/risc-v/src/mpfs/mpfs_dsn.h diff --git a/arch/risc-v/src/mpfs/Make.defs b/arch/risc-v/src/mpfs/Make.defs index a57c6164c3..b163e9fe66 100644 --- a/arch/risc-v/src/mpfs/Make.defs +++ b/arch/risc-v/src/mpfs/Make.defs @@ -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 diff --git a/arch/risc-v/src/mpfs/mpfs_dsn.c b/arch/risc-v/src/mpfs/mpfs_dsn.c new file mode 100644 index 0000000000..e745976253 --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_dsn.c @@ -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 +#include +#include +#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; +} diff --git a/arch/risc-v/src/mpfs/mpfs_dsn.h b/arch/risc-v/src/mpfs/mpfs_dsn.h new file mode 100644 index 0000000000..825d3019a4 --- /dev/null +++ b/arch/risc-v/src/mpfs/mpfs_dsn.h @@ -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 +#include + +#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 */ diff --git a/arch/risc-v/src/mpfs/mpfs_ethernet.c b/arch/risc-v/src/mpfs/mpfs_ethernet.c index ff01615ea9..816f6d8c62 100644 --- a/arch/risc-v/src/mpfs/mpfs_ethernet.c +++ b/arch/risc-v/src/mpfs/mpfs_ethernet.c @@ -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