diff --git a/arch/arm/src/common/ameba/Kconfig b/arch/arm/src/common/ameba/Kconfig index d34a65e2b6d..e2b6fa06fc1 100644 --- a/arch/arm/src/common/ameba/Kconfig +++ b/arch/arm/src/common/ameba/Kconfig @@ -61,9 +61,10 @@ config AMEBA_I2C select I2C select I2C_DRIVER ---help--- - Expose the Ameba I2C controllers (I2C0/I2C1) as NuttX I2C master - buses at /dev/i2cN. The board selects which controller is used and - its SCL/SDA pads in its bring-up code. + Expose the Ameba I2C controllers as NuttX I2C master buses at + /dev/i2cN (two controllers on most parts, three on amebasmart). + The board selects which controller is used and its SCL/SDA pads in + its bring-up code. The driver (arch/arm/src/common/ameba/ameba_i2c.c) sits on the SDK fwlib register layer and drives the DesignWare I2C block in polling diff --git a/arch/arm/src/common/ameba/ameba_i2c.c b/arch/arm/src/common/ameba/ameba_i2c.c index 66ac13c3509..82b72668b44 100644 --- a/arch/arm/src/common/ameba/ameba_i2c.c +++ b/arch/arm/src/common/ameba/ameba_i2c.c @@ -172,6 +172,9 @@ struct ameba_i2c_dev_s uint8_t sdapin; /* SDA pad (AMEBA_PA()/AMEBA_PB() encoding) */ uint8_t sclfid; /* Pin mux function code for the SCL pad */ uint8_t sdafid; /* Pin mux function code for the SDA pad */ +#ifdef AMEBA_I2C_IPCLK_FN + uint32_t ipclk; /* I2C IP reference clock (Hz) */ +#endif mutex_t lock; /* Serializes bus access */ }; @@ -233,6 +236,12 @@ static const uint32_t g_i2c_clk[AMEBA_NI2C] = AMEBA_I2C_APBPERIPH_CLK; static const uint8_t g_i2c_sclfid[AMEBA_NI2C] = AMEBA_I2C_SCLFID; static const uint8_t g_i2c_sdafid[AMEBA_NI2C] = AMEBA_I2C_SDAFID; +/* A chip whose I2C_StructInit() does not already fill in a usable I2C IP + * reference clock supplies AMEBA_I2C_IPCLK_FN(bus) in its chip header; the + * value is resolved once per bus at registration time. See the note at + * AMEBA_I2C_IPCLK_FN in the per-chip ameba_i2c_chip.h. + */ + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -269,6 +278,14 @@ static void ameba_i2c_reconfigure(struct ameba_i2c_dev_s *priv, init.mstrestr = AMEBA_ENABLE; +#ifdef AMEBA_I2C_IPCLK_FN + /* Correct the IP reference clock that I2C_SetSpeed() divides down to the + * SCL high/low counts; on this chip I2C_StructInit() left a placeholder. + */ + + init.ipclk = priv->ipclk; +#endif + if (frequency <= I2C_SPEED_STANDARD) { init.spdmod = AMEBA_I2C_SS_MODE; @@ -585,6 +602,9 @@ int ameba_i2c_register(int bus, uint8_t sclpin, uint8_t sdapin) priv->sdapin = sdapin; priv->sclfid = g_i2c_sclfid[bus]; priv->sdafid = g_i2c_sdafid[bus]; +#ifdef AMEBA_I2C_IPCLK_FN + priv->ipclk = AMEBA_I2C_IPCLK_FN(bus); +#endif priv->address = 0xffff; nxmutex_init(&priv->lock); diff --git a/arch/arm/src/common/ameba/ameba_i2c.h b/arch/arm/src/common/ameba/ameba_i2c.h index 1c7435722f9..c071fba2637 100644 --- a/arch/arm/src/common/ameba/ameba_i2c.h +++ b/arch/arm/src/common/ameba/ameba_i2c.h @@ -43,6 +43,7 @@ #define AMEBA_I2C0 0 #define AMEBA_I2C1 1 +#define AMEBA_I2C2 2 /* amebasmart only */ /**************************************************************************** * Public Function Prototypes @@ -64,7 +65,8 @@ extern "C" * the NuttX I2C character driver at /dev/i2cN, where N is the bus number. * * Input Parameters: - * bus - The controller index, AMEBA_I2C0 or AMEBA_I2C1. Also used as + * bus - The controller index, AMEBA_I2C0 .. AMEBA_I2C2 depending on how + * many controllers the chip exposes (AMEBA_NI2C). Also used as * the /dev/i2cN minor number. * sclpin - The SCL pad, encoded with AMEBA_PA()/AMEBA_PB(). * sdapin - The SDA pad, encoded with AMEBA_PA()/AMEBA_PB(). diff --git a/arch/arm/src/rtl8730e/CMakeLists.txt b/arch/arm/src/rtl8730e/CMakeLists.txt index 4a44a81d8e8..1fd353d181b 100644 --- a/arch/arm/src/rtl8730e/CMakeLists.txt +++ b/arch/arm/src/rtl8730e/CMakeLists.txt @@ -75,6 +75,15 @@ if(CONFIG_AMEBA_UART) endif() endif() +if(CONFIG_AMEBA_I2C) + list(APPEND SRCS ${AMEBA_COMMON}/ameba_i2c.c) + if(NOT CONFIG_RTL8730E_FLASH_FS + AND NOT CONFIG_AMEBA_GPIO + AND NOT CONFIG_AMEBA_UART) + list(APPEND SRCS rtl8730e_flash_stubs.c) + endif() +endif() + target_include_directories(arch PRIVATE ${AMEBA_COMMON}) target_sources(arch PRIVATE ${SRCS}) @@ -162,6 +171,11 @@ if(CONFIG_RTL8730E_FLASH_FS OR CONFIG_RTL8730E_WIFI) list(APPEND AMEBA_FWLIB_SRCS ${AMEBA_SOC}/fwlib/ram_hp/ameba_uart.c) endif() + # The whole amebasmart I2C fwlib lives in RAM, not in lib_rom.a. + if(CONFIG_AMEBA_I2C) + list(APPEND AMEBA_FWLIB_SRCS ${AMEBA_SOC}/fwlib/ram_common/ameba_i2c.c) + endif() + # Silence SDK warnings, activate CA32 code paths. No -mcmse (ARMv7-A). set(AMEBA_FWLIB_INC -Wno-int-conversion @@ -199,13 +213,16 @@ set(AMEBA_EXTRA_LIBS) # Pinmux_Config, flash MTD primitives). if(CONFIG_AMEBA_GPIO OR CONFIG_AMEBA_UART + OR CONFIG_AMEBA_I2C OR CONFIG_RTL8730E_FLASH_FS) list(APPEND AMEBA_EXTRA_LIBS ${AMEBA_SOC}/project/${AMEBA_KM_PROJ}/lib/soc/lib_rom.a) endif() # fwlib archive linked whenever any driver needs its RAM-side tables/code. -if(CONFIG_RTL8730E_FLASH_FS OR CONFIG_AMEBA_UART) +if(CONFIG_RTL8730E_FLASH_FS + OR CONFIG_AMEBA_UART + OR CONFIG_AMEBA_I2C) list(APPEND AMEBA_EXTRA_LIBS ${AMEBA_FWLIB_A}) endif() diff --git a/arch/arm/src/rtl8730e/Make.defs b/arch/arm/src/rtl8730e/Make.defs index 7a20d2fff79..dc07873cfae 100644 --- a/arch/arm/src/rtl8730e/Make.defs +++ b/arch/arm/src/rtl8730e/Make.defs @@ -65,7 +65,7 @@ AMEBA_AP_SOC_LIB = $(TOPDIR)/arch/arm/src/common/ameba/ameba-rtos/component/soc/ # rtl8730e_flash_stubs.c supplies the RAM-side symbols that lib_rom.a objects # expect (DiagPrintfNano, irq_enable, Pinmux_Config, etc.). Compile them once # whenever any driver needing ROM is enabled. -ifneq ($(filter y,$(CONFIG_AMEBA_GPIO) $(CONFIG_AMEBA_UART) $(CONFIG_RTL8730E_FLASH_FS)),) +ifneq ($(filter y,$(CONFIG_AMEBA_GPIO) $(CONFIG_AMEBA_UART) $(CONFIG_AMEBA_I2C) $(CONFIG_RTL8730E_FLASH_FS)),) CHIP_CSRCS += rtl8730e_flash_stubs.c EXTRA_LIBS += $(AMEBA_AP_SOC_LIB)$(DELIM)lib_rom.a @@ -79,6 +79,10 @@ ifeq ($(CONFIG_AMEBA_UART),y) CHIP_CSRCS += ameba_uart.c endif +ifeq ($(CONFIG_AMEBA_I2C),y) +CHIP_CSRCS += ameba_i2c.c +endif + # WiFi (WHC host, CA32 side). ifeq ($(CONFIG_RTL8730E_WIFI),y) CHIP_CSRCS += rtl8730e_wifi_init.c @@ -108,8 +112,8 @@ CHIP_CSRCS += ameba_flash_mtd.c endif # fwlib archive is needed whenever any driver uses RAM-side SDK tables -# (flash MTD, UART, ...). Link it once for all such configs. -ifneq ($(filter y,$(CONFIG_RTL8730E_FLASH_FS) $(CONFIG_AMEBA_UART)),) +# (flash MTD, UART, I2C, ...). Link it once for all such configs. +ifneq ($(filter y,$(CONFIG_RTL8730E_FLASH_FS) $(CONFIG_AMEBA_UART) $(CONFIG_AMEBA_I2C)),) # Prebuilt staging area (within the board tree, gitignored). AMEBA_PREBUILT = $(BOARD_DIR)$(DELIM)prebuilt diff --git a/arch/arm/src/rtl8730e/ameba_board.mk b/arch/arm/src/rtl8730e/ameba_board.mk index 432ed8b0135..4c16aae1da1 100644 --- a/arch/arm/src/rtl8730e/ameba_board.mk +++ b/arch/arm/src/rtl8730e/ameba_board.mk @@ -74,6 +74,13 @@ ifeq ($(CONFIG_AMEBA_UART),y) AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_hp/ameba_uart.c endif +# The whole amebasmart I2C fwlib (I2C_StructInit/Init/MasterWrite/...) lives +# in ram_common/ameba_i2c.c, not in lib_rom.a, so it must be compiled into +# libameba_fwlib.a whenever I2C is enabled. +ifeq ($(CONFIG_AMEBA_I2C),y) +AMEBA_FWLIB_SRCS += $(AMEBA_SOC)/fwlib/ram_common/ameba_i2c.c +endif + # Include paths scoped to the fwlib compile only (never leaked to NuttX core). # -DCONFIG_ARM_CORE_CA32 activates the CA32 code paths in ameba_flash_ram.c. # No -mcmse (that is Cortex-M33 TrustZone; CA32 is ARMv7-A non-secure EL1). diff --git a/arch/arm/src/rtl8730e/ameba_i2c_chip.h b/arch/arm/src/rtl8730e/ameba_i2c_chip.h new file mode 100644 index 00000000000..e1eb69fd60a --- /dev/null +++ b/arch/arm/src/rtl8730e/ameba_i2c_chip.h @@ -0,0 +1,143 @@ +/**************************************************************************** + * arch/arm/src/rtl8730e/ameba_i2c_chip.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_RTL8730E_AMEBA_I2C_CHIP_H +#define __ARCH_ARM_SRC_RTL8730E_AMEBA_I2C_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Per-chip I2C wiring for RTL8730E (amebasmart CA32). The shared driver + * (arch/arm/src/common/ameba/ameba_i2c.c) includes this header to learn how + * many I2C controllers the chip exposes and, for each, its register base, + * peripheral-clock masks, pad-mux codes and IP clock. It also learns the + * chip's I2C_InitTypeDef layout through AMEBA_I2C_HAS_DMA_FIELDS. + * + * Sources: component/soc/amebasmart/fwlib/include/hal_platform.h (bases), + * sysreg_lsys.h (APBPeriph masks), ameba_pinmux.h (pad-mux code), + * ameba_i2c.h (I2C_InitTypeDef) and hal/src/i2c_api.c (IP clocks). + */ + +#define AMEBA_NI2C 3 + +/* I2C register bases. I2C0 lives in the LP (low-power) domain on the + * LP_APB bus; I2C1 and I2C2 are the HS (high-speed) controllers on APB4. + * These are the NON-secure aliases (the secure aliases I2C1_REG_BASE_S / + * I2C2_REG_BASE_S at 0x500ef000 / 0x500f0000 must not be used -- see the + * note in ameba_i2c.c); the LP I2C0 has no secure alias at all. + */ + +#define AMEBA_I2C_BASES \ + { 0x4200f000ul, 0x400ef000ul, 0x400f0000ul } + +/* APBPeriph_I2Cx (function) and APBPeriph_I2Cx_CLOCK masks. amebasmart + * encodes these in bit 25/26/27 with the group selector bit30 = 0, unlike + * the KM4-based Ameba parts which use (bit30 | bit10/11). Equal for the + * function and clock arguments on this chip, but kept as two lists because + * RCC_PeriphClockCmd() takes them as distinct arguments. + */ + +#define AMEBA_I2C_APBPERIPH \ + { ((uint32_t)1 << 25), \ + ((uint32_t)1 << 26), \ + ((uint32_t)1 << 27) } + +#define AMEBA_I2C_APBPERIPH_CLK \ + { ((uint32_t)1 << 25), \ + ((uint32_t)1 << 26), \ + ((uint32_t)1 << 27) } + +/* amebasmart has a single generic PINMUX_FUNCTION_I2C (7) shared by every + * I2C pad; there are no per-signal SCL/SDA crossbar codes as on the other + * Ameba parts, so both lists carry the same value for every controller. + */ + +#define AMEBA_I2C_SCLFID { 7, 7, 7 } /* PINMUX_FUNCTION_I2C */ +#define AMEBA_I2C_SDAFID { 7, 7, 7 } /* PINMUX_FUNCTION_I2C */ + +/* I2C IP (reference) clock in Hz, per controller. + * + * amebasmart needs this where the other Ameba parts do not. Elsewhere + * I2C_StructInit() fills in a correct I2C0_1_IPCLK (XTAL_ClkGet() on + * amebadplus/amebagreen2, PLL_GetHBUSClk() on amebalite, HPERI_ClkGet() on + * RTL8720F); the amebasmart one hardcodes a 10 MHz placeholder, so without + * an override I2C_SetSpeed() miscomputes the SCL high/low counts and the + * bus runs at the wrong rate. Chips that leave AMEBA_I2C_IPCLK undefined + * keep the fwlib default and are unaffected. + * + * The two HS controllers live on HS_AHB, which is NP_PLL (800 MHz) divided + * by REG_LSYS_CKD_GRP0.CKD_HBUS, so the rate is a board/PLL setting rather + * than a constant: this macro reads the divider instead of assuming it. + * (Measured on an EVB: CKD_HBUS = 8 -> div9 -> 88.9 MHz, while the SDK's + * own I2CCLK_TABLE in hal/src/i2c_api.c claims a flat 100 MHz and the + * register's reset value would give 80 MHz -- neither matches, which is + * why this is computed and not tabulated.) The LP-domain I2C0 is fed from + * a fixed 20 MHz and is not affected by CKD_HBUS. + */ + +#define AMEBA_I2C_NPPLL_HZ 800000000ul + +/* REG_LSYS_CKD_GRP0: SYSTEM_CTRL_BASE_LP (0x42008000) + 0x228. CKD_HBUS is + * bits 12-15 and encodes 7 -> div8, 8 -> div9, otherwise div(value + 1). + */ + +#define AMEBA_I2C_CKD_GRP0 (0x42008000ul + 0x228) +#define AMEBA_I2C_CKD_HBUS_SHIFT 12 +#define AMEBA_I2C_CKD_HBUS_MASK 0xfu + +/* Resolved at run time, per controller: AMEBA_I2C_IPCLK_FN(bus) is called + * once when a bus is registered. Controller 0 (LP domain) has a fixed + * 20 MHz reference; controllers 1 and 2 follow the HS_AHB divider. + */ + +static inline uint32_t ameba_i2c_ipclk(int bus) +{ + uint32_t div; + + if (bus == 0) + { + return 20000000ul; + } + + div = (*(volatile uint32_t *)AMEBA_I2C_CKD_GRP0 >> + AMEBA_I2C_CKD_HBUS_SHIFT) & AMEBA_I2C_CKD_HBUS_MASK; + div = (div == 7) ? 8u : (div == 8) ? 9u : (div + 1u); + + return AMEBA_I2C_NPPLL_HZ / div; +} + +#define AMEBA_I2C_IPCLK_FN(bus) ameba_i2c_ipclk(bus) + +/* The amebasmart I2C_InitTypeDef omits the DMA request-level fields. */ + +#undef AMEBA_I2C_HAS_DMA_FIELDS + +#endif /* __ARCH_ARM_SRC_RTL8730E_AMEBA_I2C_CHIP_H */ diff --git a/arch/arm/src/rtl8730e/rtl8730e_flash_stubs.c b/arch/arm/src/rtl8730e/rtl8730e_flash_stubs.c index e8338122e54..dd9083673f6 100644 --- a/arch/arm/src/rtl8730e/rtl8730e_flash_stubs.c +++ b/arch/arm/src/rtl8730e/rtl8730e_flash_stubs.c @@ -275,6 +275,18 @@ int DiagVprintfNano(const char *fmt, va_list ap) return vprintf(fmt, ap); } +/* The full-size variant is reached from log.c rtk_log_write(), which the + * RTK_LOGx() macros in the I2C fwlib expand to. DiagPrintf itself is a weak + * definition inside lib_rom.a, but DiagVprintf is not in the ROM symbol + * table, so it must be supplied here. Weak, because rtl8730e_wifi_stubs.c + * defines it strongly when WiFi is enabled (both route to vprintf). + */ + +__attribute__((weak)) int DiagVprintf(const char *fmt, va_list ap) +{ + return vprintf(fmt, ap); +} + /**************************************************************************** * __km0_ipc_memory_start__ * diff --git a/boards/arm/rtl8730e/rtl8730e_evb/configs/i2c/defconfig b/boards/arm/rtl8730e/rtl8730e_evb/configs/i2c/defconfig new file mode 100644 index 00000000000..f73727af585 --- /dev/null +++ b/boards/arm/rtl8730e/rtl8730e_evb/configs/i2c/defconfig @@ -0,0 +1,63 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_DISABLE_MB is not set +# CONFIG_NSH_DISABLE_MH is not set +# CONFIG_NSH_DISABLE_MW is not set +CONFIG_ALARM_ARCH=y +CONFIG_AMEBA_I2C=y +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="rtl8730e_evb" +CONFIG_ARCH_BOARD_RTL8730E_EVB=y +CONFIG_ARCH_CHIP="rtl8730e" +CONFIG_ARCH_CHIP_RTL8730E=y +CONFIG_ARCH_CHIP_RTL8730E_CA32=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_LOWVECTORS=y +CONFIG_ARM_PSCI=y +CONFIG_BOARD_LOOPSPERMSEC=393693 +CONFIG_BUILTIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_TASK_STACKSIZE=4096 +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXPERIMENTAL=y +CONFIG_FLASH_SIZE=1048576 +CONFIG_FLASH_START=0x60300000 +CONFIG_FLASH_VSTART=0x60300000 +CONFIG_FS_PROCFS=y +CONFIG_FS_TMPFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=4096 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_LIBC_MEMFD_ERROR=y +CONFIG_MM_DEFAULT_ALIGNMENT=64 +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_PRIORITY_INHERITANCE=y +CONFIG_RAM_SIZE=3145728 +CONFIG_RAM_START=0x60400000 +CONFIG_RAM_VSTART=0x60400000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_HPWORK=y +CONFIG_SCHED_HPWORKPRIORITY=192 +CONFIG_SMP=y +CONFIG_SMP_NCPUS=2 +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=25 +CONFIG_START_MONTH=4 +CONFIG_START_YEAR=2023 +CONFIG_SYSTEM_I2CTOOL=y +CONFIG_SYSTEM_NSH=y +CONFIG_USEC_PER_TICK=1000 diff --git a/boards/arm/rtl8730e/rtl8730e_evb/scripts/Make.defs b/boards/arm/rtl8730e/rtl8730e_evb/scripts/Make.defs index 2e8ad81df25..cb2de51e57f 100644 --- a/boards/arm/rtl8730e/rtl8730e_evb/scripts/Make.defs +++ b/boards/arm/rtl8730e/rtl8730e_evb/scripts/Make.defs @@ -62,7 +62,7 @@ include $(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)rtl8730e$(DELIM)ameba # lib_rom.a and the RTK toolchain's libgcc.a are compiled without VFP ABI # flags; suppress the harmless mismatch so the linker does not abort on it # whenever libameba_fwlib.a is in the link (GPIO, WiFi, or flash-FS config). -ifneq ($(filter y,$(CONFIG_AMEBA_GPIO) $(CONFIG_AMEBA_UART) $(CONFIG_RTL8730E_WIFI) $(CONFIG_RTL8730E_FLASH_FS)),) +ifneq ($(filter y,$(CONFIG_AMEBA_GPIO) $(CONFIG_AMEBA_UART) $(CONFIG_AMEBA_I2C) $(CONFIG_RTL8730E_WIFI) $(CONFIG_RTL8730E_FLASH_FS)),) LDFLAGS += --no-warn-mismatch endif diff --git a/boards/arm/rtl8730e/rtl8730e_evb/src/CMakeLists.txt b/boards/arm/rtl8730e/rtl8730e_evb/src/CMakeLists.txt index afdebb491af..16c8fbdb465 100644 --- a/boards/arm/rtl8730e/rtl8730e_evb/src/CMakeLists.txt +++ b/boards/arm/rtl8730e/rtl8730e_evb/src/CMakeLists.txt @@ -33,6 +33,12 @@ if(CONFIG_AMEBA_UART) PRIVATE ${NUTTX_DIR}/arch/arm/src/common/ameba) endif() +if(CONFIG_AMEBA_I2C) + list(APPEND SRCS rtl8730e_i2c.c) + target_include_directories(board + PRIVATE ${NUTTX_DIR}/arch/arm/src/common/ameba) +endif() + if(CONFIG_LIBC_FDT) target_include_directories(board PRIVATE ${NUTTX_DIR}/libs/libc/fdt/dtc/libfdt) diff --git a/boards/arm/rtl8730e/rtl8730e_evb/src/Makefile b/boards/arm/rtl8730e/rtl8730e_evb/src/Makefile index 013336f409b..36b7cbc795b 100644 --- a/boards/arm/rtl8730e/rtl8730e_evb/src/Makefile +++ b/boards/arm/rtl8730e/rtl8730e_evb/src/Makefile @@ -34,7 +34,7 @@ ifeq ($(CONFIG_LIBC_FDT),y) CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)fdt$(DELIM)dtc$(DELIM)libfdt endif -ifneq ($(CONFIG_RTL8730E_FLASH_FS)$(CONFIG_AMEBA_GPIO)$(CONFIG_AMEBA_UART),) +ifneq ($(CONFIG_RTL8730E_FLASH_FS)$(CONFIG_AMEBA_GPIO)$(CONFIG_AMEBA_UART)$(CONFIG_AMEBA_I2C),) CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)arm$(DELIM)src$(DELIM)common$(DELIM)ameba endif @@ -46,4 +46,8 @@ ifeq ($(CONFIG_AMEBA_UART),y) CSRCS += rtl8730e_uart.c endif +ifeq ($(CONFIG_AMEBA_I2C),y) +CSRCS += rtl8730e_i2c.c +endif + include $(TOPDIR)/boards/Board.mk diff --git a/boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_bringup.c b/boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_bringup.c index d54f4263ecc..94ac3b030b4 100644 --- a/boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_bringup.c +++ b/boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_bringup.c @@ -260,6 +260,17 @@ int rtl8730e_bringup(void) } #endif +#ifdef CONFIG_AMEBA_I2C + /* Register the board's I2C master buses at /dev/i2cN. */ + + ret = rtl8730e_i2c_initialize(); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: Failed to initialize I2C: %d\n", ret); + } +#endif + UNUSED(ret); return OK; } diff --git a/boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_evb.h b/boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_evb.h index 38616432dc1..2324ede7fc0 100644 --- a/boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_evb.h +++ b/boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_evb.h @@ -65,5 +65,9 @@ int rtl8730e_gpio_initialize(void); int rtl8730e_uart_initialize(void); #endif +#ifdef CONFIG_AMEBA_I2C +int rtl8730e_i2c_initialize(void); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __BOARDS_ARM_RTL8730E_RTL8730E_EVB_SRC_RTL8730E_EVB_H */ diff --git a/boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_i2c.c b/boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_i2c.c new file mode 100644 index 00000000000..c6742932677 --- /dev/null +++ b/boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_i2c.c @@ -0,0 +1,107 @@ +/**************************************************************************** + * boards/arm/rtl8730e/rtl8730e_evb/src/rtl8730e_i2c.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 "ameba_gpio.h" +#include "ameba_i2c.h" +#include "rtl8730e_evb.h" + +#ifdef CONFIG_AMEBA_I2C + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* One entry per I2C bus exposed to NuttX at /dev/i2cN. The SCL/SDA pads are + * examples used by the `i2c` config (system/i2c i2ctool) -- adjust them to + * match your board's wiring. Unlike the GPIO or UART crossbars, an RTL8730E + * pad reaches exactly one I2C controller, so a pad can only be swapped for + * another from the same controller's set; see i2c_index_get() in the SDK's + * hal/src/i2c_api.c. Pads the audio codec drives must not be used. + */ + +struct rtl8730e_i2c_s +{ + int bus; /* Controller index (AMEBA_I2C0..AMEBA_I2C2) */ + uint8_t sclpin; /* SCL pad (AMEBA_PA()/AMEBA_PB() encoding) */ + uint8_t sdapin; /* SDA pad (AMEBA_PA()/AMEBA_PB() encoding) */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct rtl8730e_i2c_s g_i2c_buses[] = +{ + { + AMEBA_I2C0, AMEBA_PA(10), AMEBA_PA(9) + }, + { + AMEBA_I2C1, AMEBA_PA(4), AMEBA_PA(3) + }, + { + AMEBA_I2C2, AMEBA_PB(11), AMEBA_PB(10) + }, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: rtl8730e_i2c_initialize + * + * Description: + * Register the board's I2C master buses at /dev/i2cN. + * + ****************************************************************************/ + +int rtl8730e_i2c_initialize(void) +{ + int ret; + int i; + + for (i = 0; i < (int)nitems(g_i2c_buses); i++) + { + ret = ameba_i2c_register(g_i2c_buses[i].bus, g_i2c_buses[i].sclpin, + g_i2c_buses[i].sdapin); + if (ret < 0) + { + syslog(LOG_ERR, + "ERROR: ameba_i2c_register(/dev/i2c%d) failed: %d\n", + g_i2c_buses[i].bus, ret); + return ret; + } + } + + return OK; +} + +#endif /* CONFIG_AMEBA_I2C */