diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 01bca006f19b80..1f33d2379d8f75 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,12 +1,17 @@ stages: - compliance - guidlines + - doc + - twister-build + +variables: + BOARD: rz_g3s comliance-job: stage: compliance script: - echo "Starting compliance check" - - cd /builds/rec-rzzp + - cd /builds/${CI_PROJECT_NAMESPACE} - west init -l zephyr > /dev/null 2>&1 || true - cd zephyr # WA to skip undef config checks because it fails with errors about @@ -15,16 +20,47 @@ comliance-job: - sed -i "s/self.check_no_undef_outside_kconfig(kconf)/print(\"skip\")/g" ./scripts/ci/check_compliance.py - export ZEPHYR_BASE=$PWD - - ./scripts/ci/check_compliance.py --annotate -e KconfigBasic -c ${CI_DEFAULT_BRANCH}.. + - ./scripts/ci/check_compliance.py --annotate -e KconfigBasic -c origin/${CI_DEFAULT_BRANCH}.. guidlines-job: stage: guidlines script: - echo "Starting guidlines check" - - cd /builds/rec-rzzp + - cd /builds/${CI_PROJECT_NAMESPACE} - west init -l zephyr > /dev/null 2>&1 || true - cd ./zephyr - source zephyr-env.sh - - export ZEPHYR_BASE=/builds/rec-rzzp/zephyr - - ./scripts/ci/guideline_check.py --output output.txt -c ${CI_DEFAULT_BRANCH}.. || + - export ZEPHYR_BASE=/builds/${CI_PROJECT_NAMESPACE}/zephyr + - ./scripts/ci/guideline_check.py --output output.txt -c origin/${CI_DEFAULT_BRANCH}.. || cat ./output.txt + +doc-job: + stage: doc + script: + - echo "Generating release notes" + - cd /builds/${CI_PROJECT_NAMESPACE} + - west init -l zephyr > /dev/null 2>&1 || true + - cd ./zephyr + - source zephyr-env.sh + - export ZEPHYR_BASE=/builds/${CI_PROJECT_NAMESPACE}/zephyr + - west build -b ${BOARD} -t doc samples/basic/hash_map + artifacts: + paths: + - /builds/${CI_PROJECT_NAMESPACE}/zephyr/build/zephyr/rzg3s_release_notes.pdf + +twister-build-job: + stage: twister-build + when: manual + script: + - echo "Twister check" + - cd /builds/${CI_PROJECT_NAMESPACE} + - west init -l zephyr > /dev/null 2>&1 || true + - cd ./zephyr + - source zephyr-env.sh + - export ZEPHYR_BASE=/builds/${CI_PROJECT_NAMESPACE}/zephyr + - scripts/twister -p ${BOARD} --enable-slow + artifacts: + paths: + - twister-out/twister_report.xml + - twister-out/twister.xml + - twister-out/twister.json diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3f775e4d638909..205ec295a80337 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -16,10 +16,9 @@ config CPU_CORTEX config ARM_CUSTOM_INTERRUPT_CONTROLLER bool - depends on !CPU_CORTEX_M help This option indicates that the ARM CPU is connected to a custom (i.e. - non-GIC) interrupt controller. + non-GIC, NVIC) interrupt controller or required MULTI_LEVEL_INTERRUPTS support. A number of Cortex-A and Cortex-R cores (Cortex-A5, Cortex-R4/5, ...) allow interfacing to a custom external interrupt controller and this @@ -30,9 +29,10 @@ config ARM_CUSTOM_INTERRUPT_CONTROLLER functions are mapped to the SoC interrupt control interface, which is implemented at the SoC level. - N.B. This option is only applicable to the Cortex-A and Cortex-R - family cores. The Cortex-M family cores are always equipped with - the ARM Nested Vectored Interrupt Controller (NVIC). + For MULTI_LEVEL_INTERRUPTS support the architecture interrupt control + functions also has to be mapped to the SoC interrupt control interface to + perform proper interrupt control calls dispatch to the irq_nextlevel or + ARCH IRQ control API. config CODE_DATA_RELOCATION_SRAM bool "Relocate code/data sections to SRAM" diff --git a/arch/arm/core/cortex_m/irq_manage.c b/arch/arm/core/cortex_m/irq_manage.c index cd0c6f6e5bfb28..11897bbb68ad1d 100644 --- a/arch/arm/core/cortex_m/irq_manage.c +++ b/arch/arm/core/cortex_m/irq_manage.c @@ -28,6 +28,8 @@ extern void z_arm_reserved(void); +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + #define NUM_IRQS_PER_REG 32 #define REG_FROM_IRQ(irq) (irq / NUM_IRQS_PER_REG) #define BIT_FROM_IRQ(irq) (irq % NUM_IRQS_PER_REG) @@ -89,6 +91,7 @@ void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) BIT(NUM_IRQ_PRIO_BITS) - (_IRQ_PRIO_OFFSET)); NVIC_SetPriority((IRQn_Type)irq, prio); } +#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); diff --git a/arch/arm/core/mpu/arm_mpu.c b/arch/arm/core/mpu/arm_mpu.c index 9b2feffe5eea3b..0b313884146720 100644 --- a/arch/arm/core/mpu/arm_mpu.c +++ b/arch/arm/core/mpu/arm_mpu.c @@ -469,8 +469,10 @@ int z_arm_mpu_init(void) * dereferencing detection (debug feature) */ #if defined(CONFIG_NULL_POINTER_EXCEPTION_DETECTION_MPU) + #if (defined(CONFIG_ARMV8_M_BASELINE) || defined(CONFIG_ARMV8_M_MAINLINE)) && \ - (CONFIG_FLASH_BASE_ADDRESS > CONFIG_CORTEX_M_NULL_POINTER_EXCEPTION_PAGE_SIZE) + (CONFIG_FLASH_BASE_ADDRESS > CONFIG_CORTEX_M_NULL_POINTER_EXCEPTION_PAGE_SIZE) && \ + !defined(CONFIG_NULL_POINTER_EXCEPTION_DETECTION_MPU_RZ_G) #pragma message "Null-Pointer exception detection cannot be configured on un-mapped flash areas" #else const struct z_arm_mpu_partition unmap_region = { diff --git a/boards/arm/rz_a2m/board.cmake b/boards/arm/rz_a2m/board.cmake index 15edc7afbbe644..c831b939560dc7 100644 --- a/boards/arm/rz_a2m/board.cmake +++ b/boards/arm/rz_a2m/board.cmake @@ -2,3 +2,9 @@ board_runner_args(jlink "--device=R7S921053VCBG" "--speed=15000") include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) + +set(RELEASE_NOTES_SRC rza2m_release_notes.tex) +add_custom_target(doc + WORKING_DIRECTORY ${ZEPHYR_BASE}/boards/${ARCH}/${BOARD}/release_notes + COMMAND pdflatex -output-directory=${ZEPHYR_BINARY_DIR} ${RELEASE_NOTES_SRC} +) diff --git a/boards/arm/rz_a2m/rz_a2m.dts b/boards/arm/rz_a2m/rz_a2m.dts index c88c1569fc32e4..aa7db1e230328e 100644 --- a/boards/arm/rz_a2m/rz_a2m.dts +++ b/boards/arm/rz_a2m/rz_a2m.dts @@ -132,6 +132,7 @@ }; &ostm1 { + compatible = "renesas,ostm-timer"; status = "okay"; }; diff --git a/boards/arm/rz_a2m/rz_a2m_defconfig b/boards/arm/rz_a2m/rz_a2m_defconfig index 0400f97d3771fe..026914d44d3516 100644 --- a/boards/arm/rz_a2m/rz_a2m_defconfig +++ b/boards/arm/rz_a2m/rz_a2m_defconfig @@ -31,6 +31,3 @@ CONFIG_CACHE_MANAGEMENT=y # Enable BSC CONFIG_BSC=y - -# Enable RSPI -CONFIG_SPI_RZA2M=y diff --git a/boards/arm/rz_g3s/Kconfig.board b/boards/arm/rz_g3s/Kconfig.board new file mode 100644 index 00000000000000..b4a5b1a8623aa2 --- /dev/null +++ b/boards/arm/rz_g3s/Kconfig.board @@ -0,0 +1,11 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_RZ_G3S + bool "Cortex-M33 for Renesas RZ G3S" + depends on SOC_R9A08G045 + +config BOARD_RZ_G3S_FPU + bool "Cortex-M33 with FPU for Renesas RZ G3S" + select CPU_HAS_FPU + depends on SOC_R9A08G045 diff --git a/boards/arm/rz_g3s/Kconfig.defconfig b/boards/arm/rz_g3s/Kconfig.defconfig new file mode 100644 index 00000000000000..bf8b2e75a245d1 --- /dev/null +++ b/boards/arm/rz_g3s/Kconfig.defconfig @@ -0,0 +1,19 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_RZ_G3S +config BOARD + default "rz_g3s" + +endif # BOARD_RZ_G3S + +if BOARD_RZ_G3S_FPU +config BOARD + default "rz_g3s_fpu" + +config FPU + default y + +config FPU_SHARING + default y +endif # BOARD_RZ_G3S_FPU diff --git a/boards/arm/rz_g3s/board.cmake b/boards/arm/rz_g3s/board.cmake new file mode 100644 index 00000000000000..dfb4bf64ed1890 --- /dev/null +++ b/boards/arm/rz_g3s/board.cmake @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: Apache-2.0 + +if (CONFIG_BOARD_RZ_G3S_FPU) + board_runner_args(jlink "--device=R9A08G045S33_M33_1" "--speed=15000") +else () + board_runner_args(jlink "--device=R9A08G045S33_M33_0" "--speed=15000") +endif () +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) + +set(RELEASE_NOTES_SRC .) +set(RELEASE_NOTES_OUT rzg3s_release_notes.pdf) + +set(KERNEL_SREC_NAME ${KERNEL_NAME}.srec) + +add_custom_target(doc + WORKING_DIRECTORY ${ZEPHYR_BASE}/boards/${ARCH}/${BOARD}/doc + COMMAND sphinx-build -M latexpdf ${RELEASE_NOTES_SRC} ${ZEPHYR_BINARY_DIR} + COMMAND cp ${ZEPHYR_BINARY_DIR}/latex/rzg3s_release_notes.pdf ${ZEPHYR_BINARY_DIR}/${RELEASE_NOTES_OUT} + COMMAND rm -Rf ${ZEPHYR_BINARY_DIR}/latex + COMMAND rm -Rf ${ZEPHYR_BINARY_DIR}/doctrees +) + +set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${CMAKE_OBJCOPY} -I binary -O srec --srec-forceS --adjust-vma 0x23000 ${ZEPHYR_BINARY_DIR}/${KERNEL_NAME}.bin ${ZEPHYR_BINARY_DIR}/${KERNEL_SREC_NAME} +) diff --git a/boards/arm/rz_g3s/doc/_extensions/zephyr/__init__.py b/boards/arm/rz_g3s/doc/_extensions/zephyr/__init__.py new file mode 100644 index 00000000000000..c62af8e8f4df59 --- /dev/null +++ b/boards/arm/rz_g3s/doc/_extensions/zephyr/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) 2021 Zephyr Project members and individual contributors +# SPDX-License-Identifier: Apache-2.0 + +# File intentionally empty diff --git a/boards/arm/rz_g3s/doc/_extensions/zephyr/application.py b/boards/arm/rz_g3s/doc/_extensions/zephyr/application.py new file mode 100644 index 00000000000000..9369fb7becf1c6 --- /dev/null +++ b/boards/arm/rz_g3s/doc/_extensions/zephyr/application.py @@ -0,0 +1,430 @@ +# Copyright (c) 2017 Open Source Foundries Limited. +# +# SPDX-License-Identifier: Apache-2.0 + +'''Sphinx extensions related to managing Zephyr applications.''' + +from docutils import nodes +from docutils.parsers.rst import Directive +from docutils.parsers.rst import directives + + +# TODO: extend and modify this for Windows. +# +# This could be as simple as generating a couple of sets of instructions, one +# for Unix environments, and another for Windows. +class ZephyrAppCommandsDirective(Directive): + r''' + This is a Zephyr directive for generating consistent documentation + of the shell commands needed to manage (build, flash, etc.) an application. + + For example, to generate commands to build samples/hello_world for + qemu_x86 use:: + + .. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: qemu_x86 + :goals: build + + Directive options: + + \:tool: + which tool to use. Valid options are currently 'cmake', 'west' and 'all'. + The default is 'west'. + + \:app: + path to the application to build. + + \:zephyr-app: + path to the application to build, this is an app present in the upstream + zephyr repository. Mutually exclusive with \:app:. + + \:cd-into: + if set, build instructions are given from within the \:app: folder, + instead of outside of it. + + \:generator: + which build system to generate. Valid options are + currently 'ninja' and 'make'. The default is 'ninja'. This option + is not case sensitive. + + \:host-os: + which host OS the instructions are for. Valid options are + 'unix', 'win' and 'all'. The default is 'all'. + + \:board: + if set, the application build will target the given board. + + \:shield: + if set, the application build will target the given shield. + + \:conf: + if set, the application build will use the given configuration + file. If multiple conf files are provided, enclose the + space-separated list of files with quotes, e.g., "a.conf b.conf". + + \:gen-args: + if set, additional arguments to the CMake invocation + + \:build-args: + if set, additional arguments to the build invocation + + \:build-dir: + if set, the application build directory will *APPEND* this + (relative, Unix-separated) path to the standard build directory. This is + mostly useful for distinguishing builds for one application within a + single page. + + \:goals: + a whitespace-separated list of what to do with the app (in + 'build', 'flash', 'debug', 'debugserver', 'run'). Commands to accomplish + these tasks will be generated in the right order. + + \:maybe-skip-config: + if set, this indicates the reader may have already + created a build directory and changed there, and will tweak the text to + note that doing so again is not necessary. + + \:compact: + if set, the generated output is a single code block with no + additional comment lines + + \:west-args: + if set, additional arguments to the west invocation (ignored for CMake) + + ''' + has_content = False + required_arguments = 0 + optional_arguments = 0 + final_argument_whitespace = False + option_spec = { + 'tool': directives.unchanged, + 'app': directives.unchanged, + 'zephyr-app': directives.unchanged, + 'cd-into': directives.flag, + 'generator': directives.unchanged, + 'host-os': directives.unchanged, + 'board': directives.unchanged, + 'shield': directives.unchanged, + 'conf': directives.unchanged, + 'gen-args': directives.unchanged, + 'build-args': directives.unchanged, + 'build-dir': directives.unchanged, + 'goals': directives.unchanged_required, + 'maybe-skip-config': directives.flag, + 'compact': directives.flag, + 'west-args': directives.unchanged, + } + + TOOLS = ['cmake', 'west', 'all'] + GENERATORS = ['make', 'ninja'] + HOST_OS = ['unix', 'win', 'all'] + IN_TREE_STR = '# From the root of the zephyr repository' + + def run(self): + # Re-run on the current document if this directive's source changes. + self.state.document.settings.env.note_dependency(__file__) + + # Parse directive options. Don't use os.path.sep or os.path.join here! + # That would break if building the docs on Windows. + tool = self.options.get('tool', 'west').lower() + app = self.options.get('app', None) + zephyr_app = self.options.get('zephyr-app', None) + cd_into = 'cd-into' in self.options + generator = self.options.get('generator', 'ninja').lower() + host_os = self.options.get('host-os', 'all').lower() + board = self.options.get('board', None) + shield = self.options.get('shield', None) + conf = self.options.get('conf', None) + gen_args = self.options.get('gen-args', None) + build_args = self.options.get('build-args', None) + build_dir_append = self.options.get('build-dir', '').strip('/') + goals = self.options.get('goals').split() + skip_config = 'maybe-skip-config' in self.options + compact = 'compact' in self.options + west_args = self.options.get('west-args', None) + + if tool not in self.TOOLS: + raise self.error('Unknown tool {}; choose from: {}'.format( + tool, self.TOOLS)) + + if app and zephyr_app: + raise self.error('Both app and zephyr-app options were given.') + + if generator not in self.GENERATORS: + raise self.error('Unknown generator {}; choose from: {}'.format( + generator, self.GENERATORS)) + + if host_os not in self.HOST_OS: + raise self.error('Unknown host-os {}; choose from: {}'.format( + host_os, self.HOST_OS)) + + if compact and skip_config: + raise self.error('Both compact and maybe-skip-config options were given.') + + app = app or zephyr_app + in_tree = self.IN_TREE_STR if zephyr_app else None + # Allow build directories which are nested. + build_dir = ('build' + '/' + build_dir_append).rstrip('/') + + # Create host_os array + host_os = [host_os] if host_os != "all" else [v for v in self.HOST_OS + if v != 'all'] + # Create tools array + tools = [tool] if tool != "all" else [v for v in self.TOOLS + if v != 'all'] + # Build the command content as a list, then convert to string. + content = [] + tool_comment = None + if len(tools) > 1: + tool_comment = 'Using {}:' + + run_config = { + 'host_os': host_os, + 'app': app, + 'in_tree': in_tree, + 'cd_into': cd_into, + 'board': board, + 'shield': shield, + 'conf': conf, + 'gen_args': gen_args, + 'build_args': build_args, + 'build_dir': build_dir, + 'goals': goals, + 'compact': compact, + 'skip_config': skip_config, + 'generator': generator, + 'west_args': west_args + } + + if 'west' in tools: + w = self._generate_west(**run_config) + if tool_comment: + paragraph = nodes.paragraph() + paragraph += nodes.Text(tool_comment.format('west')) + content.append(paragraph) + content.append(self._lit_block(w)) + else: + content.extend(w) + + if 'cmake' in tools: + c = self._generate_cmake(**run_config) + if tool_comment: + paragraph = nodes.paragraph() + paragraph += nodes.Text(tool_comment.format( + 'CMake and {}'.format(generator))) + content.append(paragraph) + content.append(self._lit_block(c)) + else: + content.extend(c) + + if not tool_comment: + content = [self._lit_block(content)] + + return content + + def _lit_block(self, content): + content = '\n'.join(content) + + # Create the nodes. + literal = nodes.literal_block(content, content) + self.add_name(literal) + literal['language'] = 'console' + return literal + + + def _generate_west(self, **kwargs): + content = [] + generator = kwargs['generator'] + board = kwargs['board'] + app = kwargs['app'] + in_tree = kwargs['in_tree'] + goals = kwargs['goals'] + cd_into = kwargs['cd_into'] + build_dir = kwargs['build_dir'] + compact = kwargs['compact'] + west_args = kwargs['west_args'] + kwargs['board'] = None + # west always defaults to ninja + gen_arg = ' -G\'Unix Makefiles\'' if generator == 'make' else '' + cmake_args = gen_arg + self._cmake_args(**kwargs) + cmake_args = ' --{}'.format(cmake_args) if cmake_args != '' else '' + west_args = ' {}'.format(west_args) if west_args else '' + # ignore zephyr_app since west needs to run within + # the installation. Instead rely on relative path. + src = ' {}'.format(app) if app and not cd_into else '' + dst = ' -d {}'.format(build_dir) if build_dir != 'build' else '' + + if in_tree and not compact: + content.append(in_tree) + + if cd_into and app: + content.append('cd {}'.format(app)) + + # We always have to run west build. + # + # FIXME: doing this unconditionally essentially ignores the + # maybe-skip-config option if set. + # + # This whole script and its users from within the + # documentation needs to be overhauled now that we're + # defaulting to west. + # + # For now, this keeps the resulting commands working. + content.append('west build -b {}{}{}{}{}'. + format(board, west_args, dst, src, cmake_args)) + + # If we're signing, we want to do that next, so that flashing + # etc. commands can use the signed file which must be created + # in this step. + if 'sign' in goals: + content.append('west sign{}'.format(dst)) + + for goal in goals: + if goal in {'build', 'sign'}: + continue + elif goal == 'flash': + content.append('west flash{}'.format(dst)) + elif goal == 'debug': + content.append('west debug{}'.format(dst)) + elif goal == 'debugserver': + content.append('west debugserver{}'.format(dst)) + elif goal == 'attach': + content.append('west attach{}'.format(dst)) + else: + content.append('west build -t {}{}'.format(goal, dst)) + + return content + + @staticmethod + def _mkdir(mkdir, build_dir, host_os, skip_config): + content = [] + if skip_config: + content.append("# If you already made a build directory ({}) and ran cmake, just 'cd {}' instead.".format(build_dir, build_dir)) # noqa: E501 + if host_os == 'all': + content.append('mkdir {} && cd {}'.format(build_dir, build_dir)) + if host_os == "unix": + content.append('{} {} && cd {}'.format(mkdir, build_dir, build_dir)) + elif host_os == "win": + build_dir = build_dir.replace('/', '\\') + content.append('mkdir {} & cd {}'.format(build_dir, build_dir)) + return content + + @staticmethod + def _cmake_args(**kwargs): + board = kwargs['board'] + shield = kwargs['shield'] + conf = kwargs['conf'] + gen_args = kwargs['gen_args'] + board_arg = ' -DBOARD={}'.format(board) if board else '' + shield_arg = ' -DSHIELD={}'.format(shield) if shield else '' + conf_arg = ' -DCONF_FILE={}'.format(conf) if conf else '' + gen_args = ' {}'.format(gen_args) if gen_args else '' + + return '{}{}{}{}'.format(board_arg, shield_arg, conf_arg, gen_args) + + def _cd_into(self, mkdir, **kwargs): + app = kwargs['app'] + host_os = kwargs['host_os'] + compact = kwargs['compact'] + build_dir = kwargs['build_dir'] + skip_config = kwargs['skip_config'] + content = [] + os_comment = None + if len(host_os) > 1: + os_comment = '# On {}' + num_slashes = build_dir.count('/') + if not app and mkdir and num_slashes == 0: + # When there's no app and a single level deep build dir, + # simplify output + content.extend(self._mkdir(mkdir, build_dir, 'all', + skip_config)) + if not compact: + content.append('') + return content + for host in host_os: + if host == "unix": + if os_comment: + content.append(os_comment.format('Linux/macOS')) + if app: + content.append('cd {}'.format(app)) + elif host == "win": + if os_comment: + content.append(os_comment.format('Windows')) + if app: + backslashified = app.replace('/', '\\') + content.append('cd {}'.format(backslashified)) + if mkdir: + content.extend(self._mkdir(mkdir, build_dir, host, skip_config)) + if not compact: + content.append('') + return content + + def _generate_cmake(self, **kwargs): + generator = kwargs['generator'] + cd_into = kwargs['cd_into'] + app = kwargs['app'] + in_tree = kwargs['in_tree'] + build_dir = kwargs['build_dir'] + build_args = kwargs['build_args'] + skip_config = kwargs['skip_config'] + goals = kwargs['goals'] + compact = kwargs['compact'] + + content = [] + + if in_tree and not compact: + content.append(in_tree) + + if cd_into: + num_slashes = build_dir.count('/') + mkdir = 'mkdir' if num_slashes == 0 else 'mkdir -p' + content.extend(self._cd_into(mkdir, **kwargs)) + # Prepare cmake/ninja/make variables + source_dir = ' ' + '/'.join(['..' for i in range(num_slashes + 1)]) + cmake_build_dir = '' + tool_build_dir = '' + else: + source_dir = ' {}'.format(app) if app else ' .' + cmake_build_dir = ' -B{}'.format(build_dir) + tool_build_dir = ' -C{}'.format(build_dir) + + # Now generate the actual cmake and make/ninja commands + gen_arg = ' -GNinja' if generator == 'ninja' else '' + build_args = ' {}'.format(build_args) if build_args else '' + cmake_args = self._cmake_args(**kwargs) + + if not compact: + if not cd_into and skip_config: + content.append("# If you already ran cmake with -B{}, you " \ + "can skip this step and run {} directly.". + format(build_dir, generator)) # noqa: E501 + else: + content.append('# Use cmake to configure a {}-based build' \ + 'system:'.format(generator.capitalize())) # noqa: E501 + + content.append('cmake{}{}{}{}'.format(cmake_build_dir, gen_arg, + cmake_args, source_dir)) + if not compact: + content.extend(['', + '# Now run ninja on the generated build system:']) + + if 'build' in goals: + content.append('{}{}{}'.format(generator, tool_build_dir, + build_args)) + for goal in goals: + if goal == 'build': + continue + content.append('{}{} {}'.format(generator, tool_build_dir, goal)) + + return content + + +def setup(app): + app.add_directive('zephyr-app-commands', ZephyrAppCommandsDirective) + + return { + 'version': '1.0', + 'parallel_read_safe': True, + 'parallel_write_safe': True + } diff --git a/boards/arm/rz_g3s/doc/adc/adc.rst b/boards/arm/rz_g3s/doc/adc/adc.rst new file mode 100644 index 00000000000000..3a6f50cc909731 --- /dev/null +++ b/boards/arm/rz_g3s/doc/adc/adc.rst @@ -0,0 +1,157 @@ +A/D Converter (ADC) +=================== + +ADC overview +------------ + +The Renesas RZ G3S Soc has a successive approximation A/D converter with a 12-bit accuracy. +Up to eight analog input channels and one dedicated channel to TSU can be selected. + +* Resolution 12 bits +* Input voltage range 0 V to 1.8 V +* Minimum conversion time 1.0 µs per channel (when A/D conversion clock ADC_ADCLK is 100 MHz) +* The A/D conversion result is stored in a 32-bit data register corresponding to each channel. +* Sample-and-hold function +* Trigger mode + + * Software trigger mode and hardware trigger mode are available. + * Software trigger mode to start A/D conversion by software + * Hardware trigger mode to start A/D conversion by an asynchronous trigger or synchronous trigger + +* Operating mode + + * Select mode and scan mode are available. + * Select mode to convert the specified single analog input channel + * Scan mode to convert the analog inputs of arbitrarily selected channels in ascending order of channel number + +* Conversion mode + + * Single mode and repeat mode are available. + * Single mode to proceed A/D conversion only once + * Repeat mode to repeatedly proceed A/D conversion + +Refer to "A/D Converter" section in "Renesas RZ/G3S Group User’s Manual: Hardware" + +ADC driver overview +------------------- + +Zephyr RZ/G3S Renesas ADC driver provides Zephyr :ref:`adc_api` System interface implementation. + +The ADC subsystem is **not** enabled by default in ``rz_g3s_defconfig``. To enable Zephyr +ADC functionality and RZ G3S ADC driver below Kconfig options have to be enabled: + +.. code-block:: text + + CONFIG_ADC=y + /* optional */ + CONFIG_ADC_ASYNC=y + /* automatically enabled */ + CONFIG_ADC_RZG3S=y + +The RZ G3S ADC driver code can be found at: + +.. code-block:: text + + drivers/adc/adc_rz_g3s.c + +ADC testing +----------- + +tests/drivers/adc/adc_api +````````````````````````` + +Zephyr RZ/G3S ADC driver can be tested by using **tests/drivers/adc/adc_api** test application. +Use below command to build ADC **tests/drivers/adc/adc_api** test application: + +.. code-block:: bash + + west build -b rz_g3s -p always tests/drivers/adc/adc_api + +It runs several tests: + + - test_adc_asynchronous_call - ADC perform one channel reading in asynchronous mode + - test_adc_invalid_request - the wrong configuration for the ADC sequence is set and the driver is expected to return an error + - test_adc_repeated_samplings - periodic reading of 2 ADC channels is performed, repeat reading is requested by a user callback + - test_adc_sample_one_channel - one channel is tested in synchronous mode + - test_adc_sample_two_channels - all available channels specified in devicetree are tested + - test_adc_sample_with_interval - test with 100 ms interval between samples + +The **tests/drivers/adc/adc_api** sample application will produce below console output when executed: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-280-ge76b6c593adc *** + Running TESTSUITE adc_basic + =================================================================== + START - test_adc_asynchronous_call + Samples read: 0x0b96 0x0caf 0x0dc2 0x0ecb 0x0fd6 0xffff8000 + PASS - test_adc_asynchronous_call in 0.007 seconds + =================================================================== + START - test_adc_invalid_request + E: adc@50058000: supported only 12-bit resolution + E: adc@50058000: supported only 12-bit resolution + Samples read: 0x0fe2 0xffff8000 0xffff8000 0xffff8000 0xffff8000 0xffff8000 + PASS - test_adc_invalid_request in 0.016 seconds + =================================================================== + START - test_adc_repeated_samplings + repeated_samplings_callback: done 1 + Samples read: 0x0fff 0x0b38 0xffff8000 0xffff8000 0xffff8000 0xffff8000 + repeated_samplings_callback: done 2 + Samples read: 0x0fff 0x0b38 0x0f65 0x0c3b 0xffff8000 0xffff8000 + repeated_samplings_callback: done 3 + Samples read: 0x0fff 0x0b38 0x0f61 0x0cfb 0xffff8000 0xffff8000 + repeated_samplings_callback: done 4 + Samples read: 0x0fff 0x0b38 0x0f86 0x0da5 0xffff8000 0xffff8000 + repeated_samplings_callback: done 5 + Samples read: 0x0fff 0x0b38 0x0fb6 0x0e0f 0xffff8000 0xffff8000 + repeated_samplings_callback: done 6 + Samples read: 0x0fff 0x0b38 0x0fed 0x0e8c 0xffff8000 0xffff8000 + repeated_samplings_callback: done 7 + Samples read: 0x0fff 0x0b38 0x0fff 0x0ee4 0xffff8000 0xffff8000 + repeated_samplings_callback: done 8 + Samples read: 0x0fff 0x0b38 0x0fff 0x0f0e 0xffff8000 0xffff8000 + repeated_samplings_callback: done 9 + Samples read: 0x0fff 0x0b38 0x0fff 0x0f3d 0xffff8000 0xffff8000 + repeated_samplings_callback: done 10 + Samples read: 0x0fff 0x0b38 0x0fff 0x0f48 0xffff8000 0xffff8000 + PASS - test_adc_repeated_samplings in 0.091 seconds + =================================================================== + START - test_adc_sample_one_channel + Samples read: 0x0ff0 0xffff8000 0xffff8000 0xffff8000 0xffff8000 0xffff8000 + PASS - test_adc_sample_one_channel in 0.008 seconds + =================================================================== + START - test_adc_sample_two_channels + Samples read: 0x0fff 0x0ef7 0x0725 0xffff8000 0xffff8000 0xffff8000 + PASS - test_adc_sample_two_channels in 0.007 seconds + =================================================================== + START - test_adc_sample_with_interval + sample_with_interval_callback: sampling 0 + sample_with_interval_callback: sampling 1 + sample_with_interval_callback: sampling 2 + sample_with_interval_callback: sampling 3 + sample_with_interval_callback: sampling 4 + Samples read: 0x0e2f 0x0ea6 0x0ec6 0x0ee8 0x0ee9 0xffff8000 + PASS - test_adc_sample_with_interval in 0.410 seconds + =================================================================== + TESTSUITE adc_basic succeeded + ------ TESTSUITE SUMMARY START ------ + SUITE PASS - 100.00% [adc_basic]: pass = 6, fail = 0, skip = 0, total = 6 durats + - PASS - [adc_basic.test_adc_asynchronous_call] duration = 0.007 seconds + - PASS - [adc_basic.test_adc_invalid_request] duration = 0.016 seconds + - PASS - [adc_basic.test_adc_repeated_samplings] duration = 0.091 seconds + - PASS - [adc_basic.test_adc_sample_one_channel] duration = 0.008 seconds + - PASS - [adc_basic.test_adc_sample_two_channels] duration = 0.007 seconds + - PASS - [adc_basic.test_adc_sample_with_interval] duration = 0.410 seconds + ------ TESTSUITE SUMMARY END ------ + =================================================================== + PROJECT EXECUTION SUCCESSFUL + +Sample data is output in the following format: if a sample is read, its value is displayed +in ADC levels, if not read, the number 0xffff8000 is displayed. +Additionally, the ADC can be checked by applying voltage from 0 to 1.8 V to pins 1-8 +of the ADC connector located on the RZ/G3S SMARC Module board. In this case, +the ADC values of corresponding channel will be from 0 to 0xFFF, respectively. + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/canfd/canfd.rst b/boards/arm/rz_g3s/doc/canfd/canfd.rst new file mode 100644 index 00000000000000..115f30d769ca4e --- /dev/null +++ b/boards/arm/rz_g3s/doc/canfd/canfd.rst @@ -0,0 +1,379 @@ +CAN-FD Interface (CAN-FD) +========================= + +CAN-FD overview +--------------- + +Renesas RZ G3S CAN-FD controller has 2-channels that complies with ISO 11898-1 (2015) Standards. +It transmits and receives both formats of messages: the standard identifier (11 bits) +and extended ID (29 bits). The following major HW features are supported. + +* CAN-FD mode +* Nominal bit rate: Max. 1 Mbps +* Data bit rate: Max. 8 Mbps +* CAN-FD ISO 11898-1 (CD2015) compliant; +* number of receive rules (0 to 128) for each channel; +* transmit buffers up to 32 per channel; +* receive buffers 128 total, up to 64 buffers per channel; +* Transmitter Delay Compensation; +* RX/TX message timestamping; +* auto-bus recovery; +* loopback, listen-only and one-shot test modes + +Refer to "CAN-FD Interface (CAN-FD)" section in "Renesas RZ/G3S Group User’s Manual: Hardware" + +CAN-FD driver overview +---------------------- + +The RZ G3S CAN-FD driver driver provides Zephyr :ref:`can_api` System interface implementation +and supports below features: + +* 2 channels supported; +* number of receive AFL rules (0 to 128) for each channel; +* transmit buffers up to 32 per channel; +* Transmission Priority by CAN Frame ID; +* receive buffers 128 total, up to 64 buffers per channel; +* CAN-FD and Classic frames processing; +* loopback, listen-only and one-shot test modes; +* Transmitter Delay Compensation; +* RX message timestamping; +* auto bus recovery; +* Zephyr CAN statistic and RZ G3S CAN-FD driver statistic; +* Frame filering by ID, IDE, RTR/Data with masking in HW; +* Frame filering by FDF in SW. + +Unsupported HW features: + +* Gateway function +* Message buffer number Transmission Priority +* DLC filtering +* Mirror mode +* Common FIFO is not used +* TXQ is not used +* TX message timestamping; +* Timestamp source selection +* Interval transmission function +* Global test modes +* Power management +* Bus traffic measurement + +The CAN-FD subsystem is **not** enabled by default in rz_g3s_defconfig. To enable Zephyr +CAN functionality and RZ G3S CAN-FD driver below Kconfig options has to be enabled: + +.. code-block:: text + + CONFIG_CAN=y + CONFIG_CAN_FD_MODE=y + /* RZ G3S CAN-FD driver automatically enabled if corresponding DT node is enabled */ + CONFIG_CAN_RZGS_FD=y + /* optional */ + CONFIG_CAN_AUTO_BUS_OFF_RECOVERY=y + /* optional */ + ONFIG_STATS=y + /* optional */ + CONFIG_CAN_STATS=y + /* optional */ + CONFIG_CAN_RX_TIMESTAMP=y + +The RZ G3S CAN-FD driver code can be found at: + +.. code-block:: text + + drivers/can/can_rzg3s_fd.c + drivers/can/can_rzg3s_fd.h + drivers/can/Kconfig.rzg3s + +The RZ G3S CAN-FD driver Kconfig parameters are listed below: + +.. raw:: latex + + \begin{scriptsize} + ++---------------------------+--------+------------------------------------------------------------------------+ +| option | default| comment | ++===========================+========+========================================================================+ +| CONFIG_CAN_MAX_FILTER | 32 | Number of AFL entries per each CAN-FD channel. | +| | | All CAN-FD channels will use the same value. | ++---------------------------+--------+------------------------------------------------------------------------+ +| CONFIG_CAN_RZGS_FD_MAX_RX | 32 | Maximum number of RX FIFO buffers. Used to configure CFDRFCCn.RFDC. | +| | | All CAN-FD channels will use the same value. | ++---------------------------+--------+------------------------------------------------------------------------+ +| CONFIG_CAN_RZGS_FD_MAX_RX | 64 | Maximum size of RX Payload Data Size. Used to configure CFDRFCCn.RFPLS.| +| _DATA_SIZE | | All CAN-FD channels will use the same value. | ++---------------------------+--------+------------------------------------------------------------------------+ +| CONFIG_CAN_RZGS_FD_MAX_TX | 32 | Maximum number of TX message buffers per each CAN-FD channel. | +| | | All CAN-FD channels will use the same value. | ++---------------------------+--------+------------------------------------------------------------------------+ + +.. raw:: latex + + \end{scriptsize} + + +The RZ G3S CAN-FD DT node is defined in (dts/arm/renesas/rz/r9a08g045.dtsi) as: + +.. code-block:: dts + + canfd: can@400c0000 { + compatible = "renesas,r9a08g045-canfd", "renesas,rzg3s-canfd"; + reg = <0x400c0000 DT_SIZE_K(128)>; + interrupts = <373 0>, <374 0>; + interrupt-names = "g_err", "g_recc"; + clocks = <&cpg CPG_MOD R9A08G045_CANFD_CLK_RAM>, + <&cpg CPG_MOD R9A08G045_CANFD_PCLK>, + <&can_clk>; + clock-names = "fck", "canfd", "can_clk"; + resets = <&cpg_rctl R9A08G045_CANFD_RSTP_N>, + <&cpg_rctl R9A08G045_CANFD_RSTC_N>; + reset-names = "rstp_n", "rstc_n"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + canfd0: channel@0 { + reg = <0x0>; + interrupts = <375 0>, <377 0>, <379 0>; + interrupt-names = "ch_rec", "ch_err", "ch_trx"; + status = "disabled"; + }; + + canfd1: channel@1 { + reg = <0x1>; + interrupts = <376 0>, <378 0>, <380 0>; + interrupt-names = "ch_rec", "ch_err", "ch_trx"; + status = "disabled"; + }; + }; + +Each RZ G3S CAN-FD channel implemented as Zephyr CAN device and can be used independently. +The RZ G3S CAN-FD has to be enabled and configured in board DTS files to become available. +The RZ G3S CAN-FD configuration example can be found at: + +.. code-block:: text + + boards/arm/rz_g3s/rz_g3s_canfd.dtsi + snippets/rz-g3s-canfd0-test/rz-g3s-canfd0-test.overlay + snippets/rz-g3s-canfd0-test/rz-g3s-canfd1-test.overlay + +The RZ G3S CAN-FD channel's DT parameters are listed below: + +.. raw:: latex + + \begin{scriptsize} + ++-----------------------------------+----------------+---------------------------------------------------------------------------+ +| Name | Default | Comment | ++===================================+================+===========================================================================+ +| reg | 0|1 | Should be 0 for channel0 and 1 for channel1 | ++-----------------------------------+----------------+---------------------------------------------------------------------------+ +| bus-speed | board specific | Nominal Initial bitrate in bit/s | ++-----------------------------------+----------------+---------------------------------------------------------------------------+ +| sample-point | board specific | Initial sample point in per mille (e.g. 875 equals 87.5%). | +| | | Used to calculate and configure Nominal Bit Rate Configuration (CFDCnNCFG)| +| | | parameters. | ++-----------------------------------+----------------+---------------------------------------------------------------------------+ +| bus-speed-data | board specific | InitialInitial data phase bitrate in bit/s. | ++-----------------------------------+----------------+---------------------------------------------------------------------------+ +| sample-point-data | board specific | Initial data phase sample point in per mille (e.g. 875 equals 87.5%). | +| | | Used to calculate and configure Data Bit Rate Configuration (CFDCnDCFG) | +| | | parameters. | ++-----------------------------------+----------------+---------------------------------------------------------------------------+ +| phys | board specific,| Actively controlled CAN transceiver. | +| | optional | | ++-----------------------------------+----------------+---------------------------------------------------------------------------+ +| can-transceiver | board specific,| Passive CAN transceiver. The child node must be named "can-transceiver". | +| | optional | | ++-----------------------------------+----------------+---------------------------------------------------------------------------+ +| tx-delay-comp-offset | 0, | Transceiver Delay Compensation Offset, used as CFDCnFDCFG.TDCO. | +| | board specific,| | +| | optional | Transceiver Delay Compensation is enabled if this parameter != 0. | ++-----------------------------------+----------------+---------------------------------------------------------------------------+ +| renesas,tx-delay-comp-offset-only | false, | Only Transceiver Delay Compensation Offset is used when specified. | +| | board specific,| Used to set CFDCnFDCFG.TDCOC=1. | +| | optional | Valid when tx-delay-comp-offset != 0. | ++-----------------------------------+----------------+---------------------------------------------------------------------------+ + +.. raw:: latex + + \end{scriptsize} + +CAN-FD TX path +`````````````` +The RZ G3S CAN-FD driver uses TX Message Buffers (TMB) for sending CAN Frames. +For each TX CAN Frame the optional callback is saved and called from TX ("ch_trx") IRQ on TX Frame sending completion. +The CAN Frames are sent using CAN ID priority as priority, the ID priority complies with the CAN bus arbitration rule +(as specified in ISO 11898-1 specification). + +.. code-block:: text + + Zephyr | RZ G3S CAN-FD driver + | +----------------------------------+ + | |RZ G3S CAN-FD IP | + | | | + can_send | +-------------+ | +-------------+ | + ----------+-----+-----> CAN Frame +-------> | +-----------+ | + | | | | | | TMB_0 +----> TX | | + | | +-------------+ | +-------------+ | | | + | | |tx_callback | | | ... | | +-----> + | +-----> | | | +----> | | + | +----------+--+ | +-------------+ | | | + | | | | | | | | + | | | | TMB_X +----> | | + | | | +-------------+ | | | + | | | | | | + | | | +----+------+ | + | v | | | + tx_callback()| +---+ | TX ("ch_trx") IRQ | | + <---------+-------------------+ + |<--------------------------------+ | + | +---+ | | + +----------------------------------+ + +Transmission modes: + +* Regular (CAN_MODE_ONE_SHOT is not set) - When arbitration is lost or an error occurs, + message transmission will be attempted further if no transmission abort request is set for this TMB. +* One-shot (CAN_MODE_ONE_SHOT is not set) - CAM-FD attempts to transmit a message only once and + additional message transmission will not be attempted in this case. + +In case of the listen-only (CAN_MODE_LISTENONLY) mode - the TX function is prohibited +and all TX requests will be rejected by driver. + +CAN-FD RX path +`````````````` +The RZ G3S CAN-FD driver uses one RX FIFO per channel (channel 0 uses RX FIFO0, channel 1 uses RX FIFO1) +for receiving CAN Frames. Maximum number of stored CAN frames defined by CONFIG_CAN_RZGS_FD_MAX_RX Kconfig option. +The CAN Frames are dropped if RX FIFO is full. +The CAN-FD generates Global interrupt for successful reception into any of the RX FIFO buffers (RX "g_recc" IRQ). + +CAN frames are stored in RX FIFO if they passes Acceptance Filtering check according to configured AFL Entries. +The RZ G3S CAN-FD stores the "Global Acceptance Filter List Pointer", corresponding to AFL Entry number for +which Acceptance Filtering check has passed, with received CAN frame. This "Global Acceptance Filter List Pointer" +then retrieved from RX FIFO Access Message Buffer Component as "RX FIFO Buffer Pointer Field" CFDRFFDSTSn.CFDRFPTR, +and it is used to identify AFL Entry and call .rx_callback() assigned to it. + +.. code-block:: text + + Zephyr | RZ G3S CAN-FD driver +-----------------------------------+ + | |RZ G3S CAN-FD IP | + | | +--------------+ | + | | |RX FIFO | | + | RX "g_recc" IRQ | | +----------+ | +----------+ | + | +------------------------------------| | | |RX | | + | | CFDRFPTR == GAFLPTR | | +----------+ | | | | + | | | | | | | | | | + | | | | +----------+ | | | | + | | +----------------------+ | | | | | | <----- + | | | AFL | | | +-----^----+ | | | | + | | | +------------+ | | | | | | | | + | +------>|AFL entry 0 | | | +-------|------+ | | | + | | +--+---------+--+ | | | | | | + | | |GAFLPTR | | | +------------+ | | + rx_callback()| | +------------+ | | +----^-----+ | + <-------------------+rx_callback | | | | | + | | +--+---------+--+ | | +---------------+ | | + | | |AFL entry X | | | | AFL | | | + | | +--+---------+--+ +------------> +---+ | + can_add_rx_filter()| | |GAFLPTR | | | | | | + --------------> +------------+ | | +---------------+ | + | | |rx_callback | | | | + | | +------------+ | | | + | | | | | + | +----------------------+ +-----------------------------------+ + +CAN-FD statistic +```````````````` +The RZ G3S CAN-FD driver supports set of statistic groups, which names are listed below: + +* global - "can_rzg3s_global" +* per CAN channel - "can_channel@X", "can_rzg3s_chX" (X is channel id 0,1). + +The statistic is available when enabled by Kconfig option `CONFIG_CAN_STATS`. + +The "can_channel@X" group provides per-channel statistic information as described in +Zephyr :ref:`can_api` System interface. + +The "can_rzg3s_chX" group is RZ G3S CAN-FD driver specific and provides per-channel statistic +information not covered by "can_channel@X" group. + +The "can_rzg3s_global" group provides Global statistic information collected by RZ G3S CAN-FD driver. + +The RZ G3S CAN-FD driver statistic output provided below: + +.. code-block:: console + + Stats Group can_rzg3s_global (hdr addr: 0x20052784) + ecc_error_ch0 (offset: 24, addr: 0x2005279c): 0 + ecc_error_ch1 (offset: 28, addr: 0x200527a0): 0 + canfd_msg_payload_overflow (offset: 32, addr: 0x200527a4): 0 + rx_msg_lost_rfifo0 (offset: 36, addr: 0x200527a8): 0 + rx_msg_lost_rfifo1 (offset: 40, addr: 0x200527ac): 0 + Stats Group can_channel@0 (hdr addr: 0x200510e8) + bit0_error (offset: 24, addr: 0x20051100): 0 + bit1_error (offset: 28, addr: 0x20051104): 0 + stuff_error (offset: 32, addr: 0x20051108): 0 + crc_error (offset: 36, addr: 0x2005110c): 0 + form_error (offset: 40, addr: 0x20051110): 0 + ack_error (offset: 44, addr: 0x20051114): 0 + rx_overrun (offset: 48, addr: 0x20051118): 0 + Stats Group can_rzg3s_ch0 (hdr addr: 0x20052720) + arbitration_lost (offset: 24, addr: 0x20052738): 0 + bus_lock (offset: 28, addr: 0x2005273c): 0 + error_active_state (offset: 32, addr: 0x20052740): 1 + error_warning_state (offset: 36, addr: 0x20052744): 0 + error_passive_state (offset: 40, addr: 0x20052748): 0 + bus_off_state (offset: 44, addr: 0x2005274c): 0 + bus_off_recovery (offset: 48, addr: 0x20052750): 0 + bus_off_recovery_manual (offset: 52, addr: 0x20052754): 0 + tdc_violation (offset: 56, addr: 0x20052758): 0 + Stats Group can_channel@1 (hdr addr: 0x200510b0) + bit0_error (offset: 24, addr: 0x200510c8): 0 + bit1_error (offset: 28, addr: 0x200510cc): 0 + stuff_error (offset: 32, addr: 0x200510d0): 0 + crc_error (offset: 36, addr: 0x200510d4): 0 + form_error (offset: 40, addr: 0x200510d8): 0 + ack_error (offset: 44, addr: 0x200510dc): 0 + rx_overrun (offset: 48, addr: 0x200510e0): 0 + Stats Group can_rzg3s_ch1 (hdr addr: 0x20052510) + arbitration_lost (offset: 24, addr: 0x20052528): 0 + bus_lock (offset: 28, addr: 0x2005252c): 0 + error_active_state (offset: 32, addr: 0x20052530): 0 + error_warning_state (offset: 36, addr: 0x20052534): 0 + error_passive_state (offset: 40, addr: 0x20052538): 0 + bus_off_state (offset: 44, addr: 0x2005253c): 0 + bus_off_recovery (offset: 48, addr: 0x20052540): 0 + bus_off_recovery_manual (offset: 52, addr: 0x20052544): 0 + tdc_violation (offset: 56, addr: 0x20052548): 0 + +CAN-FD testing +-------------- + +For proper test/samples running two Zephyr snippets **rz-g3s-canfd0-test** and +**rz-g3s-canfd10-test** have been added to allow test/samples +execution for CAN-FD channels 0 and 1. + +The CAN-FD shippets code can be found at:: + + snippets/rz-g3s-canfd0-test + snippets/rz-g3s-canfd1-test + +To run test/samples for CAN-FD channels 0 use build command as below: + +.. code-block:: bash + + west build -b rz_g3s -p always -S rz-g3s-canfd0-test + +To run test/samples for CAN-FD channels 1 use build command as below: + +.. code-block:: bash + + west build -b rz_g3s -p always -S rz-g3s-canfd1-test + +.. toctree:: + :maxdepth: 4 + + canfd_api_test.rst + canfd_api_timing.rst + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/canfd/canfd_api_test.rst b/boards/arm/rz_g3s/doc/canfd/canfd_api_test.rst new file mode 100644 index 00000000000000..dfd07772dc18a9 --- /dev/null +++ b/boards/arm/rz_g3s/doc/canfd/canfd_api_test.rst @@ -0,0 +1,451 @@ +Channel0 tests/drivers/can/api +`````````````````````````````` + +The **tests/drivers/can/api** test is intended to perform full testing of Zephyr CAN API +interaction with RZ G3S CAN-FD driver in loopback CAN test mode. + +To build **tests/drivers/can/api** test for CAN-FD channel 0 run command: + +.. code-block:: bash + + west build -b rz_g3s -p always -S rz-g3s-canfd0-test tests/drivers/can/api + +The **tests/drivers/can/api** test will produce below console output when executed: + +.. code-block:: console + + I: can@400c0000:"CANFD IP init done ver:31240143 pclk:80000000Hz ext_clk:0Hz" + I: channel@0:"init done" + I: channel@1:"init done" + *** Booting Zephyr OS build v3.5.0-rc2-299-g93cceb9be768 *** + Running TESTSUITE can_classic + =================================================================== + START - test_add_filter + PASS - test_add_filter in 0.002 seconds + =================================================================== + START - test_filters_added_while_stopped + PASS - test_filters_added_while_stopped in 0.103 seconds + =================================================================== + START - test_filters_preserved_through_bitrate_change + PASS - test_filters_preserved_through_bitrate_change in 0.105 seconds + =================================================================== + START - test_filters_preserved_through_mode_change + PASS - test_filters_preserved_through_mode_change in 0.105 seconds + =================================================================== + START - test_get_capabilities + PASS - test_get_capabilities in 0.002 seconds + =================================================================== + START - test_get_core_clock + PASS - test_get_core_clock in 0.002 seconds + =================================================================== + START - test_get_state + PASS - test_get_state in 0.002 seconds + =================================================================== + START - test_max_ext_filters + E: channel@0:"AFLADD: no free entries" + PASS - test_max_ext_filters in 0.008 seconds + =================================================================== + START - test_max_std_filters + E: channel@0:"AFLADD: no free entries" + PASS - test_max_std_filters in 0.008 seconds + =================================================================== + START - test_receive_timeout + PASS - test_receive_timeout in 0.102 seconds + =================================================================== + START - test_recover + PASS - test_recover in 0.002 seconds + =================================================================== + START - test_recover_while_stopped + PASS - test_recover_while_stopped in 0.102 seconds + =================================================================== + START - test_send_and_forget + PASS - test_send_and_forget in 0.003 seconds + =================================================================== + START - test_send_callback + PASS - test_send_callback in 0.002 seconds + =================================================================== + START - test_send_fd_format + E: channel@0:"TX: unsupported frame flags 0x04" + PASS - test_send_fd_format in 0.005 seconds + =================================================================== + START - test_send_invalid_dlc + E: channel@0:"TX: frame dlc 9 exceeds maximum (8)" + PASS - test_send_invalid_dlc in 0.005 seconds + =================================================================== + START - test_send_receive_ext_id + PASS - test_send_receive_ext_id in 0.005 seconds + =================================================================== + START - test_send_receive_ext_id_masked + PASS - test_send_receive_ext_id_masked in 0.005 seconds + =================================================================== + START - test_send_receive_ext_id_rtr + PASS - test_send_receive_ext_id_rtr in 0.207 seconds + =================================================================== + START - test_send_receive_msgq + PASS - test_send_receive_msgq in 0.015 seconds + =================================================================== + START - test_send_receive_std_id + PASS - test_send_receive_std_id in 0.005 seconds + =================================================================== + START - test_send_receive_std_id_masked + PASS - test_send_receive_std_id_masked in 0.005 seconds + =================================================================== + START - test_send_receive_std_id_rtr + PASS - test_send_receive_std_id_rtr in 0.206 seconds + =================================================================== + START - test_send_receive_wrong_id + PASS - test_send_receive_wrong_id in 0.102 seconds + =================================================================== + START - test_send_while_stopped + PASS - test_send_while_stopped in 0.102 seconds + =================================================================== + START - test_set_bitrate + PASS - test_set_bitrate in 0.102 seconds + =================================================================== + START - test_set_bitrate_too_high + PASS - test_set_bitrate_too_high in 0.102 seconds + =================================================================== + START - test_set_bitrate_while_started + PASS - test_set_bitrate_while_started in 0.002 seconds + =================================================================== + START - test_set_mode_while_started + PASS - test_set_mode_while_started in 0.002 seconds + =================================================================== + START - test_set_state_change_callback + PASS - test_set_state_change_callback in 0.001 seconds + =================================================================== + START - test_set_timing_while_started + PASS - test_set_timing_while_started in 0.002 seconds + =================================================================== + START - test_start_while_started + I: channel@0:"start: already started" + PASS - test_start_while_started in 0.004 seconds + =================================================================== + START - test_stop_while_stopped + PASS - test_stop_while_stopped in 0.102 seconds + =================================================================== + TESTSUITE can_classic succeeded + Running TESTSUITE can_utilities + =================================================================== + START - test_can_bytes_to_dlc + PASS - test_can_bytes_to_dlc in 0.001 seconds + =================================================================== + START - test_can_dlc_to_bytes + PASS - test_can_dlc_to_bytes in 0.001 seconds + =================================================================== + START - test_can_frame_matches_filter + PASS - test_can_frame_matches_filter in 0.001 seconds + =================================================================== + TESTSUITE can_utilities succeeded + Running TESTSUITE canfd + =================================================================== + START - test_filters_preserved_through_classic_to_fd_mode_change + PASS - test_filters_preserved_through_classic_to_fd_mode_change in 0.307 seconds + =================================================================== + START - test_filters_preserved_through_fd_to_classic_mode_change + PASS - test_filters_preserved_through_fd_to_classic_mode_change in 0.307 seconds + =================================================================== + START - test_get_capabilities + PASS - test_get_capabilities in 0.001 seconds + =================================================================== + START - test_send_receive_classic + PASS - test_send_receive_classic in 0.005 seconds + =================================================================== + START - test_send_receive_fd + PASS - test_send_receive_fd in 0.004 seconds + =================================================================== + START - test_send_receive_mixed + PASS - test_send_receive_mixed in 0.004 seconds + =================================================================== + START - test_set_bitrate_data_while_started + PASS - test_set_bitrate_data_while_started in 0.002 seconds + =================================================================== + START - test_set_timing_data_while_started + PASS - test_set_timing_data_while_started in 0.002 seconds + =================================================================== + TESTSUITE canfd succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [can_classic]: pass = 33, fail = 0, skip = 0, total = 33 duration = 1.527 + seconds + - PASS - [can_classic.test_add_filter] duration = 0.002 seconds + - PASS - [can_classic.test_filters_added_while_stopped] duration = 0.103 seconds + - PASS - [can_classic.test_filters_preserved_through_bitrate_change] duration = 0.105 seconds + - PASS - [can_classic.test_filters_preserved_through_mode_change] duration = 0.105 seconds + - PASS - [can_classic.test_get_capabilities] duration = 0.002 seconds + - PASS - [can_classic.test_get_core_clock] duration = 0.002 seconds + - PASS - [can_classic.test_get_state] duration = 0.002 seconds + - PASS - [can_classic.test_max_ext_filters] duration = 0.008 seconds + - PASS - [can_classic.test_max_std_filters] duration = 0.008 seconds + - PASS - [can_classic.test_receive_timeout] duration = 0.102 seconds + - PASS - [can_classic.test_recover] duration = 0.002 seconds + - PASS - [can_classic.test_recover_while_stopped] duration = 0.102 seconds + - PASS - [can_classic.test_send_and_forget] duration = 0.003 seconds + - PASS - [can_classic.test_send_callback] duration = 0.002 seconds + - PASS - [can_classic.test_send_fd_format] duration = 0.005 seconds + - PASS - [can_classic.test_send_invalid_dlc] duration = 0.005 seconds + - PASS - [can_classic.test_send_receive_ext_id] duration = 0.005 seconds + - PASS - [can_classic.test_send_receive_ext_id_masked] duration = 0.005 seconds + - PASS - [can_classic.test_send_receive_ext_id_rtr] duration = 0.207 seconds + - PASS - [can_classic.test_send_receive_msgq] duration = 0.015 seconds + - PASS - [can_classic.test_send_receive_std_id] duration = 0.005 seconds + - PASS - [can_classic.test_send_receive_std_id_masked] duration = 0.005 seconds + - PASS - [can_classic.test_send_receive_std_id_rtr] duration = 0.206 seconds + - PASS - [can_classic.test_send_receive_wrong_id] duration = 0.102 seconds + - PASS - [can_classic.test_send_while_stopped] duration = 0.102 seconds + - PASS - [can_classic.test_set_bitrate] duration = 0.102 seconds + - PASS - [can_classic.test_set_bitrate_too_high] duration = 0.102 seconds + - PASS - [can_classic.test_set_bitrate_while_started] duration = 0.002 seconds + - PASS - [can_classic.test_set_mode_while_started] duration = 0.002 seconds + - PASS - [can_classic.test_set_state_change_callback] duration = 0.001 seconds + - PASS - [can_classic.test_set_timing_while_started] duration = 0.002 seconds + - PASS - [can_classic.test_start_while_started] duration = 0.004 seconds + - PASS - [can_classic.test_stop_while_stopped] duration = 0.102 seconds + + SUITE PASS - 100.00% [can_utilities]: pass = 3, fail = 0, skip = 0, total = 3 duration = 0.003 + seconds + - PASS - [can_utilities.test_can_bytes_to_dlc] duration = 0.001 seconds + - PASS - [can_utilities.test_can_dlc_to_bytes] duration = 0.001 seconds + - PASS - [can_utilities.test_can_frame_matches_filter] duration = 0.001 seconds + + SUITE PASS - 100.00% [canfd]: pass = 8, fail = 0, skip = 0, total = 8 duration = 0.632 seconds + - PASS - [canfd.test_filters_preserved_through_classic_to_fd_mode_change] duration = 0.307 seconds + - PASS - [canfd.test_filters_preserved_through_fd_to_classic_mode_change] duration = 0.307 seconds + - PASS - [canfd.test_get_capabilities] duration = 0.001 seconds + - PASS - [canfd.test_send_receive_classic] duration = 0.005 seconds + - PASS - [canfd.test_send_receive_fd] duration = 0.004 seconds + - PASS - [canfd.test_send_receive_mixed] duration = 0.004 seconds + - PASS - [canfd.test_set_bitrate_data_while_started] duration = 0.002 seconds + - PASS - [canfd.test_set_timing_data_while_started] duration = 0.002 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL + +Channel1 tests/drivers/can/api +`````````````````````````````` + +The **tests/drivers/can/api** test is intended to perform full testing of Zephyr CAN API +interaction with RZ G3S CAN-FD driver in loopback CAN test mode. + +To build **tests/drivers/can/api** test for CAN-FD channel 1 run command: + +.. code-block:: bash + + west build -b rz_g3s -p always -S rz-g3s-canfd1-test tests/drivers/can/api + +The **tests/drivers/can/api** test will produce below console output when executed: + +.. code-block:: console + + I: can@400c0000:"CANFD IP init done ver:31240143 pclk:80000000Hz ext_clk:0Hz" + I: channel@0:"init done" + I: channel@1:"init done" + *** Booting Zephyr OS build v3.5.0-rc2-299-g93cceb9be768 *** + Running TESTSUITE can_classic + =================================================================== + START - test_add_filter + PASS - test_add_filter in 0.002 seconds + =================================================================== + START - test_filters_added_while_stopped + PASS - test_filters_added_while_stopped in 0.103 seconds + =================================================================== + START - test_filters_preserved_through_bitrate_change + PASS - test_filters_preserved_through_bitrate_change in 0.105 seconds + =================================================================== + START - test_filters_preserved_through_mode_change + PASS - test_filters_preserved_through_mode_change in 0.105 seconds + =================================================================== + START - test_get_capabilities + PASS - test_get_capabilities in 0.002 seconds + =================================================================== + START - test_get_core_clock + PASS - test_get_core_clock in 0.002 seconds + =================================================================== + START - test_get_state + PASS - test_get_state in 0.002 seconds + =================================================================== + START - test_max_ext_filters + E: channel@1:"AFLADD: no free entries" + PASS - test_max_ext_filters in 0.008 seconds + =================================================================== + START - test_max_std_filters + E: channel@1:"AFLADD: no free entries" + PASS - test_max_std_filters in 0.008 seconds + =================================================================== + START - test_receive_timeout + PASS - test_receive_timeout in 0.102 seconds + =================================================================== + START - test_recover + PASS - test_recover in 0.002 seconds + =================================================================== + START - test_recover_while_stopped + PASS - test_recover_while_stopped in 0.102 seconds + =================================================================== + START - test_send_and_forget + PASS - test_send_and_forget in 0.003 seconds + =================================================================== + START - test_send_callback + PASS - test_send_callback in 0.002 seconds + =================================================================== + START - test_send_fd_format + E: channel@1:"TX: unsupported frame flags 0x04" + PASS - test_send_fd_format in 0.005 seconds + =================================================================== + START - test_send_invalid_dlc + E: channel@1:"TX: frame dlc 9 exceeds maximum (8)" + PASS - test_send_invalid_dlc in 0.005 seconds + =================================================================== + START - test_send_receive_ext_id + PASS - test_send_receive_ext_id in 0.005 seconds + =================================================================== + START - test_send_receive_ext_id_masked + PASS - test_send_receive_ext_id_masked in 0.005 seconds + =================================================================== + START - test_send_receive_ext_id_rtr + PASS - test_send_receive_ext_id_rtr in 0.207 seconds + =================================================================== + START - test_send_receive_msgq + PASS - test_send_receive_msgq in 0.015 seconds + =================================================================== + START - test_send_receive_std_id + PASS - test_send_receive_std_id in 0.005 seconds + =================================================================== + START - test_send_receive_std_id_masked + PASS - test_send_receive_std_id_masked in 0.005 seconds + =================================================================== + START - test_send_receive_std_id_rtr + PASS - test_send_receive_std_id_rtr in 0.206 seconds + =================================================================== + START - test_send_receive_wrong_id + PASS - test_send_receive_wrong_id in 0.102 seconds + =================================================================== + START - test_send_while_stopped + PASS - test_send_while_stopped in 0.102 seconds + =================================================================== + START - test_set_bitrate + PASS - test_set_bitrate in 0.102 seconds + =================================================================== + START - test_set_bitrate_too_high + PASS - test_set_bitrate_too_high in 0.102 seconds + =================================================================== + START - test_set_bitrate_while_started + PASS - test_set_bitrate_while_started in 0.002 seconds + =================================================================== + START - test_set_mode_while_started + PASS - test_set_mode_while_started in 0.002 seconds + =================================================================== + START - test_set_state_change_callback + PASS - test_set_state_change_callback in 0.001 seconds + =================================================================== + START - test_set_timing_while_started + PASS - test_set_timing_while_started in 0.002 seconds + =================================================================== + START - test_start_while_started + I: channel@1:"start: already started" + PASS - test_start_while_started in 0.004 seconds + =================================================================== + START - test_stop_while_stopped + PASS - test_stop_while_stopped in 0.102 seconds + =================================================================== + TESTSUITE can_classic succeeded + Running TESTSUITE can_utilities + =================================================================== + START - test_can_bytes_to_dlc + PASS - test_can_bytes_to_dlc in 0.001 seconds + =================================================================== + START - test_can_dlc_to_bytes + PASS - test_can_dlc_to_bytes in 0.001 seconds + =================================================================== + START - test_can_frame_matches_filter + PASS - test_can_frame_matches_filter in 0.001 seconds + =================================================================== + TESTSUITE can_utilities succeeded + Running TESTSUITE canfd + =================================================================== + START - test_filters_preserved_through_classic_to_fd_mode_change + PASS - test_filters_preserved_through_classic_to_fd_mode_change in 0.307 seconds + =================================================================== + START - test_filters_preserved_through_fd_to_classic_mode_change + PASS - test_filters_preserved_through_fd_to_classic_mode_change in 0.307 seconds + =================================================================== + START - test_get_capabilities + PASS - test_get_capabilities in 0.001 seconds + =================================================================== + START - test_send_receive_classic + PASS - test_send_receive_classic in 0.005 seconds + =================================================================== + START - test_send_receive_fd + PASS - test_send_receive_fd in 0.004 seconds + =================================================================== + START - test_send_receive_mixed + PASS - test_send_receive_mixed in 0.004 seconds + =================================================================== + START - test_set_bitrate_data_while_started + PASS - test_set_bitrate_data_while_started in 0.002 seconds + =================================================================== + START - test_set_timing_data_while_started + PASS - test_set_timing_data_while_started in 0.002 seconds + =================================================================== + TESTSUITE canfd succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [can_classic]: pass = 33, fail = 0, skip = 0, total = 33 duration = 1.527 + seconds + - PASS - [can_classic.test_add_filter] duration = 0.002 seconds + - PASS - [can_classic.test_filters_added_while_stopped] duration = 0.103 seconds + - PASS - [can_classic.test_filters_preserved_through_bitrate_change] duration = 0.105 seconds + - PASS - [can_classic.test_filters_preserved_through_mode_change] duration = 0.105 seconds + - PASS - [can_classic.test_get_capabilities] duration = 0.002 seconds + - PASS - [can_classic.test_get_core_clock] duration = 0.002 seconds + - PASS - [can_classic.test_get_state] duration = 0.002 seconds + - PASS - [can_classic.test_max_ext_filters] duration = 0.008 seconds + - PASS - [can_classic.test_max_std_filters] duration = 0.008 seconds + - PASS - [can_classic.test_receive_timeout] duration = 0.102 seconds + - PASS - [can_classic.test_recover] duration = 0.002 seconds + - PASS - [can_classic.test_recover_while_stopped] duration = 0.102 seconds + - PASS - [can_classic.test_send_and_forget] duration = 0.003 seconds + - PASS - [can_classic.test_send_callback] duration = 0.002 seconds + - PASS - [can_classic.test_send_fd_format] duration = 0.005 seconds + - PASS - [can_classic.test_send_invalid_dlc] duration = 0.005 seconds + - PASS - [can_classic.test_send_receive_ext_id] duration = 0.005 seconds + - PASS - [can_classic.test_send_receive_ext_id_masked] duration = 0.005 seconds + - PASS - [can_classic.test_send_receive_ext_id_rtr] duration = 0.207 seconds + - PASS - [can_classic.test_send_receive_msgq] duration = 0.015 seconds + - PASS - [can_classic.test_send_receive_std_id] duration = 0.005 seconds + - PASS - [can_classic.test_send_receive_std_id_masked] duration = 0.005 seconds + - PASS - [can_classic.test_send_receive_std_id_rtr] duration = 0.206 seconds + - PASS - [can_classic.test_send_receive_wrong_id] duration = 0.102 seconds + - PASS - [can_classic.test_send_while_stopped] duration = 0.102 seconds + - PASS - [can_classic.test_set_bitrate] duration = 0.102 seconds + - PASS - [can_classic.test_set_bitrate_too_high] duration = 0.102 seconds + - PASS - [can_classic.test_set_bitrate_while_started] duration = 0.002 seconds + - PASS - [can_classic.test_set_mode_while_started] duration = 0.002 seconds + - PASS - [can_classic.test_set_state_change_callback] duration = 0.001 seconds + - PASS - [can_classic.test_set_timing_while_started] duration = 0.002 seconds + - PASS - [can_classic.test_start_while_started] duration = 0.004 seconds + - PASS - [can_classic.test_stop_while_stopped] duration = 0.102 seconds + + SUITE PASS - 100.00% [can_utilities]: pass = 3, fail = 0, skip = 0, total = 3 duration = 0.003 + seconds + - PASS - [can_utilities.test_can_bytes_to_dlc] duration = 0.001 seconds + - PASS - [can_utilities.test_can_dlc_to_bytes] duration = 0.001 seconds + - PASS - [can_utilities.test_can_frame_matches_filter] duration = 0.001 seconds + + SUITE PASS - 100.00% [canfd]: pass = 8, fail = 0, skip = 0, total = 8 duration = 0.632 seconds + - PASS - [canfd.test_filters_preserved_through_classic_to_fd_mode_change] duration = 0.307 seconds + - PASS - [canfd.test_filters_preserved_through_fd_to_classic_mode_change] duration = 0.307 seconds + - PASS - [canfd.test_get_capabilities] duration = 0.001 seconds + - PASS - [canfd.test_send_receive_classic] duration = 0.005 seconds + - PASS - [canfd.test_send_receive_fd] duration = 0.004 seconds + - PASS - [canfd.test_send_receive_mixed] duration = 0.004 seconds + - PASS - [canfd.test_set_bitrate_data_while_started] duration = 0.002 seconds + - PASS - [canfd.test_set_timing_data_while_started] duration = 0.002 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL diff --git a/boards/arm/rz_g3s/doc/canfd/canfd_api_timing.rst b/boards/arm/rz_g3s/doc/canfd/canfd_api_timing.rst new file mode 100644 index 00000000000000..3ae9b63ca1b15d --- /dev/null +++ b/boards/arm/rz_g3s/doc/canfd/canfd_api_timing.rst @@ -0,0 +1,74 @@ +Channel0 tests/drivers/can/timing +````````````````````````````````` + +The **tests/drivers/can/timing** test is intended to perform full testing of Zephyr CAN API +interaction with RZ G3S CAN-FD driver in loopback CAN test mode. + +To build **tests/drivers/can/timing** test for CAN-FD channel 0 run command: + +.. code-block:: bash + + west build -b rz_g3s -p always -S rz-g3s-canfd0-test tests/drivers/can/timing + +The **tests/drivers/can/api** test will produce below console output when executed: + +.. code-block:: console + + I: can@400c0000:"CANFD IP init done ver:31240143 pclk:80000000Hz ext_clk:0Hz" + I: channel@0:"init done" + I: channel@1:"init done" + *** Booting Zephyr OS build v3.5.0-rc2-299-g93cceb9be768 *** + Running TESTSUITE can_timing + =================================================================== + testing on device channel@0 @ 40000000 Hz + START - test_set_timing_data_max + PASS - test_set_timing_data_max in 0.001 seconds + =================================================================== + START - test_set_timing_data_min + PASS - test_set_timing_data_min in 0.001 seconds + =================================================================== + START - test_set_timing_max + PASS - test_set_timing_max in 0.001 seconds + =================================================================== + START - test_set_timing_min + PASS - test_set_timing_min in 0.001 seconds + =================================================================== + START - test_timing + testing bitrate 20000, sample point 87.5% (valid): sjw = 12, prop_seg = 0, phase_seg1 = 174, phase_se% + testing bitrate 50000, sample point 87.5% (valid): sjw = 12, prop_seg = 0, phase_seg1 = 174, phase_se% + testing bitrate 125000, sample point 87.5% (valid): sjw = 10, prop_seg = 0, phase_seg1 = 139, phase_s% + testing bitrate 250000, sample point 87.5% (valid): sjw = 10, prop_seg = 0, phase_seg1 = 139, phase_s% + testing bitrate 500000, sample point 87.5% (valid): sjw = 5, prop_seg = 0, phase_seg1 = 69, phase_seg% + testing bitrate 800000, sample point 80.0% (valid): sjw = 5, prop_seg = 0, phase_seg1 = 39, phase_seg% + testing bitrate 1000000, sample point 75.0% (valid): sjw = 5, prop_seg = 0, phase_seg1 = 29, phase_se% + testing bitrate 125000, sample point 90.0% (valid): sjw = 8, prop_seg = 0, phase_seg1 = 143, phase_se% + testing bitrate 125000, sample point 80.0% (valid): sjw = 32, prop_seg = 0, phase_seg1 = 255, phase_s% + testing bitrate 125000, sample point 100.0% (invalid): OK + testing bitrate 1000001, sample point 75.0% (invalid): OK + PASS - test_timing in 0.131 seconds + =================================================================== + START - test_timing_data + testing bitrate 500000, sample point 87.5% (valid): sjw = 1, prop_seg = 0, phase_seg1 = 13, phase_seg% + testing bitrate 1000000, sample point 75.0% (valid): sjw = 5, prop_seg = 0, phase_seg1 = 29, phase_se% + testing bitrate 500000, sample point 90.0% (valid): sjw = 1, prop_seg = 0, phase_seg1 = 17, phase_seg% + testing bitrate 500000, sample point 80.0% (valid): sjw = 4, prop_seg = 0, phase_seg1 = 31, phase_seg% + testing bitrate 500000, sample point 100.0% (invalid): OK + testing bitrate 8000001, sample point 75.0% (invalid): OK + PASS - test_timing_data in 0.064 seconds + =================================================================== + TESTSUITE can_timing succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [can_timing]: pass = 6, fail = 0, skip = 0, total = 6 duration = 0.199 seconds + - PASS - [can_timing.test_set_timing_data_max] duration = 0.001 seconds + - PASS - [can_timing.test_set_timing_data_min] duration = 0.001 seconds + - PASS - [can_timing.test_set_timing_max] duration = 0.001 seconds + - PASS - [can_timing.test_set_timing_min] duration = 0.001 seconds + - PASS - [can_timing.test_timing] duration = 0.131 seconds + - PASS - [can_timing.test_timing_data] duration = 0.064 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL diff --git a/boards/arm/rz_g3s/doc/conf.py b/boards/arm/rz_g3s/doc/conf.py new file mode 100644 index 00000000000000..cd2ecb00ec9758 --- /dev/null +++ b/boards/arm/rz_g3s/doc/conf.py @@ -0,0 +1,64 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +import sys + +sys.path.insert(0, "_extensions") + +project = 'Renesas RZ G3S Cortex-M33 Zephyr on SMARC Evaluation Board Kit' +copyright = 'Copyright (c) 2024 EPAM Systems' +author = 'EPAM' +release = 'v1.0.2' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + 'sphinx.ext.ifconfig', + 'sphinx.ext.todo', + 'zephyr.application', + 'rst2pdf.pdfbuilder', + 'sphinx.ext.intersphinx', +] + +templates_path = ['_templates'] +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +language = 'en' + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'alabaster' +html_static_path = ['_static'] + +# -- Options for todo extension ---------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/extensions/todo.html#configuration + +todo_include_todos = True + +latex_documents = [('index', 'rzg3s_release_notes.tex', project, author, 'manual')] + +latex_elements = { + 'papersize': 'a4paper', + 'classoptions': ',openany,oneside', + 'babel' : '\\usepackage[english]{babel}', + 'fvset' : '\\fvset{fontsize=\\scriptsize}', + 'preamble': r''' + \usepackage[none]{hyphenat} + ''' +} + +latexpdf_documents = [('index', 'rzg3s_release_notes.pdf', project, author, 'manual')] + +pdf_documents = [('index', u'pdf-name', u'Sample doc Title', u'author name')] + +intersphinx_mapping = {'zephyr': ('https://docs.zephyrproject.org/latest/', None)} + +def setup(app): + app.add_config_value('PDF_GEN', '', '1') diff --git a/boards/arm/rz_g3s/doc/cortex-m/fpu.rst b/boards/arm/rz_g3s/doc/cortex-m/fpu.rst new file mode 100644 index 00000000000000..fc4dfe63328ca0 --- /dev/null +++ b/boards/arm/rz_g3s/doc/cortex-m/fpu.rst @@ -0,0 +1,100 @@ +Cortex-M33 Floating-Point Unit (FPU) +==================================== + +FPU overview +------------ + +The Renesas RZ G3S SoC has one Cortex-M33_FPU (r0p4) System Core which has FPU implemented. + + +The Cortex-M33 Floating-Point Unit (FPU) implements the FPv5 floating-point extensions. +The FPU fully supports single-precision add, subtract, multiply, divide, multiply and +accumulate, and square root operations. +It also provides conversions between fixed-point and floating-point data formats, +and floating-point constant instructions. + +The FPU provides floating-point computation functionality that is compliant with +the ANSI/IEEE Std 754-2008, IEEE Standard for Binary Floating-Point Arithmetic, +referred to as the IEEE 754 standard. + +The FPU contains 32 single-precision extension registers, which you can also access +as 16 doubleword registers for load, store, and move operations. + +Refer to Arm® Cortex®-M33 Processor Revision: r0p4 Technical Reference Manual +for more information. + +FPU default configuration +------------------------- + +To build Zephyr for the Cortex-M33_FPU core the following board should be used: **rz_g3s_fpu**. +So target application can be built using command: + +.. code-block:: bash + + west build -b rz_g3s_fpu -p always + +.. note:: + + Refer to :ref:`rz_g3s_prog_debug` for more information about Cortex-M33_FPU System Core build instructions. + +The following configuration parameters will be automatically enabled: + +.. code-block:: text + + CONFIG_FPU=y + #if MULTITHREADING=y + CONFIG_FPU_SHARING=y + +FPU testing +----------- + +tests/kernel/fpu_sharing/generic +```````````````````````````````` + +To build **fpu_sharing/generic** test run command: + +.. code-block:: bash + + west build -b rz_g3s_fpu -p always tests/kernel/fpu_sharing/generic + +Once **fpu_sharing/generic** is loaded it will provide console output showing +the test execution process: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-230-gc935cfadb73a *** + Running TESTSUITE fpu_sharing_generic + =================================================================== + START - test_load_store + Load and store OK after 0 (high) + 2 (low) tests + Load and store OK after 100 (high) + 239 (low) tests + Load and store OK after 200 (high) + 476 (low) tests + Load and store OK after 300 (high) + 714 (low) tests + Load and store OK after 400 (high) + 952 (low) tests + Load and store OK after 500 (high) + 1188 (low) tests + PASS - test_load_store in 0.723 seconds + =================================================================== + START - test_pi + Pi calculation OK after 50 (high) + 0 (low) tests (computed 3.141598) + Pi calculation OK after 150 (high) + 2 (low) tests (computed 3.141598) + Pi calculation OK after 250 (high) + 3 (low) tests (computed 3.141598) + Pi calculation OK after 350 (high) + 5 (low) tests (computed 3.141598) + Pi calculation OK after 450 (high) + 6 (low) tests (computed 3.141598) + PASS - test_pi in 16.591 seconds + =================================================================== + TESTSUITE fpu_sharing_generic succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [fpu_sharing_generic]: pass = 2, fail = 0, skip = 0, total = 2 duration = 17.314s + - PASS - [fpu_sharing_generic.test_load_store] duration = 0.723 seconds + - PASS - [fpu_sharing_generic.test_pi] duration = 16.591 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/cortex-m/mpu.rst b/boards/arm/rz_g3s/doc/cortex-m/mpu.rst new file mode 100644 index 00000000000000..8f669bf6d228b5 --- /dev/null +++ b/boards/arm/rz_g3s/doc/cortex-m/mpu.rst @@ -0,0 +1,130 @@ +Cortex-M33 Memory Protection Unit (MPU) +======================================= + +MPU overview +------------ + +The Renesas RZ G3S SoC Cortex-M33/Cortex-M33_FPU (r0p4) have MPU built in. +The MPU improves system reliability by defining the memory attributes for +different memory regions. + +It provides up to 16 different regions. The MPU doesn't support overlapped +memory regions. + +When the Security Extension is included, there can be two MPUs, one Secure +and one Non-secure. Each MPU can define memory attributes independently. + +Refer to Arm® Cortex®-M33 Processor Revision: r0p4 Technical Reference Manual +for more information. + +MPU default configuration +------------------------- + +The MPU is enabled by default in ``rz_g3s_defconfig``. + +.. code-block:: text + + CONFIG_ARM_MPU=y + +At boot time Zephyr configures following static memory regions and regions defined in DT: + +.. raw:: latex + + \begin{scriptsize} + ++----------------+--------------------------------------------------------------+ +| Region | | ++================+==============================================================+ +| NULL | Optional. Any, used for null pointer dereference check | +| | | +| | Enabled in Kconfig | ++----------------+--------------------------------------------------------------+ +| vector | EXEC, P_RO_U_RO_Msk, NON_SHAREABLE_Msk | ++----------------+--------------------------------------------------------------+ +| SRAM_TEXT | EXEC, P_RO_U_RO_Msk, NON_SHAREABLE_Msk | ++----------------+--------------------------------------------------------------+ +| SRAM_RODATA | NOT_EXEC, P_RW_U_NA_Msk, NON_SHAREABLE_Msk | ++----------------+--------------------------------------------------------------+ +| DEVICE | Optional. NOT_EXEC, P_RW_U_NA_Msk, NON_SHAREABLE_Msk,NOCACHE | +| | | +| | Enabled if defined(CONFIG_MPU_DISABLE_BACKGROUND_MAP) | ++----------------+--------------------------------------------------------------+ + +.. raw:: latex + + \end{scriptsize} + +More regions can be added if specified properly in DT by using standard +Zephyr DT memory **"zephyr,memory-region"** bindigs. + +Refer to Zephyr :ref:`mem_mgmt_api` documentation. + +MPU testing +------------- + +samples/arch/mpu/mpu_test +````````````````````````` + +To build **mpu_test** test run command: + +.. code-block:: bash + + west build -b rz_g3s -p always samples/arch/mpu/mpu_test + +The **mpu_test** is not automatic test and required entering commands from +console and reboot after each test: + +.. code-block:: text + + mpu read + mpu write + mpu run + +The below is console output of test execution: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-230-ga80246d0863d *** + uart:~$ mpu read + + [00:00:05.979,000] os: ***** BUS FAULT ***** + [00:00:05.979,000] os: Precise data bus error + [00:00:05.979,000] os: BFAR Address: 0x24060000 + [00:00:05.979,000] os: r0/a1: 0x0002efe4 r1/a2: 0x00000008 r2/a3: 0x20061980 + [00:00:05.979,000] os: r3/a4: 0x24060000 r12/ip: 0x0003026a r14/lr: 0x000263eb + [00:00:05.979,000] os: xpsr: 0x21000000 + [00:00:05.979,000] os: Faulting instruction address (r15/pc): 0x00023c8a + [00:00:05.979,000] os: >>> ZEPHYR FATAL ERROR 25: Unknown error on CPU 0 + [00:00:05.979,000] os: Current thread: 0x20060668 (shell_uart) + [00:00:06.048,000] os: Halting system + + *** Booting Zephyr OS build v3.5.0-rc2-230-ga80246d0863d *** + uart:~$ mpu write + write address: 0 + [00:00:05.917,000] os: ***** MPU FAULT ***** + [00:00:05.917,000] os: Data Access Violation + [00:00:05.917,000] os: MMFAR Address: 0x27000 + [00:00:05.917,000] os: r0/a1: 0x00000000 r1/a2: 0x0000000e r2/a3: 0x0badc0de + [00:00:05.917,000] os: r3/a4: 0x00027000 r12/ip: 0x00000001 r14/lr: 0x00023c6f + [00:00:05.918,000] os: xpsr: 0x61000000 + [00:00:05.918,000] os: Faulting instruction address (r15/pc): 0x00023c76 + [00:00:05.918,000] os: >>> ZEPHYR FATAL ERROR 19: Unknown error on CPU 0 + [00:00:05.918,000] os: Current thread: 0x20060668 (shell_uart) + [00:00:05.987,000] os: Halting system + + *** Booting Zephyr OS build v3.5.0-rc2-230-ga80246d0863d *** + uart:~$ mpu run + + [00:00:13.740,000] os: ***** MPU FAULT ***** + [00:00:13.740,000] os: Instruction Access Violation + [00:00:13.740,000] os: r0/a1: 0x0002efe4 r1/a2: 0x00000001 r2/a3: 0x20061980 + [00:00:13.740,000] os: r3/a4: 0x20060000 r12/ip: 0x0003029d r14/lr: 0x00023c57 + [00:00:13.740,000] os: xpsr: 0x60000000 + [00:00:13.740,000] os: Faulting instruction address (r15/pc): 0x20060000 + [00:00:13.740,000] os: >>> ZEPHYR FATAL ERROR 20: Unknown error on CPU 0 + [00:00:13.740,000] os: Current thread: 0x20060668 (shell_uart) + [00:00:13.803,000] os: Halting system + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/cortex-m/sau.rst b/boards/arm/rz_g3s/doc/cortex-m/sau.rst new file mode 100644 index 00000000000000..9999ee835652bd --- /dev/null +++ b/boards/arm/rz_g3s/doc/cortex-m/sau.rst @@ -0,0 +1,44 @@ +Cortex-M33 Security attribution unit (SAU) +========================================== + +SAU overview +------------ + +The Renesas RZ G3S SoC has one Cortex-M33_FPU (r0p4) System Core which has SAU implemented. + +The SAU is a programmable unit that determines the security of an address. +The SAU is only implemented if the ARMv8-M Security Extension is included in the processor. +The number of regions that are included in the SAU is 8. + +For instructions and data, the SAU returns the security attribute that is associated with the address. + +For instructions, the attribute determines the allowable Security state of the processor when the instruction is executed. +It can also identify whether code at a Secure address can be called from Non-secure state. + +For data, the attribute determines whether a memory address can be accessed from Non-secure state, +and also whether the external memory request is marked as Secure or Non-secure. + +Refer to Arm® Cortex®-M33 Processor Revision: r0p4 Technical Reference Manual +for more information. + +SAU default configuration +------------------------- + +The Renesas RZ G3S Zephyr implementation declares ARM SAU support at SoC level by enabling +``CONFIG_CPU_HAS_ARM_SAU`` Kconfig option by default. This also enables below Kconfig options by default. + +.. code-block:: text + + CONFIG_CPU_HAS_TEE=y + CONFIG_ARMV8_M_SE=y + +SAU testing +----------- + +.. note:: + + the ARMv8-M Security Extension is not tested. + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/cortex-m/systick.rst b/boards/arm/rz_g3s/doc/cortex-m/systick.rst new file mode 100644 index 00000000000000..caaac2541cf533 --- /dev/null +++ b/boards/arm/rz_g3s/doc/cortex-m/systick.rst @@ -0,0 +1,39 @@ +Cortex-M33 System timer (SysTick) +================================= + +SysTick overview +---------------- + +The Renesas RZ G3S SoC has the SysTick timers in the Cortex-M33/Cortex-M33_FPU. + +* There is one Secure SysTick timer and one Non-secure SysTick timer. +* The count cycle of SysTick timers is common to Secure and Non-secure. + +Refer to Arm® Cortex®-M33 Processor Revision: r0p4 Technical Reference Manual +for more information. + +SysTick driver overview +----------------------- + +The ARM SysTick serves function of Zephyr Kernel System clock as described +in :ref:`kernel_timing` documentation. + +Zephyr has generic support for the ARM SysTick which is enabled for +the Renesas RZ G3S Soc by declaring ``CONFIG_CPU_CORTEX_M_HAS_SYSTICK`` Kconfig option by default. +This also enables below Kconfig options by default. + +.. code-block:: text + + CONFIG_CPU_CORTEX_M_HAS_SYSTICK=y + CONFIG_CORTEX_M_SYSTICK=y + +The generic Zephyr ARM Cortex-M SYSTICK timer driver code can be found at: + +.. code-block:: text + + drivers/timer/cortex_m_systick.c + drivers/timer/Kconfig.cortex_m_systick + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/cpg/cpg.rst b/boards/arm/rz_g3s/doc/cpg/cpg.rst new file mode 100644 index 00000000000000..2b20671dd13169 --- /dev/null +++ b/boards/arm/rz_g3s/doc/cpg/cpg.rst @@ -0,0 +1,130 @@ +Clock Pulse Generator (CPG) +=========================== + +CPG overview +------------- + +Features: + +* PLL control +* Clock generation and control +* Reset generation and control +* PLL clock/Clock/Reset Monitor + +Refer to "Clock Pulse Generator (CPG)" section in "Renesas RZ/G3S Group User’s Manual: Hardware". + +Refer to "Low Power Consumption" section in "Renesas RZ/G3S Group User’s Manual: Hardware". + +Refer to "Renesas RZ/G3S clock_list_r1.00" document. + +CPG driver overview +------------------- + +The RZ G3S CPG driver provides Zephyr System :ref:`clock_control_api` and +:ref:`reset_api` API which are implemented as separate Zephyr drivers: + +* clock controller driver +* reset controller driver + +The CPG Clock controller driver provides Zephyr System Clock Control API to enable +HW module clock (CPG_CLKON_xx) and manage Module Standby Mode (CPG_BUS_xx_MSTOP). +In the current implementation the Module Standby Mode (MSTOP) is +cleared together with enabling HW module clock. + +Hence, the Zephyr is running on Cortex-M33 core and it's started by Cortex-A55 Core - it's +expected that PLL configuration is fully done by SW running by Cortex-A55 Core before +starting Zephyr on Cortex-M33 core. +Therefore the CPG Clock controller driver **does not** perform any kind of PLL control and +uses static default frequencies for PLL/Core clocks as specified in "Renesas RZ/G3S clock_list_r1.00" document. +See :ref:`cpg_freq_tbl`. + +The CPG Reset driver provides Zephyr System Rest API to assert/de-assert or toggle HW Module reset line(s). + +The RZ G3S CPG DT definition (dts/arm/renesas/rz/r9a08g045.dtsi): + +.. code-block:: dts + + cpg: clock-controller@41010000 { + compatible = "renesas,r9a08g045-cpg-mssr"; + reg = <0x41010000 0x10000>; + clocks = <&extal_clk>; + clock-names = "extal"; + #clock-cells = <2>; + + cpg_rctl: reset-controller { + compatible = "renesas,r9a08g045-cpg-reset"; + #reset-cells = <1>; + status = "okay"; + }; + }; + +The Zephyr Clock control and Reset subsystems are enabled by default in rz_g3s_defconfig, +which automatically enables RZ G3S CPG clock and reset drivers +if corresponding DT node are enabled. + +.. code-block:: text + + CONFIG_CLOCK_CONTROL=y + CONFIG_RESET=y + /* automatically enabled */ + CONFIG_CLOCK_CONTROL_RENESAS_RZG3S=y + CONFIG_RESET_RENESAS_RZG3S_CPG + +The RZ G3S CPG clock control driver code can be found at: + +.. code-block:: text + + drivers/clock_control/clock_control_r9a08g045_cpg_mssr.c + +The RZ G3S CPG reset driver code can be found at: + +.. code-block:: text + + drivers/reset/reset_r9a08g045_cpg.c + +The RZ G3S CPG DT helper macro are defined in: + +.. code-block:: text + + dt-bindings/clock/r9a08g045_cpg_mssr.h + +The RZ G3S SoC design required enabling module clock and releasing module reset line for enabling HW module. +The HW module enabling code example: + +.. code-block:: C + + ret = clock_control_on(cfg->clk_dev, (clock_control_subsys_t)&cfg->clk_mod); + if (ret < 0) { + LOG_DEV_ERR(dev, "Failed to configure clk"); + return ret; + } + + (void)reset_line_toggle_dt(&cfg->rspin_rst); + +Limitations +``````````` + +* PLL control is not supported + +.. _cpg_freq_tbl: + +Changing CPG PLL/Core clocks frequencies +---------------------------------------- + +The default frequencies for PLL/Core clocks can be changed manually by editing `rzg3s_core_clks` table in the +the CPG Clock controller driver (drivers/clock_control/clock_control_r9a08g045_cpg_mssr.c) code: + +.. code-block:: C + + static const struct rzg3s_cpg_core_clk rzg3s_core_clks[MOD_CLK_BASE] = { + /* External Clock Inputs */ + DEF_INPUT(CLK_EXTAL, 24000000), + + DEF_FIXED(R9A08G045_OSCCLK, CLK_EXTAL, 24000000), + DEF_FIXED(R9A08G045_OSCCLK2, CLK_EXTAL, 8000000), + ... + }; + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/delivery/boot.rst b/boards/arm/rz_g3s/doc/delivery/boot.rst new file mode 100644 index 00000000000000..cca5b238ab2a53 --- /dev/null +++ b/boards/arm/rz_g3s/doc/delivery/boot.rst @@ -0,0 +1,25 @@ +RZ G3S MPU boot sequence +------------------------ + +The Renesas RZ G3S MPU boot sequence is illustrated by below diagram: + +.. figure:: ../img/rzg3s_boot.jpg + :align: center + +As can be seen from Boot diagram the main Renesas RZ G3S MPU boot sequence is executed on Cortex-A55 System Core after SoC power-on/reset. +The cold boot from Cortex-M33(FPU) System core is not supported. + +After reset the Boot ROM program is started and loads and starts TF-A BL2 initial program loader. +Then TF-A BL2 loads BL31 (image id=3), BL32 (optionally, image id=4) and BL33 (u-boot, image id=5) from either QSPI or eMMC. + +In addition to the above, the TF-A BL2 is intended to load and start firmware (Zephyr application, image id=36) on Cortex-M33 System core. +For which the TF-A has to be built with `PLAT_M33_BOOT_SUPPORT=1` option as described in :ref:`Building yocto image`. + +The TF-A performs the following steps without which Zephyr application can't be started on Cortex-M33 System core: + +* clocks (PLLs) configuration +* enabling core IPs +* secure configuration +* loading Cortex-M33 firmware (Zephyr application) in RAM +* configuring Cortex-M33 Core (SysTick timer, reset vector address) +* starting Cortex-M33 Core diff --git a/boards/arm/rz_g3s/doc/delivery/delivery_scope.rst b/boards/arm/rz_g3s/doc/delivery/delivery_scope.rst new file mode 100644 index 00000000000000..8815c089540dff --- /dev/null +++ b/boards/arm/rz_g3s/doc/delivery/delivery_scope.rst @@ -0,0 +1,7 @@ +Scope of delivery +================= + +The release includes the following items: + +* This Release Notes. +* Zephyr repository with the source code set of drivers for RZ/A2M support integrated. diff --git a/boards/arm/rz_g3s/doc/delivery/fpu_snippet.rst b/boards/arm/rz_g3s/doc/delivery/fpu_snippet.rst new file mode 100644 index 00000000000000..a46cf83f656fda --- /dev/null +++ b/boards/arm/rz_g3s/doc/delivery/fpu_snippet.rst @@ -0,0 +1,39 @@ +Appendix B. Configure FPU on SCIF1 (experimental) +------------------------------------------------- + +.. note:: + + The provided snippet configures Zephyr to use SCIF1 (PMOD1_3A) for Cortex-M33_FPU core + instead of the SCIF3 (SER1_UART). + +To configure Cortex-M33_FPU core to use SCIF1 please do the following command: + +.. code-block:: bash + + west build -p always -b rz_g3s_fpu -S rz-g3s-fpu-scif1 + +.. note:: + + When starting Zephyr application Cortex-A55 core should be stopped on + u-boot console to prevent hardware sharing issues. + +Overview +******** + +This snippet configures Zephyr to use SCIF1 (PMOD1_3A) for Cortex-M33_FPU core +instead of the SCIF3 (SER1_UART). +This can be helpful for a testing purposes because the default +SCIF3 (SER1_UART) connection requires specific USBUART connector that +support 1.8v. To avoid using specific hardware - CM33_FPU core can be +switched to use SCIF1 (PMOD1_3A) console which works on more common 3.3v. + +Please note that Cortex-M33 core should be flashed with :ref:`hello_world` so it +will minimize interfering with SCIF1 from Cortex-M33. + +.. note:: + Please be aware that this is experimental feature. The following tests + will not work in this configuration due to hw sharing conflicts: + + * **uart_async_api** + * **wdt_basic_api** can be run only from the JLink using command **west debug** + because TF-A do not support Cortex-M33_FPU core. diff --git a/boards/arm/rz_g3s/doc/delivery/getting_source_code.rst b/boards/arm/rz_g3s/doc/delivery/getting_source_code.rst new file mode 100644 index 00000000000000..988cb8b5be6f02 --- /dev/null +++ b/boards/arm/rz_g3s/doc/delivery/getting_source_code.rst @@ -0,0 +1,19 @@ +Getting Source Code +=================== + +Follow Zephyr Getting Started Guide: :ref:`getting_started`, +but change the one step from “Get the Zephyr source code”: + +**NOTE** Please install Zephyr SDK version 0.16.5-1 or later. + +Instead of using this command west init *˜/zephyrproject* use the next one from your working directory: + +.. code-block:: bash + + west init -m git@github.com:xen-troops/zephyr.git --mr rzg3-release-v1.0.2 zephyr_rzg3s + cd zephyr_rzg3s/zephyr + +Cloning GIT repo for the first time requires SSH keys to be registration. Please follow this guide for the detailed +instructions: + +`Generating SSH Keys `_ diff --git a/boards/arm/rz_g3s/doc/delivery/hello_world_start.rst b/boards/arm/rz_g3s/doc/delivery/hello_world_start.rst new file mode 100644 index 00000000000000..51cba0ecb95945 --- /dev/null +++ b/boards/arm/rz_g3s/doc/delivery/hello_world_start.rst @@ -0,0 +1,177 @@ +Starting hello_world application +================================ + +:ref:`hello_world` is a simple sample that can be started on RZ/G3S board and prints +"Hello World" to the console. + +This sample is useful to validate board configuration, such as DIP Switch settings and +Loaders. + +.. _Starting on CM33 core using Jlink: + +Starting on CM33 core using Jlink +--------------------------------- + +Before starting :ref:`hello_world` sample on the board the following preparations should be made: + +- Confirm that all switches are set according to :ref:`rz_g3s_con` section. +- Turn on the board. +- Connect to the CA55 and CM33 console (PMOD1_3A SER0_UART) using minicom (:ref:`Linux minicom terminal`). +- Build Yocto images and flash the loaders to the eMMC (:ref:`Building yocto image`). +- Select eMMC boot mode in SW mode Switch and Reboot. + +After all needed preparations please build :ref:`hello_world` sample using instructions +from :ref:`Debugging` and use the following command: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: rz_g3s + :goals: build + +Start the debug session using command: + +.. code-block:: bash + + west debug + +The result will be the following: + +.. code-block:: console + + Copyright (C) 2022 Free Software Foundation, Inc. + License GPLv3+: GNU GPL version 3 or later + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. + Type "show copying" and "show warranty" for details. + This GDB was configured as "--host=x86_64-build_pc-linux-gnu --target=arm-zephyr-eabi". + Type "show configuration" for configuration details. + For bug reporting instructions, please see: + . + Find the GDB manual and other documentation resources online at: + . + + For help, type "help". + Type "apropos word" to search for commands related to "word"... + Reading symbols from build/rz_g3s/hello_world/zephyr/zephyr.elf... + Remote debugging using :2331 + ... + Resetting target + --Type for more, q to quit, c to continue without paging-- + Loading section rom_start, size 0x7e0 lma 0x23000 + Loading section text, size 0x3990 lma 0x237e0 + Loading section .ARM.exidx, size 0x10 lma 0x27170 + Loading section initlevel, size 0x68 lma 0x27180 + Loading section device_area, size 0xb4 lma 0x271e8 + Loading section rodata, size 0xca4 lma 0x2729c + Loading section datas, size 0x74 lma 0x27f40 + Loading section sw_isr_table, size 0xf40 lma 0x27fb4 + Loading section device_states, size 0x12 lma 0x28ef4 + Loading section .last_section, size 0x4 lma 0x2aadc + Start address 0x00023f3c, load size 24330 + Transfer rate: 19 KB/sec, 2433 bytes/write. + (gdb) + +Then type `c` and hit enter. + +Afterwards, please check the PMOD1_3A SER0_UART console. You should see the following output: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-370-g5f6ce67b2d9f *** + Hello World! rz_g3s + +Starting on CM33_FPU core using Jlink +------------------------------------- + +``west debug`` command can be used to start :ref:`hello_world` sample. + +Please follow recommendations from :ref:`Starting on CM33 core using Jlink` with the following changes: + +* Please connect to SER1_UART instead of PMOD1_3A SER0_UART using minicom (:ref:`rz_g3s_con`) + +After all needed preparations please build :ref:`hello_world` sample using instructions +from :ref:`Debugging` and use the following command: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: rz_g3s_fpu + :goals: build + +After that please follow the steps to start debugging using ``west debug`` from :ref:`Starting on CM33 core using Jlink` + +All results will be the same with one difference. The following output will appear on SER1_UART console: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-370-g5f6ce67b2d9f *** + Hello World! rz_g3s_fpu + +Flashing to SPI +---------------- + +:ref:`hello_world` sample can be flashed to the target board SPI flash so it will be started on each reboot. + +Please follow the instructions to flash :ref:`hello_world` sample to the target board: + +- Confirm that all switches are set according to :ref:`rz_g3s_con` section. +- Turn on the board. +- Connect to the CA55 and CM33 console (PMOD1_3A SER0_UART) using minicom (:ref:`Linux minicom terminal`). +- Build Yocto images and flash the loaders to the SPI (:ref:`Building yocto image`). +- Select Select SPI boot mode in SW mode Switch and Reboot. + +After all needed preparations please build :ref:`hello_world` sample using instructions +from :ref:`Debugging` and use the following command: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: rz_g3s + :goals: build + +As the result `zephyr.srec` file will be created in `build/zephyr` directory. Srec name is the same as `zephyr.bin` file +so in most cases it will have name `zephyr.srec` + +`zephyr.srec` file can be flashed to the target board. Please follow instructions in :ref:`Flashing on qSPI`. + +After flashing please Reboot the board and the following output will appear on PMOD1_3A SER0_UART console: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-370-g5f6ce67b2d9f *** + Hello World! rz_g3s + +Flash to eMMC +------------- + +:ref:`hello_world` sample can be flashed to the target board eMMC flash so it will be started on each reboot. + +Please follow the instructions to flash :ref:`hello_world` sample to the target board: + +- Confirm that all switches are set according to :ref:`rz_g3s_con` section. +- Turn on the board. +- Connect to the CA55 and CM33 console (PMOD1_3A SER0_UART) using minicom (:ref:`Linux minicom terminal`). +- Build Yocto images and flash the loaders to the eMMC (:ref:`Building yocto image`). +- Select Select eMMC boot mode in SW mode Switch and Reboot. + +After all needed preparations please build :ref:`hello_world` sample using instructions +from :ref:`Debugging` and use the following command: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: rz_g3s + :goals: build + +As the result `zephyr.srec` file will be created in `build/zephyr` directory. Srec name is the same as `zephyr.bin` file +so in most cases it will have name `zephyr.srec` + +`zephyr.srec` file can be flashed to the target board. Please follow instructions in :ref:`Flashing on eMMC`. + +After flashing please Reboot the board and the following output will appear on PMOD1_3A SER0_UART console: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-370-g5f6ce67b2d9f *** + Hello World! rz_g3s + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/delivery/initial_config.rst b/boards/arm/rz_g3s/doc/delivery/initial_config.rst new file mode 100644 index 00000000000000..e33a874aa083bd --- /dev/null +++ b/boards/arm/rz_g3s/doc/delivery/initial_config.rst @@ -0,0 +1,170 @@ +.. _rz_g3s_con: + +RZ/G3S-EVKIT board connection +----------------------------- + +Views of the Renesas RZ/G3S SMARC Evaluation Board Kit board ``rz_g3s``: + +.. figure:: ../img/rzg3s_con.jpg + :align: center + :height: 250px + +The connection diagram of RZ/G3S-EVKIT and PC is shown below: + +.. figure:: ../img/rzg3s_con_diag.jpg + :align: center + +* USB Type-C Main Power - connected to USB Type-C power supply +* micro-USB SER3_UART - shell be connected to PC. + It's used as console for SW running on Cortex-A55 System Core. +* PMOD1_3A SER0_UART (3.3V) - shell be connected to PC using UART-USB adapter, like YP-05. + It's used as console for SW running on Cortex-M33 System Core. + +.. figure:: ../img/rzg3s_ser0.jpg + :align: center + :height: 300px + +The connection schema is the following: + +* USB->SERIAL RX -> PMOD1_3A PIN2 (PMOD1_SER0_TX) +* USB->SERIAL TX -> PMOD1_3A PIN3 (PMOD1_SER0_RX) +* USB->SERIAL GND -> PMOD1_3A PIN5 (GND) + +Link: `YP-05 adapter`_. + +.. _YP-05 adapter: https://www.ebay.com/itm/144718688888 + +* 4-pin connector SER1_UART (1.8V) - shell be connected to PC using UART-USB adapter, like MCS-73LV. + It's used as console for SW running on Cortex-M33_FPU System Core. + +.. image:: ../img/SER1.jpg + :height: 250px + :align: center + +* USB->SERIAL RX -> SER1_UART PIN1 +* USB->SERIAL TX -> SER1_UART PIN2 +* USB->SERIAL GND -> SER1_UART PIN4 + +.. note:: + Please note that UART adapter should be switched to 1.8v mode using Jumper as shown on the + picture below. + +.. image:: ../img/1_8v.jpg + :height: 250px + :align: center + +Link: `MCS-73LV adapter`_. + +.. _MCS-73LV adapter: https://www.amazon.com/Level-Serial-Converter-Adapter-Module/dp/B0CDHHGGCV + +* The G3S SMARC Module JTAG interface - shell be connected to PC through SEGGER JLink probe + +.. image:: ../img/rzg3s_jlink.jpg + :height: 250px + :align: center + +Link to the SEGGER JLink software: `JLink istallation page`_. +Please install JLink software version V7.96 or later. + +.. _JLink istallation page: https://www.segger.com/downloads/jlink/ + +.. _Linux minicom terminal: + +Linux minicom terminal +`````````````````````` +The **minicom** is a terminal program for Linux and other unix-like systems. Use below command to connect to the dedicated serial device: + +.. code-block:: bash + + sudo minicom -D /dev/ + +When console port of RZ/G3S-EVKIT is connected to PC it will create TTY **/dev/ttyX** device. +The device name depends on UART-USB converter HW and usually named as **/dev/ttyUSBN**, where **N** - the number assigned by Linux and it depends on connection or re-connection of (plug/unplug UCN cable) UART-USB converter HW to PC. + +For example: + +* connect micro-USB SER3_UART to PC - the **/dev/ttyUSB0** serial device will be created (Cortex-A55) +* connect PMOD1_3A SER0_UART to PC - the **/dev/ttyUSB1** serial device will be created (Cortex-M33) +* connect SER1_UART to PC - the **/dev/ttyUSB2** serial device will be created (Cortex-M33_FPU) + +Run below three commands in different terminal windows to access RZ G3S Cortex-A55 and Cortex-M33 console: + +.. code-block:: bash + + sudo minicom -D /dev/ttyUSB0 + sudo minicom -D /dev/ttyUSB1 + sudo minicom -D /dev/ttyUSB2 + +Minicom configuration should be the following: + +* Bps/Par/Bits: 115200 8N1 +* Hardware Flow Control: No +* Software Flow Control: No + +.. _rz_g3s_hw_conf: + +RZ/G3S-EVKIT board default HW configuration +------------------------------------------- + +This section describes default RZ/G3S-EVKIT board configuration used for basic Zephyr testing. +It enables eMMC boot by default. + +G3S SMARC Module: + +* DIP Switch **SW_CONFIG**: **1:OFF 2:OFF 3:ON 4:OFF 5:OFF 6:OFF** +* DIP Switch **GPIO4_SEL**: **(2-3, 5-6)** + +The RZ SMARC Carrier II: + +* DIP switch **SW_MODE** (Boot Mode): **1:ON 2:OFF 3:OFF**. Module eMMC flash E.g. eMMC +* DIP switch **SW_MODE** (Power): **4:ON** (15V, 2A, 30W, VBUS_SEL=3) +* DIP switch **SW_OPT_MUX**: **1:OFF 2:ON 3:OFF 4:ON** +* DIP switch **SW_GPIO_CAN_PMOD** (CAN Standby): **(2-3, 5-6)** +* JP **PMOD_PWR_SEL** (PMOD Power): should be configured to supply 3.3V +* DIP switch **SW_PMOD0_PWR_SLP** (PMOD Power/Sleep Control): **(2-3, 5-6)** +* DIP switch **SW_GPIO_OPT_SEL** (GPIO Options): **(2-3, 5-6)** +* DIP switch **SW_M2_DIS** (M.2 Card Control Signals): **1:ON 2:ON 3:ON 4:ON** +* DIP switch **SW_PCIE_MUX**: **1:ON 2:OFF 3:OFF 4:ON** + +RZ/G3S-EVKIT board How to set boot mode +--------------------------------------- + +Pins no. 1 to no. 3 of **SW_MODE** are used to control the boot mode of the RZ/G3S +Boot mode should be selected as follow: + +.. _SCIF boot: + +SCIF download mode +`````````````````` + +.. figure:: ../img/scif_mode.png + :align: center + :height: 125px + +.. _SPI boot: + +SPI boot mode +````````````` + +.. figure:: ../img/spi_mode.png + :align: center + :height: 125px + +.. _eMMC boot: + +eMMC boot mode +`````````````` + +.. figure:: ../img/emmc_mode.png + :align: center + :height: 125px + +RZ/G3S-EVKIT power on +--------------------- + +* Validate DIP switch settings according to the :ref:`rz_g3s_hw_conf` +* Attach all external Hardware and connect to the console according to the :ref:`rz_g3s_con` +* Do the preparations according to the Section 4.2 Startup Procedure of `Linux Start-up Guide for RZ/G3S Board Support Package`_ +* Turn on the board + +.. _Linux Start-up Guide for RZ/G3S Board Support Package: https://www.renesas.com/us/en/document/mas/linux-start-guide-rzg3s-board-support-package-v100 diff --git a/boards/arm/rz_g3s/doc/delivery/linux_int.rst b/boards/arm/rz_g3s/doc/delivery/linux_int.rst new file mode 100644 index 00000000000000..48bb13466dc997 --- /dev/null +++ b/boards/arm/rz_g3s/doc/delivery/linux_int.rst @@ -0,0 +1,75 @@ +Integration with Linux +----------------------- + +The Linux and Zephyr application are executed on different System Cores in parallel, according to the current Renesas RZ G3S MPU Multi-OS SW design: + +* Linux on Cortex-A55 +* Zephyr on Cortex-M33 + +As result, Linux and Zephyr application should not share SoC HW resources otherwise it will cause HW corruption and unpredictable behavior. +More over, Linux consider all SoC HW which it knows about as exclusively HW used only by Linux, which first of all include all enabled +in device tree SoC devices. In addition, Linux knows about **ALL** clocks in the system and tries to disable all of them for which no users +are detected (unused clocks). + +For example, SCIF1 (SER0_UART) is used by Zephyr application and not defined in Linux device tree. +In this case, Linux will still try to disable SCIF1 clock as it will consider SCIF1 as unused clock. +As result, when both Linux and Zephyr are running the SCIF1 will stop working after Linux is fully booted. + +The below patch shows example of how to prevent Linux from manipulating Clocks which are used by HW assigned to Zephyr application, +in this case SCIF1, SCIF3 and OSTM2: + +.. code-block:: diff + + diff --git a/drivers/clk/renesas/r9a08g045-cpg.c b/drivers/clk/renesas/r9a08g045-cpg.c + index f2790305aab5..44bcd7d5e0f2 100644 + --- a/drivers/clk/renesas/r9a08g045-cpg.c + +++ b/drivers/clk/renesas/r9a08g045-cpg.c + @@ -464,8 +464,10 @@ static const unsigned int r9a08g045_crit_mod_clks[] __initconst = { + MOD_CLK_BASE + R9A08G045_IA55_CLK, + MOD_CLK_BASE + R9A08G045_DMAC_ACLK, + MOD_CLK_BASE + R9A08G045_VBAT_BCLK, + - MOD_CLK_BASE + R9A08G045_SCIF1_CLK_PCK, + - MOD_CLK_BASE + R9A08G045_OSTM2_PCLK, + + MOD_CLK_BASE + R9A08G045_SCIF1_CLK_PCK, + + MOD_CLK_BASE + R9A08G045_OSTM2_PCLK, + + MOD_CLK_BASE + R9A08G045_SCIF3_CLK_PCK, + }; + + const struct rzg2l_cpg_info r9a08g045_cpg_info = { + -- + +Below is another example of how disable CANFD IP in Linux: + +.. code-block:: diff + + diff --git a/arch/arm64/boot/dts/renesas/rz-smarc2-common.dtsi b/arch/arm64/boot/dts/renesas/rz-smarc2-common.dtsi + index a1948922919d..5b5afeb02017 100644 + --- a/arch/arm64/boot/dts/renesas/rz-smarc2-common.dtsi + +++ b/arch/arm64/boot/dts/renesas/rz-smarc2-common.dtsi + @@ -94,12 +94,12 @@ da7212: codec@1a { + &canfd { + pinctrl-0 = <&can0_pins &can1_pins>; + pinctrl-names = "default"; + - status = "okay"; + + status = "disabled"; + channel0 { + - status = "okay"; + + status = "disabled"; + }; + channel1 { + - status = "okay"; + + status = "disabled"; + }; + }; + + diff --git a/drivers/clk/renesas/r9a08g045-cpg.c b/drivers/clk/renesas/r9a08g045-cpg.c + index 0067a0fe8c21..58338afc9a63 100644 + --- a/drivers/clk/renesas/r9a08g045-cpg.c + +++ b/drivers/clk/renesas/r9a08g045-cpg.c + @@ -464,6 +464,8 @@ static const unsigned int r9a08g045_crit_mod_clks[] __initconst = { + MOD_CLK_BASE + R9A08G045_IA55_CLK, + MOD_CLK_BASE + R9A08G045_DMAC_ACLK, + MOD_CLK_BASE + R9A08G045_VBAT_BCLK, + + MOD_CLK_BASE + R9A08G045_CANFD_PCLK, + + MOD_CLK_BASE + R9A08G045_CANFD_CLK_RAM, + }; diff --git a/boards/arm/rz_g3s/doc/delivery/uboot_int.rst b/boards/arm/rz_g3s/doc/delivery/uboot_int.rst new file mode 100644 index 00000000000000..e9fe3f85a30d42 --- /dev/null +++ b/boards/arm/rz_g3s/doc/delivery/uboot_int.rst @@ -0,0 +1,37 @@ +Integration with u-boot +----------------------- + +The u-boot and Zephyr application are executed on different System Cores in parallel, according to the current Renesas RZ G3S MPU Multi-OS SW design: + +* u-boot on Cortex-A55 +* Zephyr on Cortex-M33 + +As result, u-boot and Zephyr application should not share SoC HW resources otherwise it will cause HW corruption and unpredictable behavior. +For example, if SCIF1 (SER0_UART) is used by Zephyr application then: + +* SCIF1 has to be disabled in u-boot device tree +* any SoC IP which share pins with SCIF1 (SER0_UART) should be disabled also. + +For example, default Renesas RZ G3S u-boot has sdhi2 (SD2) device enabled which shares SD2_CD (P14_1) pin with SCIF1_RXD pin on RZ/G3S-EVKIT, +as result it breaks SCIF1 RX functionality due to pinmux corruption. The below patch shows example of how sdhi2 (SD2) can be disabled in u-boot: + +.. code-block:: diff + + arch/arm/dts/smarc-rzg3s.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + + diff --git a/arch/arm/dts/smarc-rzg3s.dts b/arch/arm/dts/smarc-rzg3s.dts + index 01f7f0c890..118e311277 100644 + --- a/arch/arm/dts/smarc-rzg3s.dts + +++ b/arch/arm/dts/smarc-rzg3s.dts + @@ -84,7 +84,7 @@ + pinctrl-0 = <&sdhi2_pins>; + + bus-width = <4>; + - status = "okay"; + + status = "disabled"; + }; + + ð0 { + -- + 2.25.1 diff --git a/boards/arm/rz_g3s/doc/delivery/west_flash.rst b/boards/arm/rz_g3s/doc/delivery/west_flash.rst new file mode 100644 index 00000000000000..24951234b17c62 --- /dev/null +++ b/boards/arm/rz_g3s/doc/delivery/west_flash.rst @@ -0,0 +1,30 @@ +Appendix A. west xSPI flash (experimental) +------------------------------------------ + +.. note:: + + The default Renesas flashing process is based on using **FlashWriter**. + The usage of **west flash** (JLink flash) is considered as experimental and can be used on your own risk only. + +The **west flash** for Renesas RZ G3S uses capability of JLink SW and probe to write memory mapped flash memory, which, in this case, +is xSPI memory area. The JLink supports only Cortex-M33 and so the Cortex-M33/Cortex-M33_FPU Address Space shell be used while working with Jlink. + +To flash Zephyr application binary **west flash** uses **0x80200000** base address which is compatible with TF-A initial bootloader. + +**The minimal version of SEGGER JLink SW which can perform flashing of xSPI memory is v7.96.** + +The command: + +.. code-block:: bash + + west flash + +The output in case of success: + +.. code-block:: console + + -- west flash: rebuilding + ninja: no work to do. + -- west flash: using runner jlink + -- runners.jlink: JLink version: 7.96 + -- runners.jlink: Flashing file: /home/xtrs/zephyrproject/zephyr/build/zephyr/zephyr.bin diff --git a/boards/arm/rz_g3s/doc/delivery/yocto_build.rst b/boards/arm/rz_g3s/doc/delivery/yocto_build.rst new file mode 100644 index 00000000000000..bdd57ff46d1d88 --- /dev/null +++ b/boards/arm/rz_g3s/doc/delivery/yocto_build.rst @@ -0,0 +1,293 @@ +.. _Building yocto image: + +Building yocto image +==================== + +.. _Linux Start-up Guide for RZ/G3S Board Support Package: https://www.renesas.com/us/en/document/mas/linux-start-guide-rzg3s-board-support-package-v100 + +Overview +-------- + +RZ/G3S board is designed to start different systems on cores. It uses Yocto as the build system +to build Linux system and BootLoaders to run Linux on CA55 core. + +The provided Yocto layer is an enhancement on top of Reneass FSP build see `Linux Start-up Guide for RZ/G3S Board Support Package`_. +And it will build the following artifacts in the directory `build/tmp/deploy/images/smarc-rzg3s`: + +* RZ/G3S Linux kernel: Image-smarc-rzg3s.bin +* Device tree file: Image-r9a08g045s33-smarc.dtb +* root filesystem: -smarc-rzg3s.tar.bz2 +* L2 Boot loader for SPI: bl2_bp_spi-smarc-rzg3s.srec +* L2 Boot loader for eMMC: bl2_bp_emmc-smarc-rzg3s.srec +* L3 Boot loader: fip-smarc-rzg3s.srec +* Flash Writer: FlashWriter-smarc-rzg3s.mot +* SD image: core-image- -smarc-rzg3s.wic.gz +* BMAP image: core-image- -smarc-rzg3s.wic.bmap + +``NOTE`` can be either `core-image-minimal` or `core-image-bsp`. + +The top-level meta-layer is `meta-rz-zephyr`, please see README.md file for details: `meta-rz-zephyr`_. + +.. _meta-rz-zephyr: https://gitbud.epam.com/rec-rzzp/meta-zephyr-rz/-/blob/rzg3s_dev/README.md + +Compatibility +------------- + +This Yocto build is based on top of RZ/G3S Board Support Package Version 1.0.0 (`Linux Start-up Guide for RZ/G3S Board Support Package`_) +with ``meta-rz-features`` layer provided with Multi-OS Package v2.0.0. Please note that current release is based +on Multi-OS Package v2.0.0 and do not support Multi-OS-Package v2.0.1. + +Current Yocto repo provides the following changes to the Renesas yocto recipes: + +* trusted-firmware-a: Add `PLAT_M33_BOOT_SUPPORT=1` to start CM33 core on boot; +* rpmsg-sample_0.1: Updates to rpmsg-sample code to work with newer versions of OpenAMP; +* linux-renesas_5.10: Update kernel CPG driver to enable SCIF and OSTM clocks for Zephyr; +* u-boot_2021.10: Disable sdhi2 device as it shares scif1 pin used by Cortex-M33 core. + +Getting started with Yocto +-------------------------- + +Initialize yocto repository: + +.. code-block:: bash + + repo init -u git@gitbud.epam.com:rec-rzzp/rzg3s-manifest.git -b manifest_init + repo sync + +``NOTE`` Yocto initialization using repo for manifests. Please follow the link for repo installation details: `repo Install`_. + +.. _repo Install: https://gerrit.googlesource.com/git-repo#install + +Before building please install all needed packages, provided in *Section 2.1 Building images* +in `Linux Start-up Guide for RZ/G3S Board Support Package`_. + +Initializate bitbake environment using command: + +.. code-block:: bash + + TEMPLATECONF=$PWD/meta-zephyr-rz/docs/template/conf source poky/oe-init-build-env + +Start the build: + +.. code-block:: bash + + MACHINE=smarc-rzg3s bitbake core-image-minimal + +The above commands will clone all necessary repositories, generate necessary configuration files +and run build. + +All built files will be located in directory `/build/tmp/deploy/images/smarc-rzg3s`. + +**NOTE** BL2 TF-A image will be built with `PLAT_M33_BOOT_SUPPORT` feature to load image to CM33 core on boot. + +.. _Flash loaders: + +Flash loaders to the target board +--------------------------------- + +To Flash bootloaders to the target board please follows this steps: + +* Switch the board to SCIF Download mode. Refer to :ref:`SCIF boot`. + See section 4.1.1 of `Linux Start-up Guide for RZ/G3S Board Support Package`_ for details. + +* Connect to the board minicom consoles using minicom (:ref:`Linux minicom terminal`); +* When the following message appear: + +.. code-block:: bash + + SCI Download mode (Notmal SCI boot) + -- Load Program to SRAM ----------------- + +* Use minicom `ASCII` mode to upload FlashWriter (FlashWriter-smarc-rzg3s.mot). + Refer to :ref:`Upload with minicom`; + +* After upload the following message appear: + +.. code-block:: bash + + Flash writer for RZ/G3S Series + Product Code : RZ/G3S + +* Then upload images to either qSPI or eMMC (see below). + +Flash to qSPI +````````````` + +* use XLS2 command to upload bl2 image: + +.. code-block:: bash + + >XLS2 + ===== Qspi writing of RZ/G3 Board Command ============= + Load Program to Spiflash + Writes to any of SPI address. + Program size & Qspi Save Address + ===== Please Input Program Top Address ============ + Please Input : H'a1e00 + ===== Please Input + Qspi Save Address === + Please Input : H'0 + please send ! ('.' & CR stop load) + +* upload bl2_bp_spi-smarc-rzg3s.srec from minicom. Refer to :ref:`Upload with minicom`; +* after successful download the following output will appear: + +.. code-block:: bash + + Erase SPI Flash memory... + Erase Completed + Write to SPI Flash memory. + ======= Qspi Save Information ================= + SpiFlashMemory + Stat Address : H'00000000 + SpiFlashMemory + End Address : H'0001BCCF + ================================================ + +* use XLS2 command to upload fip image: + +.. code-block:: console + + >XLS2 + ===== Qspi writing of RZ/G3 Board Command ============= + Load Program to Spiflash + Writes to any of SPI address. + Program size & Qspi Save Address + ===== Please Input Program Top Address ============ + Please Input : H’0 + ===== Please Input Qspi Save Address === + Please Input : H'64000 + please send ! ('.' & CR stop load) + +* upload fip-smarc-rzg3s.srec from minicom. Refer to :ref:`Upload with minicom`; +* after successful download the following output will appear: + +.. code-block:: bash + + Erase SPI Flash memory... + Erase Completed + Write to SPI Flash memory. + ======= Qspi Save Information ================= + SpiFlashMemory Stat Address : H'00064000 + SpiFlashMemory End Address : H'0014782E + =========================================================== + +* Switch the board to qSPI boot mode. See section 4.1.1 of `Linux Start-up Guide for RZ/G3S Board Support Package`_; + +Flash to eMMC +````````````` + +* use EM_W command to upload bl2 image: + +.. code-block:: console + + >EM_W + EM_W Start -------------- + --------------------------------------------------------- + Please select,eMMC Partition Area. + 0:User Partition Area : 62160896 KBytes + eMMC Sector Cnt : H'0 - H'0768FFFF + 1:Boot Partition 1 : 32256 KBytes + eMMC Sector Cnt : H'0 - H'0000FBFF + 2:Boot Partition 2 : 32256 KBytes + eMMC Sector Cnt : H'0 - H'0000FBFF + --------------------------------------------------------- + Select area(0-2)>1 + -- Boot Partition 1 Program ----------------------------- + Please Input Start Address in sector :1 + Please Input Program Start Address : a1e00 + Work RAM (H'00020000-H'000FFFFF) Clear.... + please send ! ('.' & CR stop load) + +* upload bl2_bp_emmc-smarc-rzg3s.srec from minicom. Refer to :ref:`Upload with minicom`; +* after successful download the following output will appear: + +.. code-block:: console + + SAVE -FLASH....... + EM_W Complete + +* use EM_W command to upload fip image: + +.. code-block:: console + + > EM_W + EM_W Start -------------- + --------------------------------------------------------- + Please select,eMMC Partition Area. + 0:User Partition Area : 62160896 KBytes + eMMC Sector Cnt : H'0 - H'0768FFFF + 1:Boot Partition 1 : 32256 KBytes + eMMC Sector Cnt : H'0 - H'0000FBFF + 2:Boot Partition 2 : 32256 KBytes + eMMC Sector Cnt : H'0 - H'0000FBFF + --------------------------------------------------------- + Select area(0-2)>1 + -- Boot Partition 1 Program ----------------------------- + Please Input Start Address in sector :320 + Please Input Program Start Address : 0 + Work RAM(H'00020000-H'000FFFFF) Clear.... + please send ! ('.' & CR stop load) + +* upload fip-smarc-rzg3s.srec from minicom. Refer to :ref:`Upload with minicom`; +* after successful download the following output will appear: + +.. code-block:: console + + SAVE -FLASH....... + EM_W Complete! + +* set EXT_CSD register: + +.. code-block:: console + + >em_secsd + Please Input EXT_CSD Index(H'00 - H'1FF) : b1 + EXT_CSD[B1] = 0x02 + Please Input Value(H'00 - H'FF) : 2 + EXT_CSD[B1] = 0x02 + >em_secsd + Please Input EXT_CSD Index(H'00 - H'1FF) : b3 + EXT_CSD[B3] = 0x09 + Please Input Value(H'00 - H'FF) : 8 + EXT_CSD[B3] = 0x08 + > + +* Switch the board to eMMC boot mode. See section 4.1.1 of `Linux Start-up Guide for RZ/G3S Board Support Package`_; + +.. _Upload with minicom: + +Upload with minicom +``````````````````` + +For upload file with mimicom press `Ctrl+a` then `s`. In menu choose `ascii` then file to upload. + +.. _Start Linux: + +Starting Linux on the target board +---------------------------------- + +This step is optional for all Zephyr tests referenced in this document, except for :ref:`rz_g3s_openamp`. + +For :ref:`rz_g3s_openamp` this step is mandatory. + +To load Linux rootfs microSD card should be used. + +Please plug in micro SD card to your PC and then execute: + +.. code-block:: bash + + sudo bmaptool copy core-image-minimal-smarc-rzg3s.wic.gz /dev/sda + +From `/build/tmp/deploy/images/smarc-rzg3s` folder where `/dev/sda` is the device associated with microSD card. +See section 3.1 of `Linux Start-up Guide for RZ/G3S Board Support Package`_ for details. + +Then plug this microSD card to slot on carry board as shown on the following schema: + +.. figure:: ../img/sd_connection.jpg + :align: center + :height: 300px + +For details pleas see Section 5 of `Linux Start-up Guide for RZ/G3S Board Support Package`_. + +Hit reset. diff --git a/boards/arm/rz_g3s/doc/dma/dma.rst b/boards/arm/rz_g3s/doc/dma/dma.rst new file mode 100644 index 00000000000000..76604eb9c44371 --- /dev/null +++ b/boards/arm/rz_g3s/doc/dma/dma.rst @@ -0,0 +1,209 @@ +Direct Memory Access (DMA) Controller Support +============================================= + +DMA overview +------------ + +The direct memory access controller can be used in place of the CPU to perform high-speed transfers between external +memory, on-chip memory, memory-mapped external devices, and on-chip peripheral modules. +This module has controllers that handles secure and non-secure access. +Do not assign the same DMA transfer request to secure access and non- secure access, respectively. + +DMA driver overview +------------------- + +Zephyr RZ/G3S Renesas DMA driver provides Zephyr :ref:`dma_api` System interface implementation. + +The DMA subsystem is **not** enabled by default in ``rz_g3s_defconfig``. To enable Zephyr +DMA functionality and RZ G3S DMA driver below Kconfig options have to be enabled: + +.. code-block:: text + + CONFIG_DMA=y + /* automatically enabled */ + CONFIG_DMA_RZA2=y + +The RZ G3S DMA driver code can be found at: + +.. code-block:: text + + drivers/dma/dma_rza2.c + +DMA testing +----------- + +tests/drivers/dma/chan_blen_transfer +```````````````````````````````````` + +Zephyr RZ/G3S DMA driver can be tested by using **tests/drivers/dma/chan_blen_transfer** test. +To build **tests/drivers/dma/chan_blen_transfer** test run command: + +.. code-block:: bash + + west build -b rz_g3s -p always tests/drivers/dma/chan_blen_transfer + +Console output: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-364-g2f7499219d0b *** + Running TESTSUITE dma_m2m + =================================================================== + START - test_test_dma0_m2m_chan0_burst16 + Preparing DMA Controller: Name=dma@41800000, Chan_ID=0, BURST_LEN=2 + Starting the transfer + DMA transfer done + It is harder to be kind than to be wise........ + PASS - test_test_dma0_m2m_chan0_burst16 in 2.014 seconds + =================================================================== + START - test_test_dma0_m2m_chan0_burst8 + Preparing DMA Controller: Name=dma@41800000, Chan_ID=0, BURST_LEN=1 + Starting the transfer + DMA transfer done + It is harder to be kind than to be wise........ + PASS - test_test_dma0_m2m_chan0_burst8 in 2.014 seconds + =================================================================== + START - test_test_dma0_m2m_chan1_burst16 + Preparing DMA Controller: Name=dma@41800000, Chan_ID=1, BURST_LEN=2 + Starting the transfer + DMA transfer done + It is harder to be kind than to be wise........ + PASS - test_test_dma0_m2m_chan1_burst16 in 2.014 seconds + =================================================================== + START - test_test_dma0_m2m_chan1_burst8 + Preparing DMA Controller: Name=dma@41800000, Chan_ID=1, BURST_LEN=1 + Starting the transfer + DMA transfer done + It is harder to be kind than to be wise........ + PASS - test_test_dma0_m2m_chan1_burst8 in 2.014 seconds + =================================================================== + TESTSUITE dma_m2m succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [dma_m2m]: pass = 4, fail = 0, skip = 0, total = 4 duration = 8.056 seconds + - PASS - [dma_m2m.test_test_dma0_m2m_chan0_burst16] duration = 2.014 seconds + - PASS - [dma_m2m.test_test_dma0_m2m_chan0_burst8] duration = 2.014 seconds + - PASS - [dma_m2m.test_test_dma0_m2m_chan1_burst16] duration = 2.014 seconds + - PASS - [dma_m2m.test_test_dma0_m2m_chan1_burst8] duration = 2.014 seconds + + ------ TESTSUITE SUMMARY END ------ + +tests/drivers/dma/loop_transfer +``````````````````````````````` + +Zephyr RZ/G3S DMA driver can be tested by using **tests/drivers/dma/loop_transfer** test. +To build **tests/drivers/dma/loop_transfer** test run command: + +.. code-block:: bash + + west build -b rz_g3s -p always tests/drivers/dma/loop_transfer + +Console output: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-364-g2f7499219d0b *** + Running TESTSUITE dma_m2m_loop + =================================================================== + START - test_test_dma0_m2m_loop + DMA memory to memory transfer started + Preparing DMA Controller: dma@41800000 + Starting the transfer on channel 0 and waiting for 1 second + Each RX buffer should contain the full TX buffer string. + RX data Loop 0 + RX data Loop 1 + RX data Loop 2 + RX data Loop 3 + Finished DMA: dma@41800000 + PASS - test_test_dma0_m2m_loop in 0.309 seconds + =================================================================== + START - test_test_dma0_m2m_loop_repeated_start_stop + DMA memory to memory transfer started + Preparing DMA Controller + Starting the transfer on channel 1 and waiting for 1 second + Each RX buffer should contain the full TX buffer string. + RX data Loop 0 + RX data Loop 1 + RX data Loop 2 + RX data Loop 3 + Finished: DMA + PASS - test_test_dma0_m2m_loop_repeated_start_stop in 0.304 seconds + =================================================================== + START - test_test_dma0_m2m_loop_suspend_resume + DMA memory to memory transfer started + Preparing DMA Controller: dma@41800000 + Starting the transfer on channel 2 and waiting for 1 second + suspended after 0 transfers occurred + resuming after 0 transfers occurred + Resumed transfers + Transfer count 4 + Each RX buffer should contain the full TX buffer string. + RX data Loop 0 + RX data Loop 1 + RX data Loop 2 + RX data Loop 3 + Finished DMA: dma@41800000 + PASS - test_test_dma0_m2m_loop_suspend_resume in 0.568 seconds + =================================================================== + TESTSUITE dma_m2m_loop succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [dma_m2m_loop]: pass = 3, fail = 0, skip = 0, total = 3 duration = 1.181 seconds + - PASS - [dma_m2m_loop.test_test_dma0_m2m_loop] duration = 0.309 seconds + - PASS - [dma_m2m_loop.test_test_dma0_m2m_loop_repeated_start_stop] duration = 0.304 seconds + - PASS - [dma_m2m_loop.test_test_dma0_m2m_loop_suspend_resume] duration = 0.568 seconds + + ------ TESTSUITE SUMMARY END ------ + +tests/drivers/dma/scatter_gather +```````````````````````````````` + +Zephyr RZ/G3S DMA driver can be tested by using **tests/drivers/dma/scatter_gather** test. +To build **tests/drivers/dma/scatter_gather** test run command: + +.. code-block:: bash + + west build -b rz_g3s -p always tests/drivers/dma/scatter_gather + +Console output: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-364-gd807a730bca8 *** + Running TESTSUITE dma_m2m_sg + =================================================================== + START - test_dma_m2m_sg + DMA memory to memory transfer started + Preparing DMA Controller + dma block 0 block_size 8192, source addr 200590a0, dest addr 200510a0 + set next block pointer to 0x2005b2f4 + dma block 1 block_size 8192, source addr 200590a0, dest addr 200530a0 + set next block pointer to 0x2005b314 + dma block 2 block_size 8192, source addr 200590a0, dest addr 200550a0 + set next block pointer to 0x2005b334 + dma block 3 block_size 8192, source addr 200590a0, dest addr 200570a0 + Configuring the scatter-gather transfer on channel 0 + Starting the transfer on channel 0 and waiting completion + giving xfer_sem + Verify RX buffer should contain the full TX buffer string. + rx_data[0] + rx_data[1] + rx_data[2] + rx_data[3] + Finished: DMA Scatter-Gather + PASS - test_dma_m2m_sg in 0.101 seconds + =================================================================== + TESTSUITE dma_m2m_sg succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [dma_m2m_sg]: pass = 1, fail = 0, skip = 0, total = 1 duration = 0.101 seconds + - PASS - [dma_m2m_sg.test_dma_m2m_sg] duration = 0.101 seconds + + ------ TESTSUITE SUMMARY END ------ + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/gpio/gpio.rst b/boards/arm/rz_g3s/doc/gpio/gpio.rst new file mode 100644 index 00000000000000..53035be69fc355 --- /dev/null +++ b/boards/arm/rz_g3s/doc/gpio/gpio.rst @@ -0,0 +1,346 @@ +.. _rzg3s_gpio_label: + +General Purpose Input Output Port (GPIO) +======================================== + +GPIO overview +------------- + +The RZ G3S SoC can use: + +* up to 82 general-purpose I/O pins, which are split on 19 GPIO ports. +* up to 32 GPIO pin IRQs mapped through TINT module. + +Each port of the general-purpose I/O port is multiplexed with the terminal of the peripheral function, +and either the general-purpose I/O port function or the peripheral function can be selected by setting +the register. + +This section is limited to general-purpose I/O pins functionality only. + +Features: + +* each GPIO pin can be configured as input or output, or both. +* each GPIO pin can generate interrupts when in input mode. +* each GPIO pin supports buffer drive ability control (IOLH_m) +* each GPIO pin supports pull-up/Pull-down Switching (PUPD_m) +* each GPIO pin supports digital noise filter control (FILONOFF_m) + +GPIO Interrupt (TINT) +````````````````````` +GPIO interrupt is the interrupt using GPIO pins as external interrupt input pins. +When using GPIO pins as interrupts, assign GPIO pins as external interrupt input pins (GPIOINT0-81) by GPIO +register setting. + +The 32 interrupt sources can be assigned to TINT from GPIOINT0-81 by TINT Source Selection Register (TSSR0-7) in +IM33/IM33_FPU. Only 1:1 mapping is allowed. +The TINT inputs can be detected by a level or an edge. It can be selected “Rising-edge detection”, “Falling-edge +detection”, “High-level detection” or “Low-level detection”. + +.. code-block:: text + + +----------------+ + |TINT | + | | + GPIO0 | | 0 + ------+ +---- + GPIO1 | | 1 + ------+ +---- + | | + ... | | ... + | | + | | + | | + GPIO81 | | 31 + -----+ +---- + +----------------+ + +Refer to "General Purpose Input Output Port (GPIO)" section in "Renesas RZ/G3S Group User’s Manual: Hardware" +Refer to :ref:`rzg3s_pinctrl_label` + +GPIO driver overview +-------------------- + +The RZ G3S GPIO driver provides Zephyr GPIO System interface :ref:`gpio_api` implementation. + +The RZ G3S GPIO driver is logically implemented as gpio-controller and set of GPIO ports (dts/arm/renesas/rz/r9a08g045.dtsi). +GPIO ports provides Zephyr GPIO System interface implementation. +The gpio-controller provides GPIO Interrupt (TINT) management to the GPIO ports. +When GPIO consumers requests GPIO pin IRQ functionality the gpio-controller selects free TINT IRQ and maps it to requested GPIO pin. + +.. code-block:: dts + + gpio: gpio-controller@41060020 { + compatible = "renesas,r9a08g045-gpio"; + reg = <0x41060020 0x30>; + reg-names = "tint"; + interrupts = + <429 0>, <430 0>, <431 0>, <432 0>, + <433 0>, <434 0>, <435 0>, <436 0>, + <437 0>, <438 0>, <439 0>, <440 0>, + <441 0>, <442 0>, <443 0>, <444 0>, + <445 0>, <446 0>, <447 0>, <448 0>, + <449 0>, <450 0>, <451 0>, <452 0>, + <453 0>, <454 0>, <455 0>, <456 0>, + <457 0>, <458 0>, <459 0>, <460 0>; + #address-cells = <1>; + #size-cells = <0>; + + port0: gpio@0 { + reg = <0x0>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <4>; + status = "disabled"; + }; + + ... + + port18: gpio@12 { + reg = <0x12>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <6>; + status = "disabled"; + }; + }; + +The GPIO consumer should use reference at GPIO port DT node and GPIO pin number within GPIO port. +The GPIO port should be enabled in DT (example :ref:`GPIO DT request example `). + +The GPIO subsystem is enabled by default in ``rz_g3s_defconfig``, +which automatically enables RZ G3S GPIO driver if corresponding DT node is enabled. + +.. code-block:: text + + CONFIG_GPIO=y + /* automatically enabled */ + CONFIG_GPIO_RZG3S=y + +The RZ G3S GPIO driver code can be found at: + +.. code-block:: text + + drivers/gpio/gpio_rzg3s.c + +The DT helper macro are defined in: + +.. code-block:: text + + dt-bindings/gpio/gpio.h + dt-bindings/gpio/rzg3s-gpio.h + dt-bindings/pinctrl/renesas/pinctrl-r9a08g045.h + +Supported GPIO DT flags: + ++----------------------------------------+-------+--------------------------------------------+ +| DT GPIO flags | | | ++========================================+=======+============================================+ +|GPIO_ACTIVE_LOW |generic| | ++----------------------------------------+-------+--------------------------------------------+ +|GPIO_ACTIVE_HIGH |generic| | ++----------------------------------------+-------+--------------------------------------------+ +|GPIO_PULL_UP |generic|mapped at PUPD_m registers | ++----------------------------------------+-------+--------------------------------------------+ +|GPIO_PULL_DOWN |generic|mapped at PUPD_m registers | ++----------------------------------------+-------+--------------------------------------------+ +|RZG3S_GPIO_DRIVE_IOLH_SET(iolh_val) |custom |mapped at IOLH_m registers | ++----------------------------------------+-------+--------------------------------------------+ +|RZG3S_GPIO_FILTER_SET(filnum, filclksel)|custom |mapped at FILNUM_m and FILCLKSEL_m registers| ++----------------------------------------+-------+--------------------------------------------+ + +The example of DT GPIO flags usage to configure GPIO Driving Ability: + +.. code-block:: dts + + gpio-consumer { + out-gpios = <&port8 2 (GPIO_PULL_UP | RZA2_GPIO_DRIVE_IOLH_SET(PINCTRL_RZG3S_PIN_IOLH_A_3_3V_1900)>; + }; + +The example of DT GPIO flags usage to configure GPIO Digital Noise Filter: + +.. code-block:: dts + + gpio-consumer { + out-gpios = <&port8 2 (GPIO_PULL_UP | RZG3S_GPIO_FILTER_SET(3, 3))>; + }; + +GPIO testing +------------- + +tests/drivers/gpio/gpio_basic_api +````````````````````````````````` +To run **gpio_basic_api** test it's required to connect **PMOD1 Type-3A** pins +as described on picture below to form loopback connection between +RZ G3S GPIOI pins P8_2 and P8_3: + +.. code-block:: text + + +--------------------------------------------------+ + | RZ G3S SMARC Ev Board | + | | + | PMOD1 | + | Type-3A | + | +-------------+ +----+ + | |RZ G3S SoC | | | + | | | | | + | | | | | + | | | | | + | | | GPIO12:PMOD1_GPIO12 | | + | | P8_2 X--------------------------> 9 X--------+ + | | | | | | + | | | | | | + | | | | | | + | | | | | | + | | | GPIO13:PMOD1_GPIO13 | | | + | | P8_3 X<-------------------------+ 10 X<-------+ + | | | | | + | +-------------+ +----+ + | | + | | + +--------------------------------------------------+ + +The **gpio_basic_api** DT overlay (`tests/drivers/gpio/gpio_basic_api/boards/rz_g3s.overlay`) +for RZ/G3S SMARC Evaluation Board Kit is below: + +.. _rzg3s_gpio_dts_consumer: + +.. code-block:: dts + + / { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&port8 2 0>; + in-gpios = <&port8 3 0>; + }; + }; + + &port8 { + status = "okay"; + }; + +To build **gpio_basic_api** test run command: + +.. code-block:: bash + + west build -b rz_g3s -p always tests/drivers/gpio/gpio_basic_api + +The **gpio_basic_api** test will produce below console output when executed: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-227-g5edb05de40b5 *** + Running TESTSUITE gpio_port + =================================================================== + START - test_gpio_port + Validate device gpio@8 + Check gpio@8 output 2 connected to input 3 + OUT 2 to IN 3 linkage works + - bits_physical + - pin_physical + - check_raw_output_levels + - check_logic_output_levels + - check_input_levels + - bits_logical + PASS - test_gpio_port in 0.021 seconds + =================================================================== + TESTSUITE gpio_port succeeded + Running TESTSUITE gpio_port_cb_mgmt + =================================================================== + START - test_gpio_callback_add_remove + callback_2 triggered: 1 + callback_1 triggered: 1 + callback_2 triggered: 1 + PASS - test_gpio_callback_add_remove in 3.610 seconds + =================================================================== + START - test_gpio_callback_enable_disable + callback_2 triggered: 1 + callback_1 triggered: 1 + callback_2 triggered: 1 + callback_1 triggered: 1 + PASS - test_gpio_callback_enable_disable in 3.612 seconds + =================================================================== + START - test_gpio_callback_self_remove + callback_remove_self triggered: 1 + callback_1 triggered: 1 + callback_1 triggered: 1 + PASS - test_gpio_callback_self_remove in 2.510 seconds + =================================================================== + TESTSUITE gpio_port_cb_mgmt succeeded + Running TESTSUITE gpio_port_cb_vari + =================================================================== + START - test_gpio_callback_variants + callback triggered: 1 + OUT init a0001, IN cfg 3400000, cnt 1 + callback triggered: 1 + OUT init 60000, IN cfg 5400000, cnt 1 + callback triggered: 1 + OUT init 60000, IN cfg 5c00000, cnt 1 + callback triggered: 1 + OUT init a0001, IN cfg 3c00000, cnt 1 + callback triggered: 1 + callback triggered: 2 + callback triggered: 3 + OUT init 60000, IN cfg 4400000, cnt 3 + callback triggered: 1 + callback triggered: 2 + callback triggered: 3 + OUT init a0001, IN cfg 2400000, cnt 3 + callback triggered: 1 + callback triggered: 2 + callback triggered: 3 + OUT init 60000, IN cfg 4c00000, cnt 3 + callback triggered: 1 + callback triggered: 2 + callback triggered: 3 + OUT init a0001, IN cfg 2c00000, cnt 3 + Mode 7400000 not supported + PASS - test_gpio_callback_variants in 8.860 seconds + =================================================================== + TESTSUITE gpio_port_cb_vari succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [gpio_port]: pass = 1, fail = 0, skip = 0, total = 1 duration = 0.021 seconds + - PASS - [gpio_port.test_gpio_port] duration = 0.021 seconds + + SUITE PASS - 100.00% [gpio_port_cb_mgmt]: pass = 3, fail = 0, skip = 0, total = 3 duration = 9.732 + ses + - PASS - [gpio_port_cb_mgmt.test_gpio_callback_add_remove] duration = 3.610 seconds + - PASS - [gpio_port_cb_mgmt.test_gpio_callback_enable_disable] duration = 3.612 seconds + - PASS - [gpio_port_cb_mgmt.test_gpio_callback_self_remove] duration = 2.510 seconds + + SUITE PASS - 100.00% [gpio_port_cb_vari]: pass = 1, fail = 0, skip = 0, total = 1 duration = 8.860 + ses + - PASS - [gpio_port_cb_vari.test_gpio_callback_variants] duration = 8.860 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL + +samples/basic/button +```````````````````` + +To build **basic/button** test run command: + +.. code-block:: bash + + west build -b rz_g3s -p always samples/basic/button/ + +The **USER_SW2** button is enabled by default for test purposes. +The **basic/button** test will produce below console output when executed and +the **USER_SW2** button pressed: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-227-g9c638e9d4fa9 *** + Set up button at gpio@12 pin 0 + Press the button + Button pressed at 1859207199 + Button pressed at 1949018630 + Button pressed at 1998292400 + Button pressed at 2057400586 + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/i2c/i2c.rst b/boards/arm/rz_g3s/doc/i2c/i2c.rst new file mode 100644 index 00000000000000..989a11c87554f2 --- /dev/null +++ b/boards/arm/rz_g3s/doc/i2c/i2c.rst @@ -0,0 +1,109 @@ +I2C Bus Interface (I2C) +======================= + +I2C overview +------------ + +The Renesas RZ G3S Soc has 4 channels of the I2C bus interface (RIIC). + +Refer to "I2C Bus Interface" section in "Renesas RZ/G3S Group User’s Manual: Hardware" + +I2C driver overview +------------------- + +Zephyr RZ/G3S Renesas I2C driver provides Zephyr :ref:`i2c_api` System interface implementation. + +The I2C subsystem is **not** enabled by default in ``rz_g3s_defconfig``. To enable Zephyr +I2C functionality and RZ G3S I2C driver below Kconfig options have to be enabled: + +.. code-block:: text + + CONFIG_I2C=y + /* automatically enabled */ + CONFIG_I2C_RIIC=y + +The RZ G3S I2C driver code can be found at: + +.. code-block:: text + + drivers/i2c/i2c_riic.c + +Current implementation of I2C driver supports DMA transfer. Currently DMA used if amount of +transferred bytes more then 6 for read and more then 1 for write. + +DMA transfer capability in RZ G3C I2C driver below Kconfig options have to be enabled: + +.. code-block:: text + + CONFIG_I2C_RIIC_DMA_DRIVEN=y + +I2C testing +----------- + +samples/sensor/bme280 +````````````````````` + +BME280 sensor (or any I2C device) can be connected to the PMOD1_6A connector as shown on picture: + +.. image:: ../img/i2c_rzg3s.jpg + :height: 350px + :align: center + +Zephyr RZ/G3S I2C driver can be tested by using **bme280** sample application with BME280 sensor. +To build **bme280** test run command: + +.. code-block:: bash + + west build -b rz_g3s -p always samples/sensor/bme280 + +Console output: + +.. code-block:: console + + [00:00:00.004,000] BME280: bme280_chip_init: ID OK + [00:00:00.038,000] BME280: bme280_chip_init: "bme280@76" OK + *** Booting Zephyr OS build zephyr-v3.3.0-10473-g1380b66bc483 *** + Found device "bme280@76", getting sensor data + temp: 20.740000; press: 98.004894; humidity: 57.391601 + temp: 20.740000; press: 98.005222; humidity: 57.368164 + temp: 20.740000; press: 98.005468; humidity: 57.322265 + temp: 20.740000; press: 98.006050; humidity: 57.379882 + temp: 20.740000; press: 98.006628; humidity: 57.402343 + temp: 20.740000; press: 98.006628; humidity: 57.345703 + temp: 20.740000; press: 98.006628; humidity: 57.402343 + temp: 20.740000; press: 98.006464; humidity: 57.414062 + temp: 20.740000; press: 98.006628; humidity: 57.357421 + temp: 20.750000; press: 98.006910; humidity: 57.312500 + temp: 20.750000; press: 98.006578; humidity: 57.358398 + temp: 20.750000; press: 98.006085; humidity: 57.403320 + temp: 20.750000; press: 75.098539; humidity: 57.426757 + temp: 20.760000; press: 98.004425; humidity: 60.697265 + temp: 21.560000; press: 98.005820; humidity: 79.519531 + temp: 21.920000; press: 98.005921; humidity: 80.390625 + temp: 22.750000; press: 98.004371; humidity: 90.697265 + temp: 23.350000; press: 98.005582; humidity: 88.872070 + temp: 23.660000; press: 98.005925; humidity: 87.301757 + temp: 24.590000; press: 98.006113; humidity: 96.233398 + temp: 25.030000; press: 98.007187; humidity: 92.700195 + temp: 25.290000; press: 98.170148; humidity: 93.313476 + temp: 25.720000; press: 98.259449; humidity: 97.685546 + temp: 26.110000; press: 98.343542; humidity: 98.500976 + temp: 26.440000; press: 98.409437; humidity: 98.906250 + temp: 26.710000; press: 98.454328; humidity: 98.942382 + temp: 26.930000; press: 98.481500; humidity: 98.909179 + temp: 27.100000; press: 98.495117; humidity: 98.899414 + temp: 27.230000; press: 98.496042; humidity: 98.838867 + temp: 27.340000; press: 98.484203; humidity: 98.780273 + temp: 27.420000; press: 98.461601; humidity: 98.681640 + +To build **bme280** test run command with DMA support: + +.. code-block:: bash + + west build -b rz_g3s -p always samples/sensor/bme280 -S rz-g3s-i2c-dma + +Console output looks the same as above. + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/icu/interrupts.rst b/boards/arm/rz_g3s/doc/icu/interrupts.rst new file mode 100644 index 00000000000000..279c1c4a9a6170 --- /dev/null +++ b/boards/arm/rz_g3s/doc/icu/interrupts.rst @@ -0,0 +1,328 @@ +Interrupt Controller +==================== + +Overview +-------- + +The interrupt controller decides the priority of interrupt sources and controls interrupt requests to the CPU. +The interrupt controller registers set the order of priority of each interrupt, allowing the user to process interrupt +requests according to the user-set priority. + +Cortex-M33/Cortex-M33_FPU has Nested Vectored Interrupt Controller (NVIC) built in: + +* 256 levels of priority +* 480 interrupts + +All IRQ signals are routed to ARM NVIC through IM33/IM33_FPU modules. + +The IM33/IM33_FPU performs various interrupt controls including synchronization for the external interrupts of NMI, IRQ +and GPIOINT and internal peripheral interrupts output by each IP. +And it notifies the interrupt to the built-in interrupt controller (NVIC) for Cortex-M33/Cortex-M33_FPU. + +* Select 32 TINT from 82 GPIOINT. +* Indicate interrupt status to NVIC. +* Set interrupt detection method. (NMI, IRQ and TINT) +* Integration of bus error interrupts from system bus. +* Integration of ECC error interrupts from On-chip RAM. +* All interrupts can be masked by setting of SYSC Register. + +External Interrupts pin IRQs supported are: + +* NMI +* IRQ0-7 +* TINT0-31 from 82 GPIOINT + +Refer to Arm® Cortex®-M33 Processor Revision: r0p4 Technical Reference Manual. + +Refer to "Interrupt Controller" section in Renesas RZ/G3S Group User’s Manual: Hardware + +NMI pin IRQ +``````````` + +NMI interrupt is the highest priority interrupt by default even though it can be masked. +NMI is not treated as NMI exception. +The NMI pin input is detected by edge. +It can be selected “Rising-edge detection” or “Falling-edge detection”. + +IRQ pin Interrupts +`````````````````` + +IRQ interrupt is the interrupt from IRQ0-7 input pins. +Using IRQ pins as interrupt must be mapped GPIO pins onto IRQ pins by GPIO register setting. +The IRQ pin inputs are detected by a level or an edge. It can be selected “Low-level detection”, “Falling-edge +detection”, “Rising-edge detection” or “Falling/Rising-edge detection”. + +TINT GPIO IRQs +`````````````` + +The TINT processing is done by RZ G3S GPIO driver :ref:`rzg3s_gpio_label` + +Limitations +``````````` + +* bus error interrupts not supported +* ECC error interrupts not supported +* Low power modes not supported + +INTC driver overview +-------------------- + +The RZ G3S INTC driver is responsible for proper configuration and handling +of NMI and IRQ pin Interrupts and it is implemented as 2nd level interrupt controller. +The mapping between INTC logical IRQ lines and RZ G3S SoC NMI and IRQ pin Interrupts defined as below: + ++---------+---------------+ +| INTC IRQ| SoC NVIC IRQ | ++=========+===============+ +| 0 | NMI (0) | ++---------+---------------+ +| 1 | IRQ0 (1) | ++---------+---------------+ +| 2 | IRQ1 (2) | ++---------+---------------+ +| 3 | IRQ2 (3) | ++---------+---------------+ +| 4 | IRQ3 (4) | ++---------+---------------+ +| 5 | IRQ4 (5) | ++---------+---------------+ +| 6 | IRQ5 (6) | ++---------+---------------+ +| 7 | IRQ6 (7) | ++---------+---------------+ +| 8 | IRQ7 (8) | ++---------+---------------+ + +The RZ G3S INTC driver is enabled by default if corresponding DT node is enabled. +In addition below Kconfig options enabled in rz_g3s_defconfig. + +.. code-block:: text + + CONFIG_MULTI_LEVEL_INTERRUPTS=y + CONFIG_DYNAMIC_INTERRUPTS=y + /* automatically enabled */ + CONFIG_INTC_R9A08G045=y + +The RZ G3S INTC driver code can be found at: + +.. code-block:: text + + drivers/interrupt_controller/intc_r9a08g045.c + +The helper macro are defined in: + +.. code-block:: text + + dt-bindings/interrupt-controller/r7s9210-intc.h + + +INTC driver testing +------------------- + +samples/drivers/irq_keys +```````````````````````` + +The **irq_keys** sample allows to test both NMI and IRQ pin Interrupts on RZ/G3S SMARC Evaluation Board Kit. + + +* GPIO P0_3 pin is configured as IRQ1 and routed to the USER_SW3 button (GPIO7). IRQ is tested by pressing button. + +.. warning:: !!Do with Caution!! + + NMI pin connected to PCIE_WAKE# signal which is routed to the B11 pin of the PCIE_SLOT connector. + NMI pin IRQ can be tested by grounding B11 pin of the PCIE_SLOT connector. + Caution: pin B10 is power line don't touch it. + +The **irq_keys** DT overlay (samples/drivers/irq_keys/boards/rz_g3s.overlay) for RZ/G3S SMARC Evaluation Board Kit, +which shows example DT configuration is below: + +.. code-block:: dts + + / { + keyboard { + compatible = "irq-keys"; + + pinctrl-names = "default"; + pinctrl-0 = <&keyboard_pins>; + + sw3 { + interrupt-parent = <&intc>; + interrupts = ; + }; + + sw_nmi { + interrupt-parent = <&intc>; + interrupts = ; + }; + }; + }; + + &pinctrl { + keyboard_pins: keyboard_pins { + sw3-pinmux { + pinmux = ; /* IRQ1 */ + input-debounce = <(PINCTRL_RZG3S_FILTER_SET(3, 3))>; + }; + + sw3-pins { + pins = "NMI"; + input-debounce = <(PINCTRL_RZG3S_FILTER_SET(1, 2))>; + }; + }; + }; + +To build **irq_keys** test run command: + +.. code-block:: bash + + west build -b rz_g3s -p always samples/drivers/irq_keys/ + +The **irq_keys** test will produce below console output when executed, +where lines marked as **"irq line 1536"** corresponds to USER_SW3 and +lines marked as **"irq line 512"** corresponds to NMI IRQ: + +.. code-block:: console + + [00:00:00.000,000] main: Starting IRQ keys sample... + Number of IRQ Keys detected 2 + [00:00:06.171,000] main: Button (irq line 1536) pressed 1 times + [00:00:06.475,000] main: Button (irq line 1536) pressed 2 times + [00:00:09.589,000] main: Button (irq line 1536) pressed 3 times + [00:00:10.009,000] main: Button (irq line 1536) pressed 4 times + [00:00:11.158,000] main: Button (irq line 1536) pressed 5 times + [00:00:11.158,000] main: Changing of IRQ line (1536) detection mode to FALLING EDGE + [00:00:11.159,000] main: Button (irq line 1536) pressed 7 times + [00:00:11.259,000] main: Button (irq line 1536) pressed 8 times + [00:00:11.259,000] main: Changing of IRQ line (1536) detection mode to RISING EDGE + [00:00:11.362,000] main: Button (irq line 1536) pressed 9 times + [00:00:11.363,000] main: Button (irq line 1536) pressed 10 times + [00:00:11.363,000] main: Button (irq line 1536) pressed 11 times + [00:00:11.363,000] main: Changing of IRQ line (1536) detection mode to FALLING EDGE + [00:00:18.425,000] main: Button (irq line 512) pressed 1 times + [00:00:18.634,000] main: Button (irq line 512) pressed 2 times + [00:00:18.634,000] main: Button (irq line 512) pressed 3 times + [00:00:18.635,000] main: Changing of IRQ line (512) detection mode to FALLING EDGE + [00:00:18.635,000] main: Button (irq line 512) pressed 5 times + [00:00:19.678,000] main: Button (irq line 512) pressed 6 times + [00:00:19.679,000] main: Changing of IRQ line (512) detection mode to RISING EDGE + [00:00:19.681,000] main: Button (irq line 512) pressed 7 times + [00:00:19.682,000] main: Button (irq line 512) pressed 8 times + [00:00:20.860,000] main: Button (irq line 512) pressed 9 times + [00:00:20.861,000] main: Changing of IRQ line (512) detection mode to FALLING EDGE + +ARM NVIC testing +---------------- + +tests/arch/arm/arm_interrupt +```````````````````````````` + +This test to verify code fault handling in ISR execution context and the behavior of irq_lock() and irq_unlock() +when invoked from User Mode. An additional test case verifies that null pointer dereferencing +attempts are detected and interpreted as CPU faults. + +To build **tests/arch/arm/arm_interrupt** test run command: + +.. code-block:: bash + + west build -b rz_g3s -p always tests/arch/arm/arm_interrupt + +Console output: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-340-g17158a79e662 *** + Running TESTSUITE arm_interrupt + =================================================================== + START - test_arm_esf_collection + Testing ESF Reporting + E: ***** USAGE FAULT ***** + E: Attempt to execute undefined instruction + E: r0/a1: 0x00000000 r1/a2: 0x00000001 r2/a3: 0x00000002 + E: r3/a4: 0x00000003 r12/ip: 0x0000000c r14/lr: 0x0000000f + E: xpsr: 0x01000000 + E: Faulting instruction address (r15/pc): 0x0002ec68 + E: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0 + E: Current thread: 0x20050080 (unknown) + Caught system error -- reason 0 + PASS - test_arm_esf_collection in 0.038 seconds + =================================================================== + START - test_arm_interrupt + Available IRQ line: 479 + E: >>> ZEPHYR FATAL ERROR 1: Unhandled interrupt on CPU 0 + E: Current thread: 0x20050140 (test_arm_interrupt) + Caught system error -- reason 1 + E: r0/a1: 0x00000003 r1/a2: 0x20054944 r2/a3: 0x00000003 + E: r3/a4: 0x200539a0 r12/ip: 0x00000008 r14/lr: 0x000255cf + E: xpsr: 0x610001ef + E: Faulting instruction address (r15/pc): 0x00023de2 + E: >>> ZEPHYR FATAL ERROR 3: Kernel oops on CPU 0 + E: Fault during interrupt handling + + E: Current thread: 0x20050140 (test_arm_interrupt) + Caught system error -- reason 3 + E: r0/a1: 0x00000004 r1/a2: 0x20054944 r2/a3: 0x00000004 + E: r3/a4: 0x200539a0 r12/ip: 0x00000000 r14/lr: 0x000255cf + E: xpsr: 0x610001ef + E: Faulting instruction address (r15/pc): 0x00023e00 + E: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0 + E: Fault during interrupt handling + + E: Current thread: 0x20050140 (test_arm_interrupt) + Caught system error -- reason 4 + ASSERTION FAIL [0] @ WEST_TOPDIR/zephyr/tests/arch/arm/arm_interrupt/src/arm_interrupt.c:225 + Intentional assert + + E: r0/a1: 0x00000004 r1/a2: 0x000000e1 r2/a3: 0x20050140 + E: r3/a4: 0x000001ef r12/ip: 0x00000000 r14/lr: 0x000255cf + E: xpsr: 0x610001ef + E: Faulting instruction address (r15/pc): 0x0002ef54 + E: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0 + E: Fault during interrupt handling + + E: Current thread: 0x20050140 (test_arm_interrupt) + Caught system error -- reason 4 + E: ***** USAGE FAULT ***** + E: Stack overflow (context area not valid) + E: r0/a1: 0x00000000 r1/a2: 0x00000000 r2/a3: 0x000240b6 + E: r3/a4: 0x01000000 r12/ip: 0x00000000 r14/lr: 0x00000000 + E: xpsr: 0x00000000 + E: Faulting instruction address (r15/pc): 0x00000000 + E: >>> ZEPHYR FATAL ERROR 2: Stack overflow on CPU 0 + E: Current thread: 0x20050140 (test_arm_interrupt) + Caught system error -- reason 2 + PASS - test_arm_interrupt in 0.161 seconds + =================================================================== + START - test_arm_null_pointer_exception + E: ***** MPU FAULT ***** + E: Data Access Violation + E: MMFAR Address: 0x4 + E: r0/a1: 0x00000000 r1/a2: 0x00030054 r2/a3: 0x00000000 + E: r3/a4: 0x00000000 r12/ip: 0x00030040 r14/lr: 0x0002ec1f + E: xpsr: 0x61000000 + E: Faulting instruction address (r15/pc): 0x00023cae + E: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0 + E: Current thread: 0x20050140 (test_arm_null_pointer_exception) + Caught system error -- reason 0 + PASS - test_arm_null_pointer_exception in 0.038 seconds + =================================================================== + START - test_arm_user_interrupt + PASS - test_arm_user_interrupt in 0.001 seconds + =================================================================== + TESTSUITE arm_interrupt succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [arm_interrupt]: pass = 4, fail = 0, skip = 0, total = 4 duration = 0.238 seconds + - PASS - [arm_interrupt.test_arm_esf_collection] duration = 0.038 seconds + - PASS - [arm_interrupt.test_arm_interrupt] duration = 0.161 seconds + - PASS - [arm_interrupt.test_arm_null_pointer_exception] duration = 0.038 seconds + - PASS - [arm_interrupt.test_arm_user_interrupt] duration = 0.001 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/img/1_8v.jpg b/boards/arm/rz_g3s/doc/img/1_8v.jpg new file mode 100644 index 00000000000000..0d5a1ff81e3c1e Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/1_8v.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/SER1.jpg b/boards/arm/rz_g3s/doc/img/SER1.jpg new file mode 100644 index 00000000000000..02295a269c95d3 Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/SER1.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/emmc_mode.png b/boards/arm/rz_g3s/doc/img/emmc_mode.png new file mode 100644 index 00000000000000..ba81444cf46ab0 Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/emmc_mode.png differ diff --git a/boards/arm/rz_g3s/doc/img/i2c_rzg3s.jpg b/boards/arm/rz_g3s/doc/img/i2c_rzg3s.jpg new file mode 100644 index 00000000000000..3f7298f3200f4c Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/i2c_rzg3s.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/logic_analyzer.jpg b/boards/arm/rz_g3s/doc/img/logic_analyzer.jpg new file mode 100644 index 00000000000000..24d89ad13023db Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/logic_analyzer.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/poeg_api.jpg b/boards/arm/rz_g3s/doc/img/poeg_api.jpg new file mode 100644 index 00000000000000..6c666142579758 Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/poeg_api.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/poeg_connection.jpg b/boards/arm/rz_g3s/doc/img/poeg_connection.jpg new file mode 100644 index 00000000000000..7e428b6d9c0411 Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/poeg_connection.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/pwm_ab.jpg b/boards/arm/rz_g3s/doc/img/pwm_ab.jpg new file mode 100644 index 00000000000000..e4c7868b40c0ee Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/pwm_ab.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/pwm_ab_poeg.jpg b/boards/arm/rz_g3s/doc/img/pwm_ab_poeg.jpg new file mode 100644 index 00000000000000..21dafbea79d0fe Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/pwm_ab_poeg.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/pwm_ab_schema.jpg b/boards/arm/rz_g3s/doc/img/pwm_ab_schema.jpg new file mode 100644 index 00000000000000..3ea052be407dc4 Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/pwm_ab_schema.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/pwm_loopback.jpg b/boards/arm/rz_g3s/doc/img/pwm_loopback.jpg new file mode 100644 index 00000000000000..9a793d06cb0dab Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/pwm_loopback.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/rzg3s.jpg b/boards/arm/rz_g3s/doc/img/rzg3s.jpg new file mode 100644 index 00000000000000..9f10e64c113e58 Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/rzg3s.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/rzg3s_boot.jpg b/boards/arm/rz_g3s/doc/img/rzg3s_boot.jpg new file mode 100644 index 00000000000000..1a8fde42cc5c1b Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/rzg3s_boot.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/rzg3s_con.jpg b/boards/arm/rz_g3s/doc/img/rzg3s_con.jpg new file mode 100644 index 00000000000000..7ca4a58b119ad5 Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/rzg3s_con.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/rzg3s_con_diag.jpg b/boards/arm/rz_g3s/doc/img/rzg3s_con_diag.jpg new file mode 100644 index 00000000000000..c930d7a7284c89 Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/rzg3s_con_diag.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/rzg3s_jlink.jpg b/boards/arm/rz_g3s/doc/img/rzg3s_jlink.jpg new file mode 100644 index 00000000000000..21e83b158f86f7 Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/rzg3s_jlink.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/rzg3s_ser0.jpg b/boards/arm/rz_g3s/doc/img/rzg3s_ser0.jpg new file mode 100644 index 00000000000000..0b34a2a55ebc3f Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/rzg3s_ser0.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/scif_mode.png b/boards/arm/rz_g3s/doc/img/scif_mode.png new file mode 100644 index 00000000000000..947465ccfd4bea Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/scif_mode.png differ diff --git a/boards/arm/rz_g3s/doc/img/sd_connection.jpg b/boards/arm/rz_g3s/doc/img/sd_connection.jpg new file mode 100644 index 00000000000000..f773976d313ce3 Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/sd_connection.jpg differ diff --git a/boards/arm/rz_g3s/doc/img/spi_mode.png b/boards/arm/rz_g3s/doc/img/spi_mode.png new file mode 100644 index 00000000000000..74d58239cf4548 Binary files /dev/null and b/boards/arm/rz_g3s/doc/img/spi_mode.png differ diff --git a/boards/arm/rz_g3s/doc/index.rst b/boards/arm/rz_g3s/doc/index.rst new file mode 100644 index 00000000000000..21a559dcb92808 --- /dev/null +++ b/boards/arm/rz_g3s/doc/index.rst @@ -0,0 +1,350 @@ +.. _rz_g3s: +.. _rz_g3s_fpu: + +################################# +RZ/G3S SMARC Evaluation Board Kit +################################# + +.. only:: html + + .. contents:: + :depth: 5 + +.. _Linux Start-up Guide for RZ/G3S Board Support Package: https://www.renesas.com/us/en/document/mas/linux-start-guide-rzg3s-board-support-package-v100 + +.. _Overview: + +Overview +******** + +The Renesas Evaluation Board Kit for RZ/G3S MPU (RZ/G3S-EVKIT) consists +of a module board (SOM) and a carrier board. The module board complies with the SMARC v2.1 standard. + +.. toctree:: + :maxdepth: 4 + + delivery/delivery_scope.rst + delivery/getting_source_code.rst + delivery/yocto_build.rst + delivery/hello_world_start.rst + delivery/boot.rst + delivery/uboot_int.rst + delivery/linux_int.rst + +Hardware +******** + +The Renesas RZ/G3S MPU documentation can be found at: + +`RZ/G3S MPU `_ + +The Renesas Evaluation Board Kit for RZ/G3S MPU (RZ/G3S-EVKIT) documentation can be found at: + +`Evaluation Board Kit for RZ/G3S MPU `_ + +`RZG3S SMARC Module Board User's Manual Hardware `_ + +`RZ SMARC Series Carrier Board II User's Manual Hardware `_ + +The RZ G3S includes: + +* Device: RZ/G3S R9A08G045S33GBG + + * Cortex-A55 Single, Cortex-M33 x2 + * BGA 359-pin, 14mmSq body, 0.5mm pitch + +* Module Board Functions + + * LPDDR4 SDRAM: 1GB × 1pc + * QSPI flash memory: 128Mb × 1pc + * eMMC memory: 64GB × 1pc + * PMIC power supply RAA215300A2GNP#HA3 implemented + * microSD card x2 + * I3C connector + * JTAG connector + * ADC x8 channels + * Current monitor (USB Micro B) + +* Carrier Board Functions + + * Gigabit Ethernet x2 + * USB2.0 x2ch (OTG x1ch, Host x1ch) + * CAN-FD x2 + * microSD card x1 + * Mono speaker, Stereo headphone, Mic., and Aux.. + * PMOD x2 + * USB-Type C for power input + * PCIe Gen2 4-lane slot (G3S supports only 1-lane) + * M.2 Key E + * M.2 Key B and SIM card + * Coin cell battery holder (3.0V support) + +Connections and IOs +=================== + +.. toctree:: + :maxdepth: 4 + + delivery/initial_config.rst + +Supported Features +================== + +The Renesas ``rz_g3s`` board configuration supports the following +hardware features: + ++----------+------------------+--------------------+ +| Interface| Driver/components| Support level | ++==========+==================+====================+ +| PINCTRL | pinctrl | | ++----------+------------------+--------------------+ +| CLOCK | clock_control | | ++----------+------------------+--------------------+ +| gpio | gpio | | ++----------+------------------+--------------------+ +| UART | uart | serial port-polling| ++----------+------------------+--------------------+ +| rSPI | spi | 8/16 bit transfers | ++----------+------------------+--------------------+ +| I2C | i2c | | ++----------+------------------+--------------------+ +| Watchdog | wdt | | ++----------+------------------+--------------------+ +| ADC | adc | | ++----------+------------------+--------------------+ +| CAN-FD | can | | ++----------+------------------+--------------------+ +| DMAC | dma | | ++----------+------------------+--------------------+ +| GTM | timer | GTM as OS Timer | ++----------+------------------+--------------------+ +| GTM | counter | GTM as Counter | ++----------+------------------+--------------------+ +| GPT | pwm | | ++----------+------------------+--------------------+ +| POEG | pwm | POEG for GPT | ++----------+------------------+--------------------+ + +Other hardware features have not been enabled yet for this board. + +The default configuration can be found in the defconfig file: + +.. code-block:: text + + boards/arm/rz_g3s/rz_g3s_defconfig + +.. _rz_g3s_prog_debug: + +Programming and Debugging +************************* + +.. note:: + + Ensure all prerequisite steps, described in :ref:`Overview` section, are done and RZ/G3S-EVKIT board has corresponding BL2 bootloader + (ARM trusted firmware TF-A with **PLAT_M33_BOOT_SUPPORT** option enabled) flashed on eMMC(xSPI) and BL2 TF-A is booted properly. + +Applications for the ``rz_g3s`` board can be built in the usual way as documented +in :ref:`build_an_application`. + +The generating of binaries for RZ G3S Cortex-M33 and Cortex-M33_FPU system cores is +supported by using different board names: + +* ``rz_g3s`` for Cortex-M33 +* ``rz_g3s_fpu`` for Cortex-M33_FPU + +These are the memory mapping for A55 and M33: + ++----------+-----------------------+-----------------------+ +| Region | Cortex-M33 | Cortex-M33-FPU | ++==========+=======================+=======================+ +| SRAM code| 0x00023000-0x0005FC00 | 0x00063000-0x0009FC00 | ++----------+-----------------------+-----------------------+ +| DDR | 0x60000000-0x60FFFFFF | 0x61000000-0x61FFFFFF | ++----------+-----------------------+-----------------------+ + +Console +======= + +There are 2 UART ports supported from Zephyr on RZ/G3S SMARC Evaluation Board Kit board, +which assigned to Cortex-M33 System Cores as following: + +* Cortex-M33: SER0 from PMOD1_3A +* Cortex-M33_FPU: SER1 from SER1_UART + +Refer to the section :ref:`rz_g3s_con` for more information about board connection and console setup. + +.. _Debugging: + +Debugging +========= + +It is possible to load and execute a Zephyr application binary on +this board on one of the Cortex-M33/Cortex-M33_FPU System Cores from +the internal SRAM, using ``JLink`` debugger (:ref:`jlink-debug-host-tools`). + +.. note:: + + Currently it's required Renesas BL2 TF-A to be started on Cortex-A55 System Core + before starting Zephyr. As BL2 TF-A configures clocks and Cortex-A33 before starting it. + ++----------------+--------------------+ +| | JLink device id | ++================+====================+ +| Cortex-M33 | R9A08G045S33_M33_0 | ++----------------+--------------------+ +| Cortex-M33_FPU | R9A08G045S33_M33_1 | ++----------------+--------------------+ + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: rz_g3s + :goals: debug + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: rz_g3s_fpu + :goals: debug + +Flashing +======== + +.. note:: + + The flashing using west environment is not fully supported. + +Zephyr application can be flashed to eMMC or qSPI storage and then loaded by +Renesas BL2 TF-A running on Cortex-A55 System Core. +and staring binary at Cortex-M33 System Core. + +.. note:: + + Flashing is supported only for Cortex-M33 System Core. + Zephyr application can be started on Cortex-M33_FPU System Core only by using debugger. + +More information about flashing to eMMC(xSPI) can be found in Renesas document: +`Linux Start-up Guide for RZ/G3S Board Support Package`_. + +The Zephyr application binary has to be converted to Motorolla S-record `SREC`_ format +which is generated automatically in Zephyr application build directory (`*zephyr.srec*`). + +.. _SREC: https://en.wikipedia.org/wiki/SREC_(file_format) + +Follow `Linux Start-up Guide for RZ/G3S Board Support Package`_: + +* section "4.2.3 Settings" for enabling :ref:`SCIF boot` +* section "4.3 Download Flash Writer to RAM" (FlashWriter-smarc-rzg3s.mot). Refer to :ref:`Upload with minicom` + +.. _Flashing on eMMC: + +Flashing on eMMC +---------------- + +* Download and start **Flash Writer** as described above. +* Use **Flash Writer EM_W** command to flash Zephyr binary +* Input when asked: + +.. code-block:: console + + Select area(0-2)>1 + Please Input Start Address in sector :1000 + Please Input Program Start Address : 23000 + +* then send Zephyr **srec** file from terminal (use ''ascii'' mode) +* reboot the board in the **eMMC Boot Mode** + +.. code-block:: console + + >EM_W + EM_W Start -------------- + --------------------------------------------------------- + Please select,eMMC Partition Area. + 0:User Partition Area : 62160896 KBytes + eMMC Sector Cnt : H'0 - H'0768FFFF + 1:Boot Partition 1 : 32256 KBytes + eMMC Sector Cnt : H'0 - H'0000FBFF + 2:Boot Partition 2 : 32256 KBytes + eMMC Sector Cnt : H'0 - H'0000FBFF + --------------------------------------------------------- + Select area(0-2)>1 + -- Boot Partition 1 Program ----------------------------- + Please Input Start Address in sector :1000 + Please Input Program Start Address : 23000 + Work RAM (H'00020000-H'000FFFFF) Clear.... + please send ! ('.' & CR stop load) + +.. _Flashing on qSPI: + +Flashing on qSPI +---------------- + +Zephyr binary has to be converted to **srec** format. + +* Download and start **Flash Writer** as described above +* Use **Flash Writer XLS2** command to flash Zephyr binary +* Input when asked: + +.. code-block:: console + + ===== Please Input Program Top Address ============ + Please Input : H'23000 + ===== Please Input Qspi Save Address === + Please Input : H'200000 + +* then send Zephyr **srec** file from terminal (use ''ascii'' mode) +* reboot the board in the **qSPI Boot Mode** + +.. code-block:: console + + -- Load Program to SRAM --------------- + + Flash writer for RZ/G3S Series V0.60 Jan.26,2023 + Product Code : RZ/G3S + >XLS2 + ===== Qspi writing of RZ/G2 Board Command ============= + Load Program to Spiflash + Writes to any of SPI address. + Program size & Qspi Save Address + ===== Please Input Program Top Address ============ + Please Input : H'23000 + + ===== Please Input Qspi Save Address === + Please Input : H'200000 + please send ! ('.' & CR stop load) + I Flash memory... + Erase Completed + Write to SPI Flash memory. + ======= Qspi Save Information ================= + SpiFlashMemory Stat Address : H'00200000 + SpiFlashMemory End Address : H'002098E6 + =========================================================== + +Supported Features Details +************************** + +.. toctree:: + :maxdepth: 4 + + cortex-m/fpu.rst + cortex-m/mpu.rst + cortex-m/systick.rst + cortex-m/sau.rst + cpg/cpg.rst + pinctrl/pinctrl.rst + icu/interrupts.rst + uart/uart.rst + gpio/gpio.rst + rspi/rspi.rst + i2c/i2c.rst + wdt/wdt.rst + adc/adc.rst + canfd/canfd.rst + ostm_gtm/ostm_gtm.rst + openamp/mhu.rst + openamp/openamp.rst + pwm/GPT.rst + pwm/poeg.rst + dma/dma.rst + delivery/west_flash.rst + delivery/fpu_snippet.rst diff --git a/boards/arm/rz_g3s/doc/openamp/mhu.rst b/boards/arm/rz_g3s/doc/openamp/mhu.rst new file mode 100644 index 00000000000000..c014b2789d450a --- /dev/null +++ b/boards/arm/rz_g3s/doc/openamp/mhu.rst @@ -0,0 +1,64 @@ +Message Handling Unit (MHU) +=========================== + +Overview +-------- + +MHU is a function for message communication between Cortex-A55 and Cortex-M33(FPU) cores. +Message communication is done by shared RAM (On-chip RAM) for passing message and +response between CPUs and the function (MHU) for notifying when messages and responses are stored in the memory. + +It povides the following functions: + +* Interrupt by Message and response +* Event routing function +* Software interrupt control +* Provides 5 secure and 5 non-secure channels + +Refer to "Message Handling Unit (MHU)" section in Renesas RZ/G3S Group User’s Manual: Hardware + +Limitations +``````````` + +* Software interrupt control not supported + +MHU driver overview +-------------------- + +The RZ G3S MHU driver instance implements MHU single channel to communicate between two cores. +It provides Zephyr :ref:`ipm_api` System interface implementation. +The device-tree node to configure driver is the following: + +.. code-block:: dts + + mhu1_shm: memory@62F01000 { + compatible = "mmio-sram"; + reg = <0x62F01000 0x8>; + }; + + mhu1: mhu@40400020 { + compatible = "renesas,mhu"; + reg = <0x40400020 0x20>; + interrupts = <58 0>; + interrupt-parent = <&nvic>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + mhu_type = <1>; + memory-region = <&mhu1_shm>; + status = "disabled"; + }; + +Where: + +* mhu_type can be 0 to configure MHU to work as transmitter and 1 to work as responder +* memory-region accepts phandle for memory within shared memory region to pass data between CPU + +MHU driver testing +------------------- + +MHU driver for Cortex-M33 and Cortex-M33_FPU cores can be tested from **openamp_rsc_table_rzg3** sample. +Please refer to **Openamp** section for additional information. + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/openamp/openamp.rst b/boards/arm/rz_g3s/doc/openamp/openamp.rst new file mode 100644 index 00000000000000..a8e5b821e12504 --- /dev/null +++ b/boards/arm/rz_g3s/doc/openamp/openamp.rst @@ -0,0 +1,283 @@ +.. _rz_g3s_openamp: + +OpenAMP +======= + +Overview +-------- + +OpenAMP (Open Asymmetric Multi-Processing) is a framework providing the software components needed to enable +the development of software applications for AMP systems. It allows operating systems to interact within a +broad range of complex homogeneous and heterogeneous architectures and allows asymmetric multiprocessing +applications to leverage parallelism offered by the multi-core configuration. + +The framework provides the following key capabilities. + +- Provides Life Cycle Management, and Inter Processor Communication capabilities for management of remote + compute resources and their associated software contexts. +- Provides a standalone library usable with RTOS and Baremetal software environments. +- Compatibility with upstream Linux remoteproc, rpmsg, and VirtIO component + +OpenAMP driver testing +---------------------- + +TheOpenAMP sample code can be found at: + +.. code-block:: text + + samples/subsys/ipc/openamp_rsc_table_rzg3 + +This application demonstrates how to use OpenAMP with Zephyr based on a resource_table +with RZ/G Multi-OS Package v2.0.0. +It is designed to respond for the requests from RPMSG client sample +application provided by Renesas RZ/G BSP. + +This sample implementation is compatible with platforms that embed +a Linux kernel OS on the main processor and a Zephyr application on +the co-processor. + +Design overview +``````````````` +The provided sample introduces Renesas approach implementation. +The following shared memory for OpenAMP communication was reserved: + ++-------------------------+---------+ +| Cortex-M33 Address table| Name | ++-------------------------+---------+ +| ... | | ++-------------------------+---------+ +| 0x62F00000 - 0x63500000 | OpenAMP | ++-------------------------+---------+ +| ... | | ++-------------------------+---------+ + +Where OpenAMP region divided for the following sub-regions: + ++-------------------------+----------------+ +| OpenAMP Address table | Name | ++-------------------------+----------------+ +| 0x62F00000 - 0x62F01000 | resource_table | ++-------------------------+----------------+ +| ... | | ++-------------------------+----------------+ +| 0x62F01000 - 0x62F01008 | MHU shared mem | ++-------------------------+----------------+ +| ... | | ++-------------------------+----------------+ +| 0x63000000 - 0x63005000 | VRING0 control | ++-------------------------+----------------+ +| 0x63005000 - 0x63010000 | VRING1 control | ++-------------------------+----------------+ +| ... | | ++-------------------------+----------------+ +| 0x63200000 - 0x63500000 | VRING shmem | ++-------------------------+----------------+ + +This regions are used by OpenAMP library internals to +perform interprocess communication between Cortex-A55 and Cortex-M33/Cortex-M33_FPU cores. +On Renesas RZ/G boards the shared memory between CPU are mapped in different address spaces +maps the following way: + +.. code-block:: text + + 0x40000000 - 0x4fffffff on A55 to + 0x60000000 - 0x6fffffff on M33/M33_FPU cores. + +Current implementation uses the same shared region for both Cortex-M33 and Cortex-M33_FPU cores, +as was mentioned in the document **r01an5869ej0200-rzg-cm33-multi-os-pkg.pdf** in +Multi-OS Package v2.0.0. And uses MHU ch1 to communicate with Cortex-M33 and MHU ch0 to communicate +with Cortex-M33_FPU core. + +The provided sample using resource_table to pass shared memory information from Virtio device to +Virtio driver (Linux side). By default Zephyr expects resource_table to be retrieved from the +Driver side, that's why another resource_table implementation was used. + +.. note:: + + Vring addresses, passed from Zephyr side to Linux side should be converted to Cortex-A55 format + that's why `CM33_TO_A55_ADDR_S` and `CM33_TO_A55_ADDR_NS` macros were introduced for Secure and + Non-Secure address conversion. Same is applicable for shared memory addresses. + +On initialization stage OpenAMP requests for the resource table: + +.. code-block:: C + + rsc_table_get(&rsc_tab_addr, &rsc_size); + +which is placed in the corresponding linker section and then copy to the resource table region: + +.. code-block:: C + + memcpy((void *)RSC_TABLE_ADDR, rsc_tab_addr, rsc_size); + +Where RSC_TABLE_ADDR is start address of the resource_memory shared region. + +Vring addresses should be registered in metal_virtio using Cortex-M33 addresses of vring0 and vring1 regions. + +From Linux side the following command should be used to initiate the communication + +.. code-block:: bash + + rpmsg_sample_client 0 0 + +to access Cortex-M33 core and + +.. code-block:: bash + + rpmsg_sample_client 0 1 + +to access Cortex-M33_FPU core. + +Building sample application +``````````````````````````` + +This application can be built for **rz_g3s** board to start on Cortex-M33 and for **rz_g3s_fpu** board to +start on Cortex-M33_FPU core. + +Please use the following command to build for Cortex-M33 core: + +.. code-block:: bash + + west build -p always -b rz_g3s samples/subsys/ipc/openamp_rsc_table_rzg3 + +and for Cortex-M33_FPU core: + +.. code-block:: bash + + west build -p always -b rz_g3s_fpu samples/subsys/ipc/openamp_rsc_table_rzg3 + +After building `openamp_rsc_table_rzg3` sample it can be started on JLink using :ref:`Debugging` instructions or +flashed to either eMMC or qSPI using instructions from :ref:`Flashing on eMMC` and :ref:`Flashing on qSPI`. + +Please use the following **srec** file generated on build: + +.. code-block:: bash + + /zephyr/zephyr_openamp_rsc_table.srec + +Linux BSP build preparation +``````````````````````````` + +Provided sample was designed to work with the Linux build with Zephyr support for Renesas RZ/G3S +board. BSP uses Yocto as build system. +Please refer to :ref:`Building yocto image` for download and build instructions. + +Test scenario +````````````` + +After the preparation stage the following system configuration is expected: + +* Cortex-A55 is booted to Linux and the following lines are shown on Cortex-A55 console: + +.. code-block:: console + + BSP: RZG3S/RZG3S-SMARC-EVK/1.0.0 + LSI: RZG3S + Version: 1.0.0 + smarc-rzg3s login: root + [ 23.035550] audit: type=1006 audit(1600598656.996:2): pid=172 uid=0 old-auid=4294967295 auid=0 tty=(none) old-ses=4294967295 ses=1 res=1 + root@smarc-rzg3s:~# + +Use `root` user to login. + +* `openamp_rsc_table_rzg3` loaded to either CM33 or CM33_FPU core or loaded for qSPI/eMMC see :ref:`Flash loaders` + +.. note:: + + When starting `openamp_rsc_table_rzg3` on Cortex-M33_FPU please assure that qSPI and eMMC doesn't flashed with `openamp_rsc_table_rzg3`. + If it is please reflash it with :ref:`hello_world` sample. + +The following lines should appear on Cortex-M33/M33_FPU console: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-423-g6f6e7f30b321 *** + I: Starting application..! + I: Starting application threads! + I: OpenAMP[remote] linux responder demo started + +* From Linux console please run the following commands: + +.. code-block:: bash + + rpmsg_client_sample 0 0 + +to start test with Cortex-M33 core and + +.. code-block:: bash + + rpmsg_client_sample 0 1 + +to start test with Cortex-M33_FPU core. + +* On Linux console the following output should appear: + +.. code-block:: console + + root@smarc-rzg3s:~# rpmsg_sample_client 0 0 + Successfully probed IPI device + metal: info: metal_uio_dev_open: No IRQ for device 42f00000.rsctbl. + Successfully open uio device: 42f00000.rsctbl. + Successfully added memory device 42f00000.rsctbl. + metal: info: metal_uio_dev_open: No IRQ for device 43000000.vring-ctl0. + Successfully open uio device: 43000000.vring-ctl0. + Successfully added memory device 43000000.vring-ctl0. + metal: info: metal_uio_dev_open: No IRQ for device 43200000.vring-shm0. + Successfully open uio device: 43200000.vring-shm0. + Successfully added memory device 43200000.vring-shm0. + metal: info: metal_uio_dev_open: No IRQ for device 42f01000.mhu-shm. + Successfully open uio device: 42f01000.mhu-shm. + Successfully added memory device 42f01000.mhu-shm. + Initialize remoteproc successfully. + creating remoteproc virtio + initializing rpmsg shared buffer pool + initializing rpmsg vdev + 1 - Send data to remote core, retrieve the echo and validate its integrity .. + Remote proc init. + RPMSG endpoint has created. + RPMSG service has created. + sending payload number 0 of size 17 + echo test: sent : 17 + received payload number 0 of size 17 + sending payload number 1 of size 18 + echo test: sent : 18 + received payload number 1 of size 18 + sending payload number 2 of size 19 + echo test: sent : 19 + + [snip] + + sending payload number 471 of size 488 + echo test: sent : 488 + received payload number 471 of size 488 + ************************************ + Test Results: Error count = 0 + ************************************ + Quitting application .. Echo test end + Stopping application... + root@smarc-rzg3s:~# + +* On Cortex-M33/M33_FPU console the following output should appear: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-423-g6f6e7f30b321 *** + I: Starting application..! + I: Starting application threads! + I: OpenAMP[remote] linux responder demo started + I: new_service_cb: message received from service rpmsg-service-0 + I: OpenAMP[remote] Linux sample client responder started + I: OpenAMP demo ended + I: OpenAMP Linux sample client responder ended + I: Starting application threads! + I: OpenAMP[remote] linux responder demo started + I: new_service_cb: message received from service rpmsg-service-0 + I: OpenAMP[remote] Linux sample client responder started + I: OpenAMP demo ended + I: OpenAMP Linux sample client responder ended + I: Starting application threads! + I: OpenAMP[remote] linux responder demo started + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/ostm_gtm/counter_api_test.rst b/boards/arm/rz_g3s/doc/ostm_gtm/counter_api_test.rst new file mode 100644 index 00000000000000..13c1b7cd384861 --- /dev/null +++ b/boards/arm/rz_g3s/doc/ostm_gtm/counter_api_test.rst @@ -0,0 +1,198 @@ +tests/drivers/counter/counter_basic_api +``````````````````````````````````````` + +The **tests/drivers/counter/counter_basic_api** test is intended to perform full testing of +Zephyr Counter API interaction with RZ G3S GTM/OSTM Counter driver. + +To build **tests/drivers/counter/counter_basic_api** test run command: + +.. code-block:: bash + + west build -b rz_g3s -p always tests/drivers/counter/counter_basic_api + +The **tests/drivers/counter/counter_basic_api** test will produce below console output when executed: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-348-g43d0f3af38ae *** + Running TESTSUITE counter_basic + =================================================================== + START - test_all_channels + Testing timer@42801000 + Testing timer@42801400 + Testing timer@42801800 + Testing timer@42801c00 + Testing timer@42802000 + Testing timer@42802400 + Testing timer@42802800 + Testing timer@42802c00 + PASS - test_all_channels in 1.054 seconds + =================================================================== + START - test_cancelled_alarm_does_not_expire + Testing timer@42801000 + Testing timer@42801400 + Testing timer@42801800 + Testing timer@42801c00 + Testing timer@42802000 + Testing timer@42802400 + Testing timer@42802800 + Testing timer@42802c00 + PASS - test_cancelled_alarm_does_not_expire in 8.146 seconds + =================================================================== + START - test_late_alarm + Testing timer@42801000 + Testing timer@42801400 + Testing timer@42801800 + Testing timer@42801c00 + Testing timer@42802000 + Testing timer@42802400 + Testing timer@42802800 + Testing timer@42802c00 + PASS - test_late_alarm in 0.815 seconds + =================================================================== + START - test_late_alarm_error + Testing timer@42801000 + Testing timer@42801400 + Testing timer@42801800 + Testing timer@42801c00 + Testing timer@42802000 + Testing timer@42802400 + Testing timer@42802800 + Testing timer@42802c00 + PASS - test_late_alarm_error in 0.814 seconds + =================================================================== + START - test_multiple_alarms + Skipped for timer@42801000 + Skipped for timer@42801400 + Skipped for timer@42801800 + Skipped for timer@42801c00 + Skipped for timer@42802000 + Skipped for timer@42802400 + Skipped for timer@42802800 + Skipped for timer@42802c00 + PASS - test_multiple_alarms in 0.816 seconds + =================================================================== + START - test_set_top_before_start_with_alarm + Testing timer@42801000 + E: timer@42801000:"alarm: not supported in interval mode" + Testing timer@42801400 + E: timer@42801400:"alarm: not supported in interval mode" + Testing timer@42801800 + E: timer@42801800:"alarm: not supported in interval mode" + Testing timer@42801c00 + E: timer@42801c00:"alarm: not supported in interval mode" + Testing timer@42802000 + E: timer@42802000:"alarm: not supported in interval mode" + Testing timer@42802400 + E: timer@42802400:"alarm: not supported in interval mode" + Testing timer@42802800 + E: timer@42802800:"alarm: not supported in interval mode" + Testing timer@42802c00 + E: timer@42802c00:"alarm: not supported in interval mode" + PASS - test_set_top_before_start_with_alarm in 2.008 seconds + =================================================================== + START - test_set_top_before_start_with_callback + Testing timer@42801000 + Testing timer@42801400 + Testing timer@42801800 + Testing timer@42801c00 + Testing timer@42802000 + Testing timer@42802400 + Testing timer@42802800 + Testing timer@42802c00 + PASS - test_set_top_before_start_with_callback in 1.646 seconds + =================================================================== + START - test_set_top_value_with_alarm + Testing timer@42801000 + Testing timer@42801400 + Testing timer@42801800 + Testing timer@42801c00 + Testing timer@42802000 + Testing timer@42802400 + Testing timer@42802800 + Testing timer@42802c00 + PASS - test_set_top_value_with_alarm in 1.686 seconds + =================================================e================= + START - test_set_top_with_callback_two_times + Testing timer@42801000 + Testing timer@42801400 + Testing timer@42801800 + Testing timer@42801c00 + Testing timer@42802000 + Testing timer@42802400 + Testing timer@42802800 + Testing timer@42802c00 + PASS - test_set_top_with_callback_two_times in 2.639 seconds + =================================================================== + START - test_short_relative_alarm + Testing timer@42801000 + Testing timer@42801400 + Testing timer@42801800 + Testing timer@42801c00 + Testing timer@42802000 + Testing timer@42802400 + Testing timer@42802800 + Testing timer@42802c00 + PASS - test_short_relative_alarm in 0.880 seconds + =================================================================== + START - test_single_shot_alarm_notop + Testing timer@42801000 + Testing timer@42801400 + Testing timer@42801800 + Testing timer@42801c00 + Testing timer@42802000 + Testing timer@42802400 + Testing timer@42802800 + Testing timer@42802c00 + PASS - test_single_shot_alarm_notop in 1.374 seconds + =================================================================== + START - test_single_shot_alarm_top + Skipped for timer@42801000 + Skipped for timer@42801400 + Skipped for timer@42801800 + Skipped for timer@42801c00 + Skipped for timer@42802000 + Skipped for timer@42802400 + Skipped for timer@42802800 + Skipped for timer@42802c00 + PASS - test_single_shot_alarm_top in 0.816 seconds + =================================================================== + TESTSUITE counter_basic succeeded + Running TESTSUITE counter_no_callback + =================================================================== + START - test_set_top_value_without_alarm + Testing timer@42801000 + Testing timer@42801400 + Testing timer@42801800 + Testing timer@42801c00 + Testing timer@42802000 + Testing timer@42802400 + Testing timer@42802800 + Testing timer@42802c00 + PASS - test_set_top_value_without_alarm in 0.857 seconds + =================================================================== + TESTSUITE counter_no_callback succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [counter_basic]: pass = 12, fail = 0, skip = 0, total = 12 duration = 22.694 seconds + - PASS - [counter_basic.test_all_channels] duration = 1.054 seconds + - PASS - [counter_basic.test_cancelled_alarm_does_not_expire] duration = 8.146 seconds + - PASS - [counter_basic.test_late_alarm] duration = 0.815 seconds + - PASS - [counter_basic.test_late_alarm_error] duration = 0.814 seconds + - PASS - [counter_basic.test_multiple_alarms] duration = 0.816 seconds + - PASS - [counter_basic.test_set_top_before_start_with_alarm] duration = 2.008 seconds + - PASS - [counter_basic.test_set_top_before_start_with_callback] duration = 1.646 seconds + - PASS - [counter_basic.test_set_top_value_with_alarm] duration = 1.686 seconds + - PASS - [counter_basic.test_set_top_with_callback_two_times] duration = 2.639 seconds + - PASS - [counter_basic.test_short_relative_alarm] duration = 0.880 seconds + - PASS - [counter_basic.test_single_shot_alarm_notop] duration = 1.374 seconds + - PASS - [counter_basic.test_single_shot_alarm_top] duration = 0.816 seconds + + SUITE PASS - 100.00% [counter_no_callback]: pass = 1, fail = 0, skip = 0, total = 1 duration = 0.857 seconds + - PASS - [counter_no_callback.test_set_top_value_without_alarm] duration = 0.857 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL diff --git a/boards/arm/rz_g3s/doc/ostm_gtm/ostm_gtm.rst b/boards/arm/rz_g3s/doc/ostm_gtm/ostm_gtm.rst new file mode 100644 index 00000000000000..c2407c71f566ea --- /dev/null +++ b/boards/arm/rz_g3s/doc/ostm_gtm/ostm_gtm.rst @@ -0,0 +1,120 @@ +General Timer (GTM/OSTM) +======================== + +GTM overview +------------ + +The Renesas RZ G3S SoC has the 8 General Timers (GTM/OSTM). + +The General timer has the following features. + + * Two operating modes + + * Interval timer mode + * Free-running comparison mode + + * Choice between startup of DMA by compare match and generation of interrupt + +In Zephyr the RZ G3S General Timers can be enabled to serve as: + +* Zephyr OS timer +* Zephyr Counter + +Refer to "General Timer (GTM)" section in "Renesas RZ/G3S Group User’s Manual: Hardware" + +GTM as Zephyr OS timer +---------------------- + +When GTM is enabled as Zephyr OS timer it serves function of Zephyr Kernel System clock as described +in :ref:`kernel_timing` documentation. + +On Renesas RZ G3S platform the GTM is **not** enabled as Zephyr OS timer by default. +To enable GTM as Zephyr OS timer the **"compatible"** property of the selected GTM has to be updated to include **"renesas,ostm-timer"** and Cortex-M **Systyck** has to be disabled. The below DT example shows enabling of GTM0 as Zephyr OS timer: + +.. code-block:: dts + + >m0 { + compatible = "renesas,ostm-r9a08g045-timer", "renesas,ostm-timer"; + status = "okay"; + }; + + &systick { + status = "disabled"; + }; + +The Zephyr snippet **rz-g3s-gtm-timer-test** can be used for testing purposes and already contains DT changes for enabling GTM0 as Zephyr OS timer: + +.. code-block:: text + + snippets/rz-g3s-gtm-timer-test/README.rst + snippets/rz-g3s-gtm-timer-test/rz-g3s-gtm-timer-test.overlay + snippets/rz-g3s-gtm-timer-test/snippet.yml + +The GTM OS timer driver will be enabled in Kconfig once above DT changes are applied. + +.. code-block:: text + + CONFIG_RZ_OS_TIMER=y + /* automatically enabled */ + CONFIG_RZ_OS_TIMER=y + +The GTM OS timer driver code can be found at: + +.. code-block:: text + + drivers/timer/rz_os_timer.c + drivers/timer/Kconfig.rz + +GTM as Zephyr OS timer testing +------------------------------ + +.. toctree:: + :maxdepth: 4 + + timer_tickless_test.rst + +GTM as Zephyr Counter +--------------------- + +Zephyr RZ/G3S Renesas GTM/OSTM Counter driver provides Zephyr :ref:`counter_api` System interface implementation. + +GTM/OSTM counter can't support both alarms and changing top value in free-running mode, +so this driver allows to use either alarms in free-running (counting up) mode, or +either changing top (CMP) value in interval mode (counting down). + +Therefore: + + * driver starts with counter in free-running mode with alarms support by default; + * set top value is rejected if alarm is active; + * set top value causes counter to switch to interval mode and disables alarms; + * set top to RZ_GTM_TIMER_TOP_VALUE (0xFFFFFFFF) switches counter back to free-running mode and enables alarms; + +Over all it could be practical to use GTM Counter instance as either free-running with alarms or as +interval counter with supporting of changing top value, but not both. + +The Zephyr Counter subsystem is **not** enabled by default in ``rz_g3s_defconfig``. To enable Zephyr +Counter functionality and RZ G3S GTM/OSTM Counter driver below Kconfig options have to be enabled: + +.. code-block:: text + + CONFIG_COUNTER=y + /* automatically enabled */ + CONFIG_COUNTER_RZ_GTM_COUNTER=y + +The RZ G3S GTM/OSTM Counter driver code can be found at: + +.. code-block:: text + + drivers/counter/counter_rz_gtm.c + +GTM Counter testing +------------------- + +.. toctree:: + :maxdepth: 4 + + counter_api_test.rst + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/ostm_gtm/timer_tickless_test.rst b/boards/arm/rz_g3s/doc/ostm_gtm/timer_tickless_test.rst new file mode 100644 index 00000000000000..5b33f6d3385145 --- /dev/null +++ b/boards/arm/rz_g3s/doc/ostm_gtm/timer_tickless_test.rst @@ -0,0 +1,46 @@ +tests/kernel/tickless/tickless_concept +`````````````````````````````````````` + +Zephyr RZ/G3S GTM as Zephyr OS timer driver can be tested by using **tests/kernel/tickless/tickless_concept** test. +To build **tests/kernel/tickless/tickless_concept** test run command: + +.. code-block:: bash + + west build -p always -b rz_g3s -S rz-g3s-gtm-timer-test tests/kernel/tickless/tickless_concept + +Console output: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-331-gb7a06954094c *** + Running TESTSUITE tickless_concept + =================================================================== + START - test_tickless_slice + elapsed slice 110, expected: <100, 110> + elapsed slice 100, expected: <100, 110> + elapsed slice 100, expected: <100, 110> + elapsed slice 100, expected: <100, 110> + PASS - test_tickless_slice in 0.611 seconds + =================================================================== + START - test_tickless_sysclock + time 2920, 3130 + time 3140, 3340 + PASS - test_tickless_sysclock in 0.426 seconds + =================================================================== + TESTSUITE tickless_concept succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [tickless_concept]: pass = 2, fail = 0, skip = 0, total = 2 duration = 1.037 + ses + - PASS - [tickless_concept.test_tickless_slice] duration = 0.611 seconds + - PASS - [tickless_concept.test_tickless_sysclock] duration = 0.426 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/pinctrl/pinctrl.rst b/boards/arm/rz_g3s/doc/pinctrl/pinctrl.rst new file mode 100644 index 00000000000000..0d13c0a0ec320a --- /dev/null +++ b/boards/arm/rz_g3s/doc/pinctrl/pinctrl.rst @@ -0,0 +1,279 @@ +.. _rzg3s_pinctrl_label: + +PINCTRL/PINMUX +============== + +PINCTRL overview +---------------- + +Renesas RZ G3S (r9a08g045) SoC series has combined Pin Function and GPIO Controller module. + +The Pin Function provides possibility to configure: + +* 82 GPIO pins function and parameters. GPIO pins can work as GPIO IN/OUT pin or as peripheral function pins; + + * function: GPIO or Peripheral; + * Pull-Up/Pull-Down; + * Driving Ability; + * Digital Noise Filter; + * input GPIO pin Interrupt Enable + +* Special Purpose pins parameters - functions of such pins is fixed (NMI, I3C, AUDIO_CLK1 pins as an example) + + * Driving Ability; + * Digital Noise Filter; + * Input enable; + * Output enable; + +* Group of pins, such ETHx, SD_CHx, XSPI, I3C. For Group of pins the applied configuration affect all pins in group + + * IO voltage mode + * standby mode (I3C) + * XSPI Hi-Z pin state + +Refer to "General Purpose Input Output Port (GPIO)" section in "Renesas RZ/G3S Group User’s Manual: Hardware" + +Refer to Renesas "RZG3S_pinfunction_List_r1.1.xls" + +PINCTRL driver overview +----------------------- + +The RZ G3S PINCTRL driver provides Zephyr :ref:`pinctrl_api` System interface implementation. +The RZ G3S PINCTRL driver is defined in Device tree as pin-controller (dts/arm/renesas/rz/r9a08g045.dtsi). + +.. code-block:: dts + + pinctrl: pin-controller@41030000 { + compatible = "renesas,r9a08g045-pinctrl"; + reg = <0x41030000 DT_SIZE_K(64)>; + reg-names = "pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + }; + +Refer to DT bindings documentation: + +.. code-block:: text + + dts/bindings/pinctrl/renesas,rzg3s-pinctrl.yaml + dts/bindings/pinctrl/pincfg-node.yaml + dts/bindings/pinctrl/pinctrl-device.yaml + +The PINCTRL subsystem is enabled by default in ``rz_g3s_defconfig``, +which automatically enables RZ G3S PINCTRL driver if corresponding DT node is enabled. + +.. code-block:: text + + CONFIG_PINCTRL=y + /* automatically enabled */ + CONFIG_PINCTRL_RZG3S=y + +The RZ G3S PINCTRL driver code can be found at: + +.. code-block:: text + + drivers/pinctrl/pinctrl_rzg3s.c + drivers/pinctrl/Kconfig.rzg3s + soc/arm/renesas_rz/rz_g/pinctrl_soc.h + +The RZ G3S PINCTRL driver DT helper macro are defined in: + +.. code-block:: text + + dt-bindings/pinctrl/renesas/pinctrl-r9a08g045.h + +GPIO pins configuration +``````````````````````` + +The RZ G3S PINCTRL driver allows to configure GPIO pins by using **pinmux** DT nodes (the nodes with **pinmux** property). +The GPIO pins are grouped in Ports with up to 8 pins per ports, each of them configurable +as GPIO or Peripheral Function pin. +Up to 8 different alternate function modes exist for each single GPIO pin. + +When GPIO is used in as GPIO the pin the configurations as actually performed by request from +RZ G3S GPIO driver (:ref:`rzg3s_gpio_label`) which is passed internally to RZ G3S PINCTRL driver. + +When GPIO pin is used as Peripheral Function pin the pin configuration shell be provided in Device tree. +For RZ G3S SoC the pin control DT configuration shell be placed in *boards/arm/rz_g3s/rz_g3s_pinctrl.dtsi* file. +For example, SCIF0 pin configuration: + +.. code-block:: dts + + &pinctrl { + scif0_pins: scif0 { + scif0-pinmux { + pinmux = , /* TXD */ + ; /* RXD */ + /* Additional cfg properties */ + /* bias-pull-down; */ + /* bias-pull-up; */ + /* bias-pull-pin-default; */ + /* drive-strength-microamp; */ + /* input-debounce; */ + }; + }; + }; + +The additional optional configuration parameters will be applied to every pin specified in **pinmux** property. +The GPIO **pinmux** nodes supports following additional configuration parameters: + +* Pull-Up/Pull-Down configuration which will be reflected in **PUPD_m** registers + + * **"bias-pull-down"** - Pull-down is selected; + * **"bias-pull-up"** - Pull-up is selected; + * **"bias-pull-pin-default"** - Pull-Up/Pull-Down configuration will be left unchanged; + * if **none** of the above is specified then Neither pull-up nor pull-down is set (disabled). + +* Driving Ability configuration which will be reflected in **IOLH_m** registers + + * **"drive-strength-microamp"** - the drive Ability of pin. + This property should use values defined by PINCTRL_RZG3S_PIN_IOLH_xx helper macro in pinctrl-r9a08g045.h + depending on pin group and selected power supply. + +* Digital Noise Filter configuration which will be reflected in **FILONOFF_m, FILNUM_m and FILCLKSEL_m** registers + + * **"input-debounce"** - the Digital Noise Filter configuration of the pins. + This property should be defined using INCTRL_RZG3S_FILTER_SET() helper macro in pinctrl-r9a08g045.h to specify + values for FILNUM_m and FILCLKSEL_m registers and enable Digital Noise Filter. + +Special Purpose pins configuration +`````````````````````````````````` + +The Special Purpose pins has statically assigned function, but supports additional parameters configuration. +The RZ G3S PINCTRL driver allows to configure Special Purpose pins by using **pins** DT nodes (the nodes with **pins** property). +The Special Purpose pins are identified by name. + +Refer to dts/bindings/pinctrl/renesas,rzg3s-pinctrl.yaml and +"General Purpose Input Output Port (GPIO)" section in "Renesas RZ/G3S Group User’s Manual: Hardware" for list of supported pins. +Example of Special Purpose pins configuration: + +.. code-block:: dts + + &pinctrl { + example_pins: example0 { + a-pins { + pins = "AUDIO_CLK1", "TMS_SWDIO"; + input-enable; + /* Additional cfg properties */ + }; + b-pins { + pins = "TMS_SWDIO"; + drive-strength-microamp = ; + /* Additional cfg properties */ + }; + }; + }; + +The additional optional configuration parameters will be applied to every pin specified in **pins** property. +The Special Purpose **pins** nodes supports following additional configuration parameters: + +* Driving Ability configuration which will be reflected in **IOLH_m** registers + + * **"drive-strength-microamp"** - the Drive Ability of pin. + This property should use values defined by PINCTRL_RZG3S_PIN_IOLH_xx helper macro in pinctrl-r9a08g045.h + depending on pin group and selected power supply. + +* Input Enable configuration which will be reflected in **IEN_m** registers + + * **"input-enable"** - Input enabled; + * **"input-disable"** - Input disabled; + * if **none** of the above is specified then Input Enable configuration will be left unchanged. + +* Output enable configuration which will be reflected in **ETH_MODE** registers + + * **"output-enable"** - The Direction of the IO buffer is Output; + * **"input-enable"** - The Direction of the IO buffer is Input; + * if **none** of the above is specified then Output enable will be left unchanged. + +* Digital Noise Filter configuration which will be reflected in **FILONOFF_m, FILNUM_m and FILCLKSEL_m** registers. + It's supported only for the **"NMI"** Special pin + + * **"input-debounce"** - the Digital Noise Filter configuration of the pins. + This property should be defined using INCTRL_RZG3S_FILTER_SET() helper macro in pinctrl-r9a08g045.h to specify + values for FILNUM_m and FILCLKSEL_m registers and enable Digital Noise Filter. + +Group of pins configuration +``````````````````````````` + +The Group of pins supports additional parameters configuration, which will affect all pins in group. +The RZ G3S supports below Group of pins: + +* ETH0 settings reflects in Ether Ch0 Voltage Mode Control Register (ETH0_POC); +* ETH1 settings reflects in Ether Ch0 Voltage Mode Control Register (ETH0_POC); +* SD_CH0 settings reflects in SD Ch0 IO Voltage Mode Control Register (SD_CH0_POC); +* SD_CH1 settings reflects in SD Ch1 IO Voltage Mode Control Register (SD_CH1_POC); +* XSPI settings reflects in XSPI IO Voltage Mode Control Register (XSPI_POC) and + XSPI/OCTA Output Enable Control Register (XSPI/OCTA Hi-Z); +* I3C settings reflects I3C Control Register (I3C_SET) + +The RZ G3S PINCTRL driver allows to configure the Group of pins by using **groups** DT nodes (the nodes with **groups** property). +The Group of pins are identified by name. + +Refer to dts/bindings/pinctrl/renesas,rzg3s-pinctrl.yaml and +"General Purpose Input Output Port (GPIO)" section in "Renesas RZ/G3S Group User’s Manual: Hardware" for list of supported groups. +Example of Group of pins configuration: + +.. code-block:: dts + + &pinctrl { + example_groups: example0 { + a-group { + pins = "XSPI"; + power-source = <1800>; + }; + b-group { + pins = "I3C"; + power-source = <1200>; + low-power-enable; + }; + }; + }; + +The Group of pins **groups** nodes supports following configuration parameters depending on group: + +* ETH0, ETH1, SD_CH0, SD_CH1, XSPI, I3C + + * **"power-source"** - sets the IO voltage mode for the corresponding group of pins in x_POC registers. + +* XSPI + + * **"bias-high-impedance"** - Control to Hi-Z (output disable) in XSPI/OCTA Hi-Z register; + * **"bias-disable"** - Unlock Hi-Z in XSPI/OCTA Hi-Z register. + +* I3C + + * **"low-power-enable"** - Standby mode in I3C_SET register; + * **"low-power-disable"** - Normal mode in I3C_SET register. + + +* Output enable configuration which will be reflected in **ETH_MODE** registers + + * **"output-enable"** - The Direction of the IO buffer is Output; + * **"input-enable"** - The Direction of the IO buffer is Input; + * if **none** of the above is specified then Output enable will be left unchanged. + +PINCTRL consumer interface +`````````````````````````` + +The consumer device can use standard **pinctrl-X** (and **pinctrl-names**) DT properties to specify +required Pins configuration in DT, and then use Zephyr :ref:`pinctrl_api` to apply it. + +.. code-block:: dts + + &scif1 { + current-speed = <115200>; + pinctrl-0 = <&scif1_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + &canfd { + pinctrl-0 = <&can0_pins &can1_pins>; + pinctrl-names = "default"; + }; + +Refer to Zephyr :ref:`pinctrl-guide` for more information. + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/pwm/GPT.rst b/boards/arm/rz_g3s/doc/pwm/GPT.rst new file mode 100644 index 00000000000000..ec7c5ed56e362c --- /dev/null +++ b/boards/arm/rz_g3s/doc/pwm/GPT.rst @@ -0,0 +1,290 @@ +General PWM Timer (GPT) +======================= + +GPT overview +------------ + +The Renesas RZ G3S Soc has general purpose PWM timer (GPT) composed of 8 channels of 32-bit timer (GPT32E) +for Secure and Non-Secure space. + +Refer to "General PWM Timer (GPT)" section in "Renesas RZ/G3S Group User’s Manual: Hardware" + +GPT driver overview +------------------- + +Zephyr RZ/G3S Renesas GPT driver provides Zephyr :ref:`pwm_api` interface implementation. + +The PWM subsystem is **not** enabled by default in ``rz_g3s_defconfig``. To enable Zephyr +PWM functionality below Kconfig options have to be enabled: + +.. code-block:: text + + CONFIG_PWM=y + +Default pwm devices can be set in the alias section: + +.. code-block:: dts + + aliases { + pwm-0 = &gpt32e0; + pwm-1 = &gpt32e3; + }; + +This aliases are setting the default *pwm-0* and *pwm-1* devices that are used by the system. + +The RZ G3S PWM driver code can be found at: + +.. code-block:: text + + drivers/pwm/pwm_rz2am.c + +This driver is compatible with RZ/A2M driver so the implementation is shared. + +Limitations +```````````` +* Only saw-wave mode is supported by now; +* External pins input is not supported; +* Two in pins in the same channel is not supported; +* Capturing both A and B channels is not supported; +* Overflow handling is not implemented. + +GPT testing +----------- + +tests/drivers/pwm/pwm_api +`````````````````````````` +Zephyr RZ/G3S GPT driver can be tested by using **pwm_api** tests application. +Use below command to build GPT test application: + +.. code-block:: bash + + west build -p always -b rz_g3s tests/drivers/pwm/pwm_api + +**pwm_api** test can be found in the Zephyr source code on the following +path: + +.. code-block:: bash + + ./tests/drivers/pwm/pwm_api/ + +This test is part of the Zephyr test collection. The details about the +test work can be found in the comment on top of the test source file: + +.. code-block:: bash + + ./tests/drivers/pwm/pwm_api/src/test_pwm.c + +**NOTE**: Please connect multimeter or similar analyzing tool to PMOD1_6A pin 7 to +see the PWM output. + +Console output: + +.. code-block:: console + + *** Booting Zephyr OS build v2.5.0-rc2-339-gcd6600121b35 *** + Running TESTSUITE pwm_basic + =================================================================== + START - test_pwm_cycle + [PWM]: 0, [period]: 64000, [pulse]: 32000 + [PWM]: 0, [period]: 64000, [pulse]: 64000 + [PWM]: 0, [period]: 64000, [pulse]: 0 + PASS - test_pwm_cycle in 3.011 seconds + =================================================================== + START - test_pwm_nsec + [PWM]: 0, [period]: 2000000, [pulse]: 1000000 + [PWM]: 0, [period]: 2000000, [pulse]: 2000000 + [PWM]: 0, [period]: 2000000, [pulse]: 0 + PASS - test_pwm_nsec in 3.012 seconds + =================================================================== + TESTSUITE pwm_basic succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [pwm_basic]: pass = 2, fail = 0, skip = 0, total = 2 duration = 6.023 seconds + - PASS - [pwm_basic.test_pwm_cycle] duration = 3.011 seconds + - PASS - [pwm_basic.test_pwm_nsec] duration = 3.012 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL + + +tests/drivers/pwm/pwm_loopback +``````````````````````````````` + +Zephyr RZ/G3S GPT driver can be tested by using **pwm_loopback** test application. +Use below command to build PWM **pwm_loopback** test application: + +.. code-block:: bash + + west build -p always -b rz_g3s tests/drivers/pwm/pwm_loopback + +**NOTE** Please connect PMOD1_6A pin 7 (GPT ch0) and PMOD0_2A pin 7(GPT ch3) to perform +**pwm_looback** test. The below image shows the connection schema: + +.. image:: ../img/pwm_loopback.jpg + :height: 250px + :align: center + +Console output: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-336-g84ec9a6d42b4 *** + Running TESTSUITE pwm_loopback + =================================================================== + START - test_capture_busy + E: gpt32e3@50048300: capture started, pls, stop before reconfigutration + E: rza2m_pwm_enable_capture:gpt32e3@50048300: capture has been already started + PASS - test_capture_busy in 0.013 seconds + =================================================================== + START - test_capture_timeout + W: pwm capture timed out + PASS - test_capture_timeout in 1.003 seconds + =================================================================== + START - test_continuous_capture + PASS - test_continuous_capture in 1.157 seconds + =================================================================== + START - test_period_capture + Testing PWM capture @ 15000000/100000000 nsec + Testing PWM capture @ 75000/100000 usec + PASS - test_period_capture in 0.313 seconds + =================================================================== + START - test_period_capture_inverted + Testing PWM capture @ 15000000/100000000 nsec + Testing PWM capture @ 75000/100000 usec + PASS - test_period_capture_inverted in 0.388 seconds + =================================================================== + START - test_pulse_and_period_capture + Testing PWM capture @ 15000000/100000000 nsec + Testing PWM capture @ 75000/100000 usec + PASS - test_pulse_and_period_capture in 0.387 seconds + =================================================================== + START - test_pulse_capture + Testing PWM capture @ 15000000/100000000 nsec + Testing PWM capture @ 75000/100000 usec + PASS - test_pulse_capture in 0.263 seconds + =================================================================== + START - test_pulse_capture_inverted + Testing PWM capture @ 15000000/100000000 nsec + Testing PWM capture @ 75000/100000 usec + PASS - test_pulse_capture_inverted in 0.288 seconds + =================================================================== + TESTSUITE pwm_loopback succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [pwm_loopback]: pass = 8, fail = 0, skip = 0, total = 8 duration = 3.812 seconds + - PASS - [pwm_loopback.test_capture_busy] duration = 0.013 seconds + - PASS - [pwm_loopback.test_capture_timeout] duration = 1.003 seconds + - PASS - [pwm_loopback.test_continuous_capture] duration = 1.157 seconds + - PASS - [pwm_loopback.test_period_capture] duration = 0.313 seconds + - PASS - [pwm_loopback.test_period_capture_inverted] duration = 0.388 seconds + - PASS - [pwm_loopback.test_pulse_and_period_capture] duration = 0.387 seconds + - PASS - [pwm_loopback.test_pulse_capture] duration = 0.263 seconds + - PASS - [pwm_loopback.test_pulse_capture_inverted] duration = 0.288 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL + + +tests/drivers/pwm/pwm_ab +````````````````````````` + +Zephyr RZ/G3S GPT driver can be tested by using **pwm_ab** test application. +This test shows configuration of A and B channels of the PWM device. +It is including the following set of tests: + +* Set/clear pulse on channel A of the PWM device +* Set/clear pulse on channel A and channel B of the PWM device +* Set/clear pulse on channel B of the PWM device +* Set channel A to Always on -> Period : Pulse (1 : 1) -> 3.3V +* Set channel A to Half on -> Period : Pulse (2 : 1) -> 1.65V +* Set channel A to Always off -> Period : Pulse (1 : 0) -> 0V + +Use below command to build PWM **pwm_ab** test application: + +.. code-block:: bash + + west build -p always -b rz_g3s tests/drivers/pwm/pwm_ab + +**NOTE** Please connect logic analyzer or similar analyzing tool to PMOD1_6A pin 7 (GPT ch0 A) and PMOD1_6A pin 8(GPT ch0 B) +to perform **pwm_ab** test. The below image shows the connection schema: + +.. image:: ../img/pwm_ab_schema.jpg + :height: 250px + :align: center + +The below image shows the sample wave form on analyzer after successful test: + +.. image:: ../img/pwm_ab.jpg + :height: 250px + :align: center + +Console output: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-376-g484f3ddf8e85 *** + Running TESTSUITE pwm_ab + =================================================================== + START - test_pwm_a + [PWM]: 0, [period]: 2000000, [pulse]: 1000000 + [PWM]: 0, [period]: 2000000, [pulse]: 0 + [PWM]: 0, [period]: 2000000, [pulse]: 1000000 + [PWM]: 0, [period]: 2000000, [pulse]: 0 + PASS - test_pwm_a in 3.015 seconds + =================================================================== + START - test_pwm_ab + [PWM]: 0, [period]: 2000000, [pulse]: 1000000 + [PWM]: c0000000, [period]: 2000000, [pulse]: 1000000 + [PWM]: 0, [period]: 2000000, [pulse]: 0 + [PWM]: c0000000, [period]: 2000000, [pulse]: 0 + [PWM]: 0, [period]: 2000000, [pulse]: 1000000 + [PWM]: c0000000, [period]: 2000000, [pulse]: 1000000 + [PWM]: 0, [period]: 2000000, [pulse]: 0 + [PWM]: c0000000, [period]: 2000000, [pulse]: 0 + PASS - test_pwm_ab in 3.032 seconds + =================================================================== + START - test_pwm_b + [PWM]: c0000000, [period]: 2000000, [pulse]: 1000000 + [PWM]: c0000000, [period]: 2000000, [pulse]: 0 + [PWM]: c0000000, [period]: 2000000, [pulse]: 1000000 + [PWM]: c0000000, [period]: 2000000, [pulse]: 0 + PASS - test_pwm_b in 3.017 seconds + =================================================================== + START - test_pwm_cycle + [PWM]: 0, [period]: 64000, [pulse]: 32000 + [PWM]: 0, [period]: 64000, [pulse]: 64000 + [PWM]: 0, [period]: 64000, [pulse]: 0 + PASS - test_pwm_cycle in 3.011 seconds + =================================================================== + START - test_pwm_nsec + [PWM]: 0, [period]: 2000000, [pulse]: 1000000 + [PWM]: 0, [period]: 2000000, [pulse]: 2000000 + [PWM]: 0, [period]: 2000000, [pulse]: 0 + PASS - test_pwm_nsec in 3.012 seconds + =================================================================== + TESTSUITE pwm_ab succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [pwm_ab]: pass = 5, fail = 0, skip = 0, total = 5 duration = 15.087 seconds + - PASS - [pwm_ab.test_pwm_a] duration = 3.015 seconds + - PASS - [pwm_ab.test_pwm_ab] duration = 3.032 seconds + - PASS - [pwm_ab.test_pwm_b] duration = 3.017 seconds + - PASS - [pwm_ab.test_pwm_cycle] duration = 3.011 seconds + - PASS - [pwm_ab.test_pwm_nsec] duration = 3.012 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL + + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/pwm/poeg.rst b/boards/arm/rz_g3s/doc/pwm/poeg.rst new file mode 100644 index 00000000000000..6667bd42767238 --- /dev/null +++ b/boards/arm/rz_g3s/doc/pwm/poeg.rst @@ -0,0 +1,332 @@ +Port Output Enable for GPT (POEG) +================================= + +POEG overview +------------- + +The output pins of the general PWM timer (GPT) can be disabled by using the port output enabling function for the +GPT (POEG). Specifically, either of the following ways can be used. + +* Input level detection of the GTETRGA to GTETRGD pins +* Output-disable request from the GPT +* Register settings + +The GTETRGA to GTETRGD pins can also be used as GPT external trigger input pins. + +POEG driver overview +-------------------- + +Zephyr RZ/G3S Renesas POEG driver provides Zephyr `poeg_api` interface implementation. +And should be used with GPT device which provides :ref:`pwm_api` interface. + +The PWM subsystem is **not** enabled by default in ``rz_g3s_defconfig``. To enable Zephyr +PWM functionality below Kconfig options have to be enabled: + +.. code-block:: text + + CONFIG_PWM=y + +Default pwm devices can be set in the alias section: + +.. code-block:: dts + + aliases { + pwm-0 = &gpt32e0; + pwm-1 = &gpt32e3; + }; + +This aliases are setting the default *pwm-0* and *pwm-1* devices that are used by the system. + +POEG provides 4 channels to be connected to the PWM devices: + +* POEGA +* POEGB +* POEGC +* POEGD + +To assign POEG device to the PWM the following configuration should be done: + +.. code-block:: dts + + aliases { + pwm-0 = &gpt32e3; + }; + + &gpt32e3 { + poeg = "POEGB"; + status = "okay" + renesas,poeg = "POEGB"; + renesas,poeg-device = <&poegb>; + renesas,disable-requests = ;; + }; + + &poegb { + pinctrl-0 = <&poegb_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + + &pinctrl { + /* P18_1 used as GTETRGB */ + /omit-if-no-ref/ poegb_pins: poegb { + poegb-pinmux { + pinmux = ; /* GTETRGB */ + }; + }; + +See the following overlay as the configuration example: + +.. code-block:: text + + test/drivers/pwm/poeg_api/board/rz_g3s.overlay + +This example configures GPT3 as PWM-0 device and assigns `POEGB` device to control +channel. Also configures pin P18_1 to work as `GTETRGB` control channel. + +The RZ G3S POEG driver code can be found at: + +.. code-block:: text + + drivers/pwm/poeg_rzg3.c + + +Limitations +```````````` +* Software enable/disable is not supported. + +POEG testing +------------ + +In POEG testing the following Logic Analyzer was used: + +.. image:: ../img/logic_analyzer.jpg + :height: 250px + :align: center + +The device can be found on link_. + +.. _link: https://www.amazon.com/innomaker-Logic-Analyzer/dp/B07D21GG6J?th=1 + +tests/drivers/pwm/poeg_api +``````````````````````````` +Zephyr RZ/G3S POEG driver can be tested by using **poeg_api** tests application. +Use below command to build GPT test application: + +.. code-block:: bash + + west build -p always -b rz_g3s tests/drivers/pwm/poeg_api + +**poeg_api** test can be found in the Zephyr source code on the following +path: + +.. code-block:: bash + + ./tests/drivers/pwm/poeg_api/ + +To perform the test please use Logic Analyzer or Oscilloscope to connect to the +following pins: + +* connect PMOD1_3A pin 7 (GPT ch0) and PMOD0_2A pin 8 +* connect analyzer channel2 to PMOD0_2A pin 8 +* connect analyzer channel1 to PMOD0_2A pin 7 +* connect analyzer GND to PMOD1_6A pin 5 + +.. note:: + Connection schema is different when the test is running on Cortex-M33_FPU core + please connect logic analyzer channel2 to PMOD1_6A pin 7 instead of + PMOD0_2A pin 7. + +The below image shows the connection schema: + +.. image:: ../img/poeg_connection.jpg + :height: 250px + :align: center + +This test is part of the Zephyr test collection. The details about the +test work can be found in the comment on top of the test source file: + +.. code-block:: bash + + ./tests/drivers/pwm/pwm_api/src/test_pwm.c + +Console output: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-401-g84154004cb8c *** + Running TESTSUITE poeg_basic + =================================================================== + START - test_poeg_trigger + Got POEG status 1 + [PWM]: 3, [period]: 2000000, [pulse]: 1000000 + Got POEG status 1 + PASS - test_poeg_trigger in 4.007 seconds + =================================================================== + TESTSUITE poeg_basic succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [poeg_basic]: pass = 1, fail = 0, skip = 0, total = 1 duration = 4.007 seconds + - PASS - [poeg_basic.test_poeg_trigger] duration = 4.007 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL + +After the test run the following signal schema should appear on Logic Analyzer sample: + +.. image:: ../img/poeg_api.jpg + :align: center + +Where Ch2 is GPIO controlled pin and CH0 is PWM output channel. As can be seen - there are 2 interrupts when control pin goes low: + +* when GPIO is configured; +* when Control PIN toggles low then PWM timer stops and then restores after 1s. + +To perform **poeg_api** test from Cortex-M33_FPU core the following command should be executed: + +.. code-block:: bash + + west build -p always -b rz_g3s_fpu tests/drivers/pwm/poeg_api + +**poeg_api** test can be found in the Zephyr source code on the following +path: + +.. code-block:: bash + + ./tests/drivers/pwm/poeg_api/ + +To perform the test please use Logic Analyzer or Oscilloscope to connect to the +following pins: + +* connect PMOD1_3A pin 7 (GPT ch0) and PMOD0_2A pin 8 +* connect analyzer channel2 to PMOD0_2A pin 8 +* connect analyzer channel1 to PMOD1_6A pin 7 +* connect analyzer GND to PMOD1_6A pin 5 + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-414-g37387d0cc89b *** + Running TESTSUITE poeg_basic + =================================================================== + START - test_poeg_trigger + Got POEG status 1 + [PWM]: 0, [period]: 2000000, [pulse]: 1000000 + Got POEG status 1 + PASS - test_poeg_trigger in 4.007 seconds + =================================================================== + TESTSUITE poeg_basic succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [poeg_basic]: pass = 1, fail = 0, skip = 0, total = 1 duration = 4.007 secs + - PASS - [poeg_basic.test_poeg_trigger] duration = 4.007 seconds + + ------ TESTSUITE SUMMARY END ------ + +After the test run the following signal schema should appear on Logic Analyzer sample: + +.. image:: ../img/poeg_api.jpg + :align: center + +tests/drivers/pwm/pwm_ab +````````````````````````` + +Zephyr RZ/G3S POEG driver disable requests can be tested by using **pwm_ab** +test application with snippet. + +This test shows configuration of A and B channels of the PWM device. +It is including the following set of tests: + +* Set/clear pulse on channel A of the PWM device +* Set/clear pulse on channel A and channel B of the PWM device. + Channel B is blocked by POEG. +* Set/clear pulse on channel B of the PWM device. + Channel B non blocked because Channel A is LOW. +* Set channel A to Always on -> Period : Pulse (1 : 1) -> 3.3V +* Set channel A to Half on -> Period : Pulse (2 : 1) -> 1.65V +* Set channel A to Always off -> Period : Pulse (1 : 0) -> 0V + +Use below command to build WDT **pwm_ab** test application: + +.. code-block:: bash + + west build -p always -b rz_g3s -S rz-g3s-poeg-disa-test tests/drivers/pwm/pwm_ab + +**NOTE** Please connect logic analyzer or similar analyzing tool to PMOD1_6A pin 7 (GPT ch0 A) and PMOD1_6A pin 8(GPT ch0 B) +to perform **pwm_ab** test. The below image shows the connection schema: + +.. image:: ../img/pwm_ab_schema.jpg + :height: 250px + :align: center + +The below image shows the sample wave form on analyzer after successful test: + +.. image:: ../img/pwm_ab_poeg.jpg + :height: 250px + :align: center + +Console output: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-376-g484f3ddf8e85 *** + Running TESTSUITE pwm_ab + =================================================================== + START - test_pwm_a + [PWM]: 0, [period]: 2000000, [pulse]: 1000000 + [PWM]: 0, [period]: 2000000, [pulse]: 0 + [PWM]: 0, [period]: 2000000, [pulse]: 1000000 + [PWM]: 0, [period]: 2000000, [pulse]: 0 + PASS - test_pwm_a in 3.015 seconds + =================================================================== + START - test_pwm_ab + [PWM]: 0, [period]: 2000000, [pulse]: 1000000 + [PWM]: c0000000, [period]: 2000000, [pulse]: 1000000 + [PWM]: 0, [period]: 2000000, [pulse]: 0 + [PWM]: c0000000, [period]: 2000000, [pulse]: 0 + [PWM]: 0, [period]: 2000000, [pulse]: 1000000 + [PWM]: c0000000, [period]: 2000000, [pulse]: 1000000 + [PWM]: 0, [period]: 2000000, [pulse]: 0 + [PWM]: c0000000, [period]: 2000000, [pulse]: 0 + PASS - test_pwm_ab in 3.033 seconds + =================================================================== + START - test_pwm_b + [PWM]: c0000000, [period]: 2000000, [pulse]: 1000000 + [PWM]: c0000000, [period]: 2000000, [pulse]: 0 + [PWM]: c0000000, [period]: 2000000, [pulse]: 1000000 + [PWM]: c0000000, [period]: 2000000, [pulse]: 0 + PASS - test_pwm_b in 3.017 seconds + =================================================================== + START - test_pwm_cycle + [PWM]: 0, [period]: 64000, [pulse]: 32000 + [PWM]: 0, [period]: 64000, [pulse]: 64000 + [PWM]: 0, [period]: 64000, [pulse]: 0 + PASS - test_pwm_cycle in 3.011 seconds + =================================================================== + START - test_pwm_nsec + [PWM]: 0, [period]: 2000000, [pulse]: 1000000 + [PWM]: 0, [period]: 2000000, [pulse]: 2000000 + [PWM]: 0, [period]: 2000000, [pulse]: 0 + PASS - test_pwm_nsec in 3.012 seconds + =================================================================== + TESTSUITE pwm_ab succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [pwm_ab]: pass = 5, fail = 0, skip = 0, total = 5 duration = 15.088 seconds + - PASS - [pwm_ab.test_pwm_a] duration = 3.015 seconds + - PASS - [pwm_ab.test_pwm_ab] duration = 3.033 seconds + - PASS - [pwm_ab.test_pwm_b] duration = 3.017 seconds + - PASS - [pwm_ab.test_pwm_cycle] duration = 3.011 seconds + - PASS - [pwm_ab.test_pwm_nsec] duration = 3.012 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/rspi/rspi.rst b/boards/arm/rz_g3s/doc/rspi/rspi.rst new file mode 100644 index 00000000000000..31e9457451c5b7 --- /dev/null +++ b/boards/arm/rz_g3s/doc/rspi/rspi.rst @@ -0,0 +1,114 @@ +Renesas Serial Peripheral Interface (rSPI) +========================================== + +rSPI overview +------------- + +The Renesas RZ G3S Soc includes three independent Renesas serial peripheral interfaces (rSPI). +The rSPI module is capable of full-duplex synchronous serial communication. + +Refer to "Renesas Serial Peripheral Interface" section in "Renesas RZ/G3S Group User’s Manual: Hardware" + +rSPI driver overview +-------------------- + +Zephyr RZ/G3S Renesas Serial Peripheral Interface (rSPI) driver supports: + +• 8/16bit transfers + +Zephyr RZ/G3S Renesas rSPI driver provides Zephyr :ref:`spi_api` System interface implementation. + +The SPI subsystem is **not** enabled by default in ``rz_g3s_defconfig``. To enable Zephyr +SPI functionality and RZ G3S rSPI driver below Kconfig options have to be enabled: + +.. code-block:: text + + CONFIG_SPI=y + /* automatically enabled */ + CONFIG_SPI_RZA2M=y + +The RZ G3S rSPI driver code can be found at: + +.. code-block:: text + + drivers/spi/spi_rza2m.c + +rSPI testing +------------ + +tests/drivers/spi/spi_loopback +`````````````````````````````` + +Zephyr RZ/G3S Renesas Serial Peripheral Interface (rSPI) driver can be tested by +using generic **spi_loopback** test. Use below command to build SPI **spi_loopback** sample application: + +.. code-block:: bash + + west build -b rz_g3s -p always tests/drivers/spi/spi_loopback + +Once **spi_loopback** is loaded it will provide console output showing the test execution process: + +.. code-block:: console + + I: spi@400aa000:"Init done fck:100000000Hz" + *** Booting Zephyr OS build v3.5.0-rc2-364-g2f7499219d0b *** + Running TESTSUITE spi_loopback + =================================================================== + START - test_spi_loopback + I: SPI test on buffers TX/RX 0x20051260/0x20051240, frame size = 8, DMA enabled (without CONFIG_NOCACHE_MEMORY) + I: SPI test slow config + I: Start complete multiple + I: Passed + I: Start complete loop + I: Passed + I: Start null tx + I: Passed + I: Start half start + I: Passed + I: Start half end + I: Passed + I: Start every 4 + I: Passed + I: Start rx bigger than tx + I: Passed + I: Start async call + I: Passed + I: SPI test fast config + I: Start complete multiple + I: Passed + I: Start complete loop + I: Passed + I: Start null tx + I: Passed + I: Start half start + I: Passed + I: Start half end + I: Passed + I: Start every 4 + I: Passed + I: Start rx bigger than tx + I: Passed + I: Start async call + I: Passed + I: Start complete loop + I: Passed + I: Start complete loop + I: Passed + I: All tx/rx passed + PASS - test_spi_loopback in 0.078 seconds + =================================================================== + TESTSUITE spi_loopback succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [spi_loopback]: pass = 1, fail = 0, skip = 0, total = 1 duration = 0.078 seconds + - PASS - [spi_loopback.test_spi_loopback] duration = 0.078 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/uart/uart.rst b/boards/arm/rz_g3s/doc/uart/uart.rst new file mode 100644 index 00000000000000..9d695ad6f51905 --- /dev/null +++ b/boards/arm/rz_g3s/doc/uart/uart.rst @@ -0,0 +1,266 @@ +UART Serial Communications Interface with FIFO (SCIFA) +====================================================== + +UART overview +------------- + +The Renesas RZ G3S Soc has five channels of serial communication interface (SCIFA) +with FIFO that support both asynchronous and clock synchronous serial communication. +The SCIFA has 16-stage FIFO buffers for transmission and reception, +respectively, for each channel to perform efficient high-speed continuous communication. + +Refer to "Serial Communications Interface with FIFO (SCIFA)" section +in "Renesas RZ/G3S Group User’s Manual: Hardware" + +There are 2 UART ports supported from Zephyr on RZ/G3S SMARC Evaluation Board Kit board: + +* SER0 from PMOD1_3A which is currently used to access Console of M33 cores; +* SER1 from SER1_UART which can be use as M33_FPU console. + +.. _ser0_usage: + +SER0 usage +`````````` + +.. figure:: ../img/rzg3s_ser0.jpg + :align: center + :height: 300px + +SER0 can be used with USB/UART adapter which support 3.3V level. +SER0 connector corresponds to SCIF ch1 peripheral on the board. +You can configure that peripheral in device-tree in the following way: + +.. code-block:: dts + + &scif1 { + current-speed = <115200>; + pinctrl-0 = <&scif1_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + +.. _ser1_usage: + +SER1 usage +`````````` +.. image:: ../img/SER1.jpg + :height: 250px + :align: center + +SER1 can be used with USB/UART adapter which support 1.8V level. Connect +appropriate adapter according to the picture. SER1 connector corresponds to +SCIF ch3 peripheral on the board. You can configure that peripheral in +device-tree overlay file in the following way: + +.. code-block:: dts + + &scif3 { + current-speed = <115200>; + pinctrl-0 = <&scif3_pins>; + pinctrl-names = "default"; + status = "okay"; + }; + +UART driver overview +-------------------- + +The Renesas SCIF driver provides Zephyr :ref:`uart_api` System interface implementation. + +The Zephyr SERIAL subsystem and serial console are enabled by default in ``rz_g3s_defconfig``, +which automatically enables RZ G3S SCIF driver if corresponding DT node is enabled. + +.. code-block:: text + + # Enable UART driver + CONFIG_SERIAL=y + # Enable console + CONFIG_CONSOLE=y + CONFIG_UART_CONSOLE=y + /* automatically enabled */ + CONFIG_UART_SCIF=y + +The RZ G3S SCIF driver code can be found at + +.. code-block:: text + + drivers/serial/uart_scif.c + +UART testing +------------ + +tests/drivers/uart/uart_basic_api +````````````````````````````````` + +To build **uart_basic_api** test run command: + +.. code-block:: bash + + west build -b rz_g3s -p always tests/drivers/uart/uart_basic_api + +The **uart_basic_api** test will produce below console output when executed: + +.. note:: + + During test run when the following message appear on screen: + Please send characters to serial console + please input some characters to the console to continue test. + +.. code-block:: console + + *** Booting Zephyr OS build zephyr-v3.3.0-10465-gb8ad06c6248d *** + Running TESTSUITE uart_basic_api + =================================================================== + START - test_uart_config_get + This is a configure_g PASS - test_uart_config_get in 0.003 seconds + =================================================================== + START - test_uart_co PASS - test_uart_configure in 0.001 seconds + =================================================================== + START - test_uart_fifo_fill + This is a FIFO test. + PASS - test_uart_fifo_fill in 0.501 seconds + =================================================================== + START - test_uart_fifo_read + Please send characters to serial console + PASS - test_uart_fifo_read in 4.425 seconds + =================================================================== + START - test_uart_poll_in + Please send characters to serial console + PASS - test_uart_poll_in in 1.853 seconds + =================================================================== + START - test_uart_poll_out + This is a POLL test. + PASS - test_uart_poll_out in 0.002 seconds + =================================================================== + TESTSUITE uart_basic_api succeeded + Running TESTSUITE uart_basic_api_pending + =================================================================== + START - test_uart_pending + Please send characters to serial console + w PASS - test_uart_pending in 0.801 seconds + =================================================================== + TESTSUITE uart_basic_api_pending succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE PASS - 100.00% [uart_basic_api]: pass = 6, fail = 0, skip = 0, total = 6 duration = 6.785 seconds + - PASS - [uart_basic_api.test_uart_config_get] duration = 0.003 seconds + - PASS - [uart_basic_api.test_uart_configure] duration = 0.001 seconds + - PASS - [uart_basic_api.test_uart_fifo_fill] duration = 0.501 seconds + - PASS - [uart_basic_api.test_uart_fifo_read] duration = 4.425 seconds + - PASS - [uart_basic_api.test_uart_poll_in] duration = 1.853 seconds + - PASS - [uart_baesic_api.test_uart_poll_out] duration = 0.002 seconds + + SUITE PASS - 100.00% [uart_basic_api_pending]: pass = 1, fail = 0, skip = 0, total = 1 duration = 0.801 s + - PASS - [uart_basic_api_pending.test_uart_pending] duration = 0.801 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL + +tests/drivers/uart/uart_async_api +````````````````````````````````` +Async api uses DMA for communication. This test is using SCIF loopback test mode to run the **uart_async_api** test. +To build **uart_async_api** test run command: + +.. code-block:: bash + + west build -b rz_g3s -p always tests/drivers/uart/uart_async_api + +The **uart_async_api** test will produce below console output when executed: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-372-ge216e1e5896c *** + Running TESTSUITE uart_async_chain_read + =================================================================== + START - test_chained_read + SKIP - test_chained_read in 0.002 seconds + =================================================================== + TESTSUITE uart_async_chain_read succeeded + Running TESTSUITE uart_async_chain_write + =================================================================== + START - test_chained_write + PASS - test_chained_write in 0.004 seconds + =================================================================== + TESTSUITE uart_async_chain_write succeeded + Running TESTSUITE uart_async_double_buf + =================================================================== + START - test_double_buffer + SKIP - test_double_buffer in 0.002 seconds + =================================================================== + TESTSUITE uart_async_double_buf succeeded + Running TESTSUITE uart_async_long_buf + =================================================================== + START - test_long_buffers + SKIP - test_long_buffers in 0.002 seconds + =================================================================== + TESTSUITE uart_async_long_buf succeeded + Running TESTSUITE uart_async_multi_rx + =================================================================== + START - test_multiple_rx_enable + SKIP - test_multiple_rx_enable in 0.002 seconds + =================================================================== + TESTSUITE uart_async_multi_rx succeeded + Running TESTSUITE uart_async_read_abort + =================================================================== + START - test_read_abort + PASS - test_read_abort in 1.121 seconds + =================================================================== + TESTSUITE uart_async_read_abort succeeded + Running TESTSUITE uart_async_single_read + =================================================================== + START - test_single_read + PASS - test_single_read in 0.354 seconds + =================================================================== + TESTSUITE uart_async_single_read succeeded + Running TESTSUITE uart_async_timeout + =================================================================== + START - test_forever_timeout + PASS - test_forever_timeout in 3.003 seconds + =================================================================== + TESTSUITE uart_async_timeout succeeded + Running TESTSUITE uart_async_write_abort + =================================================================== + START - test_write_abort + SKIP - test_write_abort in 0.002 seconds + =================================================================== + TESTSUITE uart_async_write_abort succeeded + + ------ TESTSUITE SUMMARY START ------ + + SUITE SKIP - 0.00% [uart_async_chain_read]: pass = 0, fail = 0, skip = 1, total = 1 duration = 0.002 ss + - SKIP - [uart_async_chain_read.test_chained_read] duration = 0.002 seconds + + SUITE PASS - 100.00% [uart_async_chain_write]: pass = 1, fail = 0, skip = 0, total = 1 duration = 0.004 s + - PASS - [uart_async_chain_write.test_chained_write] duration = 0.004 seconds + + SUITE SKIP - 0.00% [uart_async_double_buf]: pass = 0, fail = 0, skip = 1, total = 1 duration = 0.002 ss + - SKIP - [uart_async_double_buf.test_double_buffer] duration = 0.002 seconds + + SUITE SKIP - 0.00% [uart_async_long_buf]: pass = 0, fail = 0, skip = 1, total = 1 duration = 0.002 secs + - SKIP - [uart_async_long_buf.test_long_buffers] duration = 0.002 seconds + + SUITE SKIP - 0.00% [uart_async_multi_rx]: pass = 0, fail = 0, skip = 1, total = 1 duration = 0.002 secs + - SKIP - [uart_async_multi_rx.test_multiple_rx_enable] duration = 0.002 seconds + + SUITE PASS - 100.00% [uart_async_read_abort]: pass = 1, fail = 0, skip = 0, total = 1 duration = 1.121 ss + - PASS - [uart_async_read_abort.test_read_abort] duration = 1.121 seconds + + SUITE PASS - 100.00% [uart_async_single_read]: pass = 1, fail = 0, skip = 0, total = 1 duration = 0.354 s + - PASS - [uart_async_single_read.test_single_read] duration = 0.354 seconds + + SUITE PASS - 100.00% [uart_async_timeout]: pass = 1, fail = 0, skip = 0, total = 1 duration = 3.003 secos + - PASS - [uart_async_timeout.test_forever_timeout] duration = 3.003 seconds + + SUITE SKIP - 0.00% [uart_async_write_abort]: pass = 0, fail = 0, skip = 1, total = 1 duration = 0.002 s + - SKIP - [uart_async_write_abort.test_write_abort] duration = 0.002 seconds + + ------ TESTSUITE SUMMARY END ------ + + =================================================================== + PROJECT EXECUTION SUCCESSFUL + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/doc/wdt/wdt.rst b/boards/arm/rz_g3s/doc/wdt/wdt.rst new file mode 100644 index 00000000000000..fad2b845d8eb17 --- /dev/null +++ b/boards/arm/rz_g3s/doc/wdt/wdt.rst @@ -0,0 +1,138 @@ +Watchdog Timer (WDT) +==================== + +WDT overview +------------ + +The Renesas RZ G3S Soc has 3 channels of watchdog timer and generates a reset request signal when the counter value is +not rewritten and overflows due to system runaway. + +* WDT CH0 - WDT to check the operation of Cortex-A55-CPU +* WDT CH1 - WDT to check the operation of Cortex-M33 CPU +* WDT CH2 - WDT to check the operation of Cortex-M33_FPU CPU + +Each WDT channel can reset only specific CPU Core or cause System (SoC) reset. + +Refer to "Watchdog Timer (WDT)" section in "Renesas RZ/G3S Group User’s Manual: Hardware" + +WDT driver overview +------------------- + +Zephyr RZ/G3S Renesas WDT driver provides Zephyr :ref:`watchdog_api` System interface implementation. +Zephyr RZ/G3S Renesas WDT driver supports following Watchdog behavior flags: + +* Reset: none - WDT_FLAG_RESET_NONE; +* Reset: CPU core - WDT_FLAG_RESET_CPU_CORE; +* Reset: SoC - WDT_FLAG_RESET_SOC. + +The WATCHDOG subsystem is **not** enabled by default in ``rz_g3s_defconfig``. To enable Zephyr +WDT functionality and RZ G3S WDT driver below Kconfig options have to be enabled: + +.. code-block:: text + + CONFIG_WATCHDOG=y + /* automatically enabled */ + CONFIG_WDT_RZG=y + +The RZ G3S WDT driver code can be found at: + +.. code-block:: text + + drivers/watchdog/wdt_rzg.c + +WDT testing +----------- + +samples/drivers/watchdog +```````````````````````` + +Zephyr RZ/G3S WDT driver can be tested by using **samples/drivers/watchdog** sample application. +Use below command to build WDT **samples/drivers/watchdog** sample application: + +.. code-block:: bash + + west build -b rz_g3s -p always samples/drivers/watchdog + +The details about the **samples/drivers/watchdog** test can be found in the following link: +`Zephyr Project Watchdog Sample +`_ + +The **samples/drivers/watchdog** sample application will produce below console output when executed: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-231-g585ed1539f97 *** + Watchdog sample application + Attempting to test pre-reset callback + [00:00:00.010,000] wdt_rzg: wdt_rzg_install_timeout: watchdog@42800400: configuring reset SOC mode + Feeding watchdog 5 times + Feeding watchdog... + Feeding watchdog... + Feeding watchdog... + Feeding watchdog... + Feeding watchdog... + Waiting for reset... + Handled things..ready to reset + +After this, the SoC should reset. + +tests/drivers/watchdog/wdt_basic_api +```````````````````````````````````` + +.. note:: + + This test is not working from JLink debugger (west debug) and has to be run by flashing on xSPI/eMMC. + This is because test code stores some data in the memory and expects it no to be corrupted after reset. + In case of running WDT test from JLink debugger system will be rebooted by JLink which causes Cortex-A55 + to start and TF-A to reinitialize memory which leads to test data corruption. + +Zephyr RZ/G3S WDT driver can be tested by using **wdt_basic_api** test application. +Use below command to build WDT **wdt_basic_api** test application: + +.. code-block:: bash + + west build -b rz_g3s -p always tests/drivers/watchdog/wdt_basic_api + +It runs several tests: running WDT without a callback and waiting for the Cortex-M33 to reset, +running WDT with a callback and waiting for it to fire and Cortex-M33 to reset, +setting an invalid timeout and waiting for the WDT API to generate an error. + +Only Cortex-M33 System Core will be reset during this test. + +The **wdt_basic_api** will application will produce below console output when executed: + +.. code-block:: console + + *** Booting Zephyr OS build v3.5.0-rc2-231-g585ed1539f97 *** + Running TESTSUITE wdt_basic_test_suite + =================================================================== + START - test_wdt + Testcase: test_wdt_no_callback + Waiting to restart MCU + Running TESTSUITE wdt_basic_test_suite + =================================================================== + START - test_wdt + Testcase: test_wdt_no_callback + Testcase passed + Testcase: test_wdt_callback_1 + Waiting to restart MCU + Running TESTSUITE wdt_basic_test_suite + =================================================================== + START - test_wdt + Testcase: test_wdt_callback_1 + Testcase passed + Testcase: test_wdt_bad_window_max + E: watchdog@42800400: invalid timeout val(s) min 0 max 0 + PASS - test_wdt in 0.013 seconds + =================================================================== + TESTSUITE wdt_basic_test_suite succeeded + ------ TESTSUITE SUMMARY START ------ + SUITE PASS - 100.00% [wdt_basic_test_suite]: pass = 1, fail = 0, skip = 0, total = 1 duration = 0.013 ss + - PASS - [wdt_basic_test_suite.test_wdt] duration = 0.013 seconds + ------ TESTSUITE SUMMARY END ------ + =================================================================== + PROJECT EXECUTION SUCCESSFUL + +.. raw:: latex + + \newpage diff --git a/boards/arm/rz_g3s/rz_g3s.dts b/boards/arm/rz_g3s/rz_g3s.dts new file mode 100644 index 00000000000000..f6332a5fb1e2e5 --- /dev/null +++ b/boards/arm/rz_g3s/rz_g3s.dts @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include +#include +#include + +#define INTC_OFFSET 0x41060000 +#define INTC_OFFSET_NODE 41060000 +#define TINT_OFFSET 0x41060020 +#define TINT_OFFSET_NODE 41060020 + +#include +#include "rz_g3s_pinctrl.dtsi" +#include "rz_g3s_canfd.dtsi" +#include "rz_g3s_mhu.dtsi" + +/ { + model = "Renesas RZ G3S board"; + compatible = "renesas,rz-g3s"; + + chosen { + zephyr,sram = &sram_mcpu0; + zephyr,flash = &spi_flash; + zephyr,console = &scif1; + zephyr,shell-uart = &scif1; + }; + + aliases { + sw2 = &sw_1; + sw0 = &sw_2; + sw1 = &sw_3; + }; + + ddr: memory@60000000 { + compatible ="zephyr,memory-region", "mmio-sram"; + reg = <0x60000000 DT_SIZE_M(16)>; + zephyr,memory-region = "DDR"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; + }; + + sram_mcpu0: memory@23000 { + compatible = "mmio-sram"; + reg = <0x23000 DT_SIZE_K(243)>; + }; + + /* + * This node is defined to enable west flash support. + * The base addr and size depends on ATF-F configuration, which is running on Cortex-A55 and + * loading Zephyr app from xSPI flash. + */ + spi_flash: memory@80200000 { + compatible = "mmio-sram"; + reg = <0x80200000 DT_SIZE_K(256)>; + }; + + buttons { + compatible = "gpio-keys"; + + sw_1: button_1 { + gpios = <&port18 0 GPIO_ACTIVE_LOW>; + label = "SW1"; + zephyr,code = ; + }; + + sw_2: button_2 { + gpios = <&port0 1 GPIO_ACTIVE_LOW>; + label = "SW2"; + zephyr,code = ; + }; + + sw_3: button_3 { + gpios = <&port0 3 GPIO_ACTIVE_LOW>; + label = "SW3"; + zephyr,code = ; + }; + }; +}; + +&scif1 { + current-speed = <115200>; + pinctrl-0 = <&scif1_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&extal_clk { + clock-frequency = ; +}; + +&port0 { + status = "okay"; +}; + +&port18 { + status = "okay"; +}; + +&spi0 { + pinctrl-0 = <&spi0_pins>; + pinctrl-names = "default"; +}; + +&wdt1 { + status = "okay"; +}; diff --git a/boards/arm/rz_g3s/rz_g3s.yaml b/boards/arm/rz_g3s/rz_g3s.yaml new file mode 100644 index 00000000000000..4e4ace1ca255a1 --- /dev/null +++ b/boards/arm/rz_g3s/rz_g3s.yaml @@ -0,0 +1,27 @@ +identifier: rz_g3s +name: Cortex M33 for Renesas RZ/G3S +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +supported: + - clock_control + - pinctrl + - uart + - spi + - gpio + - watchdog + - adc + - counter + - i2c + - can + - pwm + - dma + - input +testing: + default: true + ignore_tags: + - net + - bluetooth + - isotp diff --git a/boards/arm/rz_g3s/rz_g3s_canfd.dtsi b/boards/arm/rz_g3s/rz_g3s_canfd.dtsi new file mode 100644 index 00000000000000..66e273ef3644ce --- /dev/null +++ b/boards/arm/rz_g3s/rz_g3s_canfd.dtsi @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * CAN-FD nodes for RZ/G3S SMARC Evaluation Board Kit. + * The on-board CAN transceiver has Standby functions that may be controlled using GPIO. + * Refer to SW_GPIO_CAN_PMOD for configuration. + */ + +/ { + chosen { + zephyr,canbus = &canfd0; + }; +}; + +&canfd { + pinctrl-0 = <&can0_pins &can1_pins>; + pinctrl-names = "default"; +}; + +&canfd0 { + bus-speed-data = <1000000>; + bus-speed = <125000>; + sample-point = <875>; + sample-point-data = <750>; + + can-transceiver { + max-bitrate = <5000000>; + }; +}; + +&canfd1 { + bus-speed-data = <1000000>; + bus-speed = <125000>; + sample-point = <875>; + sample-point-data = <750>; + + can-transceiver { + max-bitrate = <5000000>; + }; +}; diff --git a/boards/arm/rz_g3s/rz_g3s_defconfig b/boards/arm/rz_g3s/rz_g3s_defconfig new file mode 100644 index 00000000000000..9e3690f81e15ce --- /dev/null +++ b/boards/arm/rz_g3s/rz_g3s_defconfig @@ -0,0 +1,39 @@ +CONFIG_SOC_R9A08G045=y +CONFIG_SOC_SERIES_RZ_G=y +CONFIG_BOARD_RZ_G3S=y + +CONFIG_SYS_CLOCK_EXISTS=y + +CONFIG_XIP=n + +CONFIG_ARM_MPU=y + +# Enable clock control +CONFIG_CLOCK_CONTROL=y +CONFIG_RESET=y + +# Enable System Controller driver +CONFIG_SYSCON=y + +CONFIG_MAIN_STACK_SIZE=4096 + +# Enable PINCTRL driver +CONFIG_PINCTRL=y + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable GPIO driver +CONFIG_GPIO=y + +CONFIG_MULTI_LEVEL_INTERRUPTS=y +CONFIG_DYNAMIC_INTERRUPTS=y + +#this is required to enable debug with xSPI boot when Zephyr already booted by TF-A +#and MPU configured which prevent running debug code with exception +CONFIG_INIT_ARCH_HW_AT_BOOT=y +CONFIG_PLATFORM_SPECIFIC_INIT=n diff --git a/boards/arm/rz_g3s/rz_g3s_fpu.dts b/boards/arm/rz_g3s/rz_g3s_fpu.dts new file mode 100644 index 00000000000000..caeea04b11e3a1 --- /dev/null +++ b/boards/arm/rz_g3s/rz_g3s_fpu.dts @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include +#include +#include + +#define INTC_OFFSET 0x41070000 +#define INTC_OFFSET_NODE 41070000 +#define TINT_OFFSET 0x41070020 +#define TINT_OFFSET_NODE 41070020 + +#include +#include "rz_g3s_pinctrl.dtsi" +#include "rz_g3s_canfd.dtsi" +#include "rz_g3s_mhu_fpu.dtsi" + +/ { + model = "Renesas RZ G3S board (FPU)"; + compatible = "renesas,rz-g3s-fpu"; + + chosen { + zephyr,sram = &sram_mcpu1; + zephyr,console = &scif3; + zephyr,shell-uart = &scif3; + }; + + aliases { + sw2 = &sw_1; + sw0 = &sw_2; + sw1 = &sw_3; + }; + + ddr: memory@60000000 { + compatible ="zephyr,memory-region", "mmio-sram"; + reg = <0x61000000 DT_SIZE_M(16)>; + zephyr,memory-region = "DDR"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; + }; + + sram_mcpu1: memory@63000 { + compatible = "mmio-sram"; + reg = <0x63000 DT_SIZE_K(243)>; + }; + + buttons { + compatible = "gpio-keys"; + + sw_1: button_1 { + gpios = <&port18 0 GPIO_ACTIVE_LOW>; + label = "SW1"; + zephyr,code = ; + }; + + sw_2: button_2 { + gpios = <&port0 1 GPIO_ACTIVE_LOW>; + label = "SW2"; + zephyr,code = ; + }; + + sw_3: button_3 { + gpios = <&port0 3 GPIO_ACTIVE_LOW>; + label = "SW3"; + zephyr,code = ; + }; + }; +}; + +&cpu0 { + compatible = "arm,cortex-m33f"; +}; + +&scif3 { + current-speed = <115200>; + pinctrl-0 = <&scif3_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&extal_clk { + clock-frequency = ; +}; + +&port0 { + status = "okay"; +}; + +&port18 { + status = "okay"; +}; + +&wdt2 { + status = "okay"; +}; diff --git a/boards/arm/rz_g3s/rz_g3s_fpu.yaml b/boards/arm/rz_g3s/rz_g3s_fpu.yaml new file mode 100644 index 00000000000000..e25717a804ec6e --- /dev/null +++ b/boards/arm/rz_g3s/rz_g3s_fpu.yaml @@ -0,0 +1,17 @@ +identifier: rz_g3s_fpu +name: Cortex M33 with FPU for Renesas RZ/G3S +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +supported: + - clock_control + - uart + - spi +testing: + default: true + ignore_tags: + - net + - bluetooth + - isotp diff --git a/boards/arm/rz_g3s/rz_g3s_fpu_defconfig b/boards/arm/rz_g3s/rz_g3s_fpu_defconfig new file mode 100644 index 00000000000000..40450cdb6764bd --- /dev/null +++ b/boards/arm/rz_g3s/rz_g3s_fpu_defconfig @@ -0,0 +1,34 @@ +CONFIG_SOC_R9A08G045=y +CONFIG_SOC_SERIES_RZ_G=y +CONFIG_BOARD_RZ_G3S_FPU=y + +CONFIG_SYS_CLOCK_EXISTS=y + +CONFIG_XIP=n + +CONFIG_ARM_MPU=y + +# Enable clock control +CONFIG_CLOCK_CONTROL=y +CONFIG_RESET=y + +# Enable System Controller driver +CONFIG_SYSCON=y + +CONFIG_MAIN_STACK_SIZE=4096 + +# Enable PINCTRL driver +CONFIG_PINCTRL=y + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable GPIO driver +CONFIG_GPIO=y + +CONFIG_MULTI_LEVEL_INTERRUPTS=y +CONFIG_DYNAMIC_INTERRUPTS=y diff --git a/boards/arm/rz_g3s/rz_g3s_mhu.dtsi b/boards/arm/rz_g3s/rz_g3s_mhu.dtsi new file mode 100644 index 00000000000000..70be6c77e6edb5 --- /dev/null +++ b/boards/arm/rz_g3s/rz_g3s_mhu.dtsi @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + soc { + mhu1: mhu@40400020 { + compatible = "renesas,mhu"; + reg = <0x40400020 0x20>; + interrupts = <58 0>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + renesas,mhu-type = <1>; + status = "disabled"; + }; + + mhu3: mhu@40400060 { + compatible = "renesas,mhu"; + reg = <0x40400060 0x20>; + interrupts = <59 0>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + renesas,mhu-type = <1>; + status = "disabled"; + }; + + mhu4: mhu@40400080 { + compatible = "renesas,mhu"; + reg = <0x40400080 0x20>; + interrupts = <60 0>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + renesas,mhu-type = <0>; + status = "disabled"; + }; + + mhu5: mhu@40400100 { + compatible = "renesas,mhu"; + reg = <0x40400100 0x20>; + interrupts = <61 0>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + renesas,mhu-type = <0>; + status = "disabled"; + }; + + mhu1_s: mhu@40401020 { + compatible = "renesas,mhu"; + reg = <0x40401020 0x20>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + interrupts = <62 0>; + renesas,mhu-type = <1>; + status = "disabled"; + }; + + mhu3_s: mhu@40401060 { + compatible = "renesas,mhu"; + reg = <0x40401060 0x20>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + interrupts = <63 0>; + renesas,mhu-type = <1>; + status = "disabled"; + }; + + mhu4_s: mhu@40401080 { + compatible = "renesas,mhu"; + reg = <0x40401080 0x20>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + interrupts = <64 0>; + renesas,mhu-type = <0>; + status = "disabled"; + }; + + mhu5_s: mhu@40401100 { + compatible = "renesas,mhu"; + reg = <0x40401100 0x20>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + interrupts = <65 0>; + renesas,mhu-type = <0>; + status = "disabled"; + }; + }; +}; diff --git a/boards/arm/rz_g3s/rz_g3s_mhu_fpu.dtsi b/boards/arm/rz_g3s/rz_g3s_mhu_fpu.dtsi new file mode 100644 index 00000000000000..a0d3b8fe8a3b18 --- /dev/null +++ b/boards/arm/rz_g3s/rz_g3s_mhu_fpu.dtsi @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + soc { + mhu0_fpu: mhu@40400000 { + compatible = "renesas,mhu"; + reg = <0x40400000 0x20>; + interrupts = <58 0>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + renesas,mhu-type = <1>; + status = "disabled"; + }; + + mhu2_fpu: mhu@40400040 { + compatible = "renesas,mhu"; + reg = <0x40400040 0x20>; + interrupts = <59 0>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + renesas,mhu-type = <0>; + status = "disabled"; + }; + + mhu3_fpu: mhu@40400060 { + compatible = "renesas,mhu"; + reg = <0x40400060 0x20>; + interrupts = <60 0>; //59 + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + renesas,mhu-type = <0>; + status = "disabled"; + }; + + mhu5_fpu: mhu@40400100 { + compatible = "renesas,mhu"; + reg = <0x40400100 0x20>; + interrupts = <61 0>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + renesas,mhu-type = <1>; + status = "disabled"; + }; + + mhu0_fpu_s: mhu@40401000 { + compatible = "renesas,mhu"; + reg = <0x40401000 0x20>; + interrupts = <62 0>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + renesas,mhu-type = <1>; + status = "disabled"; + }; + + mhu2_fpu_s: mhu@40401040 { + compatible = "renesas,mhu"; + reg = <0x40401040 0x20>; + interrupts = <63 0>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + renesas,mhu-type = <0>; + status = "disabled"; + }; + + mhu3_fpu_s: mhu@40401060 { + compatible = "renesas,mhu"; + reg = <0x40401060 0x20>; + interrupts = <64 0>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + renesas,mhu-type = <0>; + status = "disabled"; + }; + + mhu5_fpu_s: mhu@40401100 { + compatible = "renesas,mhu"; + reg = <0x40401100 0x20>; + interrupts = <65 0>; + clocks = <&cpg CPG_MOD R9A08G045_MHU_PCLK>; + resets = <&cpg_rctl R9A08G045_MHU_RESETN>; + renesas,mhu-type = <1>; + status = "disabled"; + }; + }; +}; diff --git a/boards/arm/rz_g3s/rz_g3s_pinctrl.dtsi b/boards/arm/rz_g3s/rz_g3s_pinctrl.dtsi new file mode 100644 index 00000000000000..bcb7209e31b4de --- /dev/null +++ b/boards/arm/rz_g3s/rz_g3s_pinctrl.dtsi @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +&pinctrl { + /omit-if-no-ref/ scif0_pins: scif0 { + scif0-pinmux { + pinmux = , /* TXD */ + ; /* RXD */ + }; + }; + + /omit-if-no-ref/ scif1_pins: scif1 { + scif1-pinmux { + pinmux = , /* TXD */ + ; /* RXD */ + }; + }; + + /omit-if-no-ref/ scif3_pins: scif3 { + scif3-pinmux { + pinmux = , /* TXD */ + ; /* RXD */ + }; + }; + + /omit-if-no-ref/ scif5_pins: scif5 { + scif5-pinmux { + pinmux = , /* RXD */ + ; /* TXD */ + }; + }; + + /omit-if-no-ref/ spi0_pins: spi0 { + pinmux = , /* CK */ + , /* MOSI */ + , /* MISO */ + ; /* SSL */ + }; + + /omit-if-no-ref/ can0_pins: can0 { + can0-pinmux { + pinmux = , /* TX */ + ; /* RX */ + }; + }; + + /omit-if-no-ref/ can1_pins: can1 { + can1-pinmux { + pinmux = , /* TX */ + ; /* RX */ + }; + }; +}; diff --git a/drivers/adc/CMakeLists.txt b/drivers/adc/CMakeLists.txt index a22af9a53365d0..8d45dfe3314a5e 100644 --- a/drivers/adc/CMakeLists.txt +++ b/drivers/adc/CMakeLists.txt @@ -46,3 +46,4 @@ zephyr_library_sources_ifdef(CONFIG_ADC_TLA2021 adc_tla2021.c) zephyr_library_sources_ifdef(CONFIG_ADC_NXP_S32_ADC_SAR adc_nxp_s32_adc_sar.c) zephyr_library_sources_ifdef(CONFIG_ADC_MAX1125X adc_max1125x.c) zephyr_library_sources_ifdef(CONFIG_ADC_MAX11102_17 adc_max11102_17.c) +zephyr_library_sources_ifdef(CONFIG_ADC_RZG3S adc_rz_g3s.c) diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index 32cf7601e8df1d..44ef2ad75d9137 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -106,7 +106,7 @@ source "drivers/adc/Kconfig.gecko" source "drivers/adc/Kconfig.ifx_cat1" -source "drivers/adc/Kconfig.smartbond" +source "drivers/adc/Kconfig.renesas" source "drivers/adc/Kconfig.tla2021" diff --git a/drivers/adc/Kconfig.smartbond b/drivers/adc/Kconfig.renesas similarity index 75% rename from drivers/adc/Kconfig.smartbond rename to drivers/adc/Kconfig.renesas index d18148eeee2d69..e3319ec753ca22 100644 --- a/drivers/adc/Kconfig.smartbond +++ b/drivers/adc/Kconfig.renesas @@ -18,3 +18,11 @@ config ADC_SMARTBOND_SDADC select ADC_CONFIGURABLE_INPUTS help Enable support for ADC driver for Renesas SmartBond(tm) MCU series. + +config ADC_RZG3S + bool "Renesas RZ/G3S ADC Interface" + default y + depends on SOC_R9A08G045 + depends on DT_HAS_RENESAS_RZG3S_ADC_ENABLED + help + Enables support for ADC driver for Renesas RZ/A2M series SoC. diff --git a/drivers/adc/adc_rz_g3s.c b/drivers/adc/adc_rz_g3s.c new file mode 100644 index 00000000000000..3d1b3bcd205a5a --- /dev/null +++ b/drivers/adc/adc_rz_g3s.c @@ -0,0 +1,650 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT renesas_rzg3s_adc + +/* + * *************************** INCLUDES ***************************** + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* This define used for adc_context.h */ +#define ADC_CONTEXT_USES_KERNEL_TIMER +#include "adc_context.h" + +/* + * *************************** CONSTANTS ***************************** + */ +/* Registers */ +#define RZG3S_ADM(n) ((n) * 0x4) +#define RZG3S_TSUMODE 0x10 +#define RZG3S_ADINT 0x20 +#define RZG3S_ADSTS 0x24 +#define RZG3S_ADFIL 0x2c +#define RZG3S_ADCR(n) (0x30 + ((n) * 0x4)) + +/* Register bits */ +#define RZG3S_ADM0_ADCE BIT(0) +#define RZG3S_ADM0_ADBSY BIT(1) +#define RZG3S_ADM0_PWDWNB BIT(2) +#define RZG3S_ADM0_SRESB BIT(15) + +#define RZG3S_ADM1_TRG BIT(0) +#define RZG3S_ADM1_MS BIT(2) +#define RZG3S_ADM1_BS BIT(4) +#define RZG3S_ADM1_EGA_MASK GENMASK(13, 12) + +#define RZG3S_ADM2_CHSEL_MASK GENMASK(8, 0) + +#define RZG3S_ADM3_ADIL_MASK GENMASK(31, 24) +#define RZG3S_ADM3_ADCMP_MASK GENMASK(23, 16) +#define RZG3S_ADM3_ADCMP_1D FIELD_PREP(RZG3S_ADM3_ADCMP_MASK, 0x1d) +#define RZG3S_ADM3_ADSMP_MASK GENMASK(7, 0) + +#define RZG3S_TSUMODE_TSUEN BIT(1) + +#define RZG3S_ADINT_INTEN_MASK GENMASK(11, 0) +#define RZG3S_ADINT_CSEEN BIT(16) +#define RZG3S_ADINT_INTS BIT(31) + +#define RZG3S_ADSTS_CSEST BIT(16) +#define RZG3S_ADSTS_INTST_MASK GENMASK(8, 0) + +#define RZG3S_ADIVC_DIVADC_MASK GENMASK(8, 0) +#define RZG3S_ADIVC_DIVADC_4 FIELD_PREP(RZG3S_ADIVC_DIVADC_MASK, 0x4) + +#define RZG3S_ADCR_AD_MASK GENMASK(11, 0) + +/* Other constants */ +#define RZG3S_ADSMP_DEFAULT_SAMPLING 0x7F +#define RZG3S_ADSMP_DEFAULT_SAMPLING_CH8 0xFF + +#define RZG3S_ADC_RESOLUTION 12 +/* 8 inputs ADC_CH0 to ADC_CH7 and one Thermal Sensor Unit (TSU) */ +#define RZG3S_ADC_CHANNELS_NUM 9 + +/* + * **************************** MACROS ******************************* + */ +LOG_MODULE_REGISTER(adc_rzg3s, CONFIG_ADC_LOG_LEVEL); + +/* + * *********************** TYPE DECLARATIONS ************************* + */ + +/** + * @brief RZ/G3S ADC config + * + * This structure contains constant data for given instance of RZ/G3S ADC. + */ +struct adc_rzg3s_config { + /** Must be first */ + DEVICE_MMIO_ROM; + /** pointer to clock device for ADC */ + const struct device *clock_dev; + /** ADC clocks */ + struct renesas_cpg_clk adclk; + struct renesas_cpg_clk pclk; + /* reset controllers */ + struct reset_dt_spec adrstn; + struct reset_dt_spec presetn; + /** function pointer to irq setup */ + void (*irq_configure)(void); +}; + +/** + * @brief RZ/G3S ADC data + * + * This structure contains data structures used by a RZ/G3S ADC. + */ +struct adc_rzg3s_data { + /** Must be first */ + DEVICE_MMIO_RAM; + /** Structure that handle state of ongoing read operation */ + struct adc_context ctx; + /** Pointer to RZ/G3S ADC own device structure */ + const struct device *dev; + /** Pointer to memory where next sample will be written */ + uint16_t *buf; + /** Pointer to where will be data stored in case of repeated sampling */ + uint16_t *repeat_buf; + /** Mask with channels that will be sampled */ + uint32_t channels; +}; + + +/* + * ************************* PRIVATE FUNCTIONS *************************** + */ + +/** + * @brief Function performs write value to RZ/G3S ADC register + * + * @param dev Pointer to RZ/G3S ADC device + * @param offs ADC register offset + * @param value Value to write + * + * @return none + */ +static void adc_rzg3s_write(const struct device *dev, uint32_t offs, uint32_t value) +{ + sys_write32(value, DEVICE_MMIO_GET(dev) + offs); +} + +/** + * @brief Function performs read value from RZ/G3S ADC register + * + * @param dev Pointer to RZ/G3S ADC device + * @param offs ADC register offset + * + * @return ADC register value + */ +static uint32_t adc_rzg3s_read(const struct device *dev, uint32_t offs) +{ + return sys_read32(DEVICE_MMIO_GET(dev) + offs); +} + +/** + * @brief Function for reading ADC conversion result + * + * @param dev Pointer to RZ/G3S ADC device + * @param channel ADC channel to read + * + * @return ADC conversion result value + */ +static inline uint16_t adc_rzg3s_get_result(const struct device *dev, uint8_t channel) +{ + return (uint16_t)adc_rzg3s_read(dev, RZG3S_ADCR(channel)) & RZG3S_ADCR_AD_MASK; +} + +/** + * @brief Function for reading ADC status + * + * @param dev Pointer to RZ/G3S ADC device + * + * @return ADC status + */ +static inline uint32_t adc_rzg3s_get_status(const struct device *dev) +{ + return adc_rzg3s_read(dev, RZG3S_ADSTS); +} + +/** + * @brief Function for clearing ADC status + * + * @param dev Pointer to RZ/G3S ADC device + * @param mask Clearing bits mask + * + * @return none + */ +static inline void adc_rzg3s_clear_status(const struct device *dev, uint32_t mask) +{ + adc_rzg3s_write(dev, RZG3S_ADSTS, mask); +} + +/** + * @brief Function performs ADC software reset + * + * @param dev Pointer to RZ/G3S ADC device + * + * @return 0 on success, negative errno code on failures + */ +static int adc_rzg3s_sw_reset(const struct device *dev) +{ + uint32_t reg; + int timeout = 5; + + reg = adc_rzg3s_read(dev, RZG3S_ADM(0)); + reg |= RZG3S_ADM0_SRESB; + adc_rzg3s_write(dev, RZG3S_ADM(0), reg); + + /* Reset timeout = timeout * 100 us */ + while (!(adc_rzg3s_read(dev, RZG3S_ADM(0)) & RZG3S_ADM0_SRESB)) { + if (!timeout) { + return -EBUSY; + } + timeout--; + k_busy_wait(100); + } + + return 0; +} + +/** + * @brief Function starts/stops ADC conversion + * + * @param dev Pointer to RZ/G3S ADC device + * @param on If true, ADC conversion starts and stops otherwise + * + * @return none + */ +static void adc_rzg3s_start_stop(const struct device *dev, bool start) +{ + int timeout = 5; + uint32_t reg; + + reg = adc_rzg3s_read(dev, RZG3S_ADM(0)); + if (start) { + reg |= RZG3S_ADM0_ADCE; + } else { + reg &= ~RZG3S_ADM0_ADCE; + } + adc_rzg3s_write(dev, RZG3S_ADM(0), reg); + + if (start) { + return; + } + + /* Stop timeout = timeout * 100 us */ + do { + k_busy_wait(100); + reg = adc_rzg3s_read(dev, RZG3S_ADM(0)); + timeout--; + if (!timeout) { + LOG_ERR("ADC stop timed out\n"); + break; + } + } while (((reg & RZG3S_ADM0_ADBSY) || (reg & RZG3S_ADM0_ADCE))); +} + +/** + * @brief Function for changing ADC power mode + * + * @param dev Pointer to RZ/G3S ADC device + * @param on If true, release from power-saving mode, if false - enter PS mode + * + * @return none + */ +static void adc_rzg3s_set_power(const struct device *dev, bool on) +{ + uint32_t reg; + + if (!on) { + /* Before entering power-saving mode, check that A/D conversion stopped */ + reg = adc_rzg3s_read(dev, RZG3S_ADM(0)); + if ((reg & RZG3S_ADM0_ADBSY) || (reg & RZG3S_ADM0_ADCE)) { + adc_rzg3s_start_stop(dev, false); + } + } + + reg = adc_rzg3s_read(dev, RZG3S_ADM(0)); + if (on) { + /* Release from power-saving mode */ + reg |= RZG3S_ADM0_PWDWNB; + } else { + /* Enter power-saving mode */ + reg &= ~RZG3S_ADM0_PWDWNB; + } + adc_rzg3s_write(dev, RZG3S_ADM(0), reg); + /* Stabilization wait time */ + k_busy_wait(2); +} + +/** + * @brief Check if buffer in @p sequence is big enough to hold all ADC samples + * + * @param dev Pointer to RZ/G3S ADC device + * @param sequence Pointer to ADC sequence description + * + * @return 0 on success + * @return -ENOMEM if buffer is not big enough + */ +static int adc_rzg3s_check_buffer_size(const struct device *dev, + const struct adc_sequence *sequence) +{ + uint8_t channels = 0; + size_t needed_size; + uint32_t mask; + + /* Calculate number of channels in sequence */ + for (mask = BIT(RZG3S_ADC_CHANNELS_NUM - 1); mask != 0; mask >>= 1) { + if (mask & sequence->channels) { + channels++; + } + } + + needed_size = channels * sizeof(uint16_t); + if (sequence->options) { + needed_size *= (1 + sequence->options->extra_samplings); + } + + if (sequence->buffer_size < needed_size) { + return -ENOMEM; + } + + return 0; +} + +/** + * @brief Start A/D conversion request + * + * @param dev Pointer to RZ/G3S ADC device + * @param sequence Pointer to ADC sequence description + * + * @return 0 on success + * @return -ENOTSUP if requested resolution or channel is outside of supported range + * @return -ENOMEM if buffer is not big enough (see @ref adc_rpi_check_buffer_size) + * @return other error code returned by adc_context_wait_for_completion + */ +static int adc_rzg3s_start_conversion(const struct device *dev, + const struct adc_sequence *sequence) +{ + struct adc_rzg3s_data *data = dev->data; + int err; + + if (sequence->resolution != RZG3S_ADC_RESOLUTION) { + LOG_ERR("%s: supported only 12-bit resolution", dev->name); + return -ENOTSUP; + } + + if (!sequence->channels || + find_msb_set(sequence->channels) > RZG3S_ADC_CHANNELS_NUM) { + LOG_ERR("unsupported channels in mask: 0x%08x", sequence->channels); + return -ENOTSUP; + } + + err = adc_rzg3s_check_buffer_size(dev, sequence); + if (err) { + LOG_ERR("buffer size too small"); + return err; + } + + data->buf = sequence->buffer; + adc_context_start_read(&data->ctx, sequence); + + return adc_context_wait_for_completion(&data->ctx); +} + +/** + * @brief API function for pre-configure ADC channel + * + * @param dev Pointer to RZ/G3S ADC device + * @param channel_cfg Pointer to single channel configuration + * + * @return 0 on success + * @return -ENOTSUP if requested channel ID or mode is outside of supported range + * @return -EINVAL if acquisition time or gain is not valid + */ +static int adc_rzg3s_channel_setup(const struct device *dev, + const struct adc_channel_cfg *channel_cfg) +{ + if (channel_cfg->channel_id >= RZG3S_ADC_CHANNELS_NUM) { + LOG_ERR("unsupported channel id '%d'", channel_cfg->channel_id); + return -ENOTSUP; + } + + if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) { + LOG_ERR("Acquisition time is not valid"); + return -EINVAL; + } + + if (channel_cfg->differential) { + LOG_ERR("unsupported differential mode"); + return -ENOTSUP; + } + + if (channel_cfg->gain != ADC_GAIN_1) { + LOG_ERR("Gain is not valid"); + return -EINVAL; + } + + return 0; +} + +static int adc_rzg3s_conversion_setup(const struct device *dev, uint32_t chan_mask) +{ + uint32_t reg; + uint8_t last_channel = find_msb_set(chan_mask) - 1; + + if (adc_rzg3s_read(dev, RZG3S_ADM(0)) & RZG3S_ADM0_ADBSY) + return -EBUSY; + + /* + * Setup ADM1 for SW trigger + * TRGEN[21:16] - Unused, set 00 + * EGA[13:12] - Set 00 to indicate hardware trigger is invalid + * BS[4] - Enable 1-buffer mode + * RPS[3] - Select single conversion number + * MS[2] - Enable Scan mode + * TRGIN[1] - Trigger input mode unused + * TRG[0] - Enable software trigger mode + */ + adc_rzg3s_write(dev, RZG3S_ADM(1), 0); + + /* Select analog input channels subjected to conversion. */ + adc_rzg3s_write(dev, RZG3S_ADM(2), RZG3S_ADM2_CHSEL_MASK & chan_mask); + + /* + * Setup AMD3 + * ADIL[31:24] - Should be always set to 0 + * ADCMP[23:16] - Should be always set to 0x1D + * ADSMP[15:0] - Set default sampling period for channels + */ + reg = RZG3S_ADM3_ADCMP_1D; + reg |= ((last_channel == 8) ? RZG3S_ADSMP_DEFAULT_SAMPLING_CH8 : + RZG3S_ADSMP_DEFAULT_SAMPLING); + adc_rzg3s_write(dev, RZG3S_ADM(3), reg); + + /* + * Setup ADINT + * INTS[31] - Select pulse signal + * CSEEN[16] - Enable channel select error interrupt + * INTEN[11:0] - Select channel interrupt for last channel in sequence + */ + + reg = (RZG3S_ADINT_CSEEN | BIT(last_channel)); + adc_rzg3s_write(dev, RZG3S_ADINT, reg); + + return 0; +} + +/** + * @brief API function for performing A/D conversion in asynchronous mode + * + * @param dev Pointer to RZ/G3S ADC device + * @param sequence Pointer to ADC sequence description + * @param async Pointer to conversion complete callback, + * if NULL, conversion will performed in synchronous mode + * + * @return 0 on success, negative errno code on failures + */ +static int adc_rzg3s_conversion_async(const struct device *dev, + const struct adc_sequence *sequence, + struct k_poll_signal *async) +{ + struct adc_rzg3s_data *data = dev->data; + int err; + + adc_context_lock(&data->ctx, async ? true : false, async); + err = adc_rzg3s_start_conversion(dev, sequence); + adc_context_release(&data->ctx, err); + + return err; +} + +/** + * @brief API function for performing A/D conversion in synchronous mode + * + * @param dev Pointer to RZ/G3S ADC device + * @param sequence Pointer to ADC sequence description + * + * @return 0 on success, negative errno code on failures + */ +static int adc_rzg3s_conversion(const struct device *dev, + const struct adc_sequence *sequence) +{ + return adc_rzg3s_conversion_async(dev, sequence, NULL); +} + +/** + * @brief Function called on init for each ADC device. It setups all + * channels to return constant 0 mV and create acquisition thread. + * + * @param dev Pointer to RZ/G3S ADC device + * + * @return 0 on success + */ +static int adc_rzg3s_init(const struct device *dev) +{ + const struct adc_rzg3s_config *config = dev->config; + struct adc_rzg3s_data *data = dev->data; + int ret; + + if (!device_is_ready(config->clock_dev)) { + LOG_ERR("Device %s is not ready\n", dev->name); + return -ENODEV; + } + + ret = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->pclk); + if (ret != 0) { + LOG_ERR("Can't turn on pclk clock for %s\n", dev->name); + return ret; + } + + ret = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->adclk); + if (ret != 0) { + LOG_ERR("Can't turn on adclk clock for %s\n", dev->name); + goto err; + } + + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + + /* HW and software reset */ + (void)reset_line_toggle_dt(&config->adrstn); + (void)reset_line_toggle_dt(&config->presetn); + ret = adc_rzg3s_sw_reset(dev); + if (ret != 0) { + LOG_ERR("Device %s reset timeout\n", dev->name); + goto err; + } + + config->irq_configure(); + + adc_context_unlock_unconditionally(&data->ctx); + + return 0; +err: + /* On error */ + clock_control_off(config->clock_dev, (clock_control_subsys_t)&config->adclk); + clock_control_off(config->clock_dev, (clock_control_subsys_t)&config->pclk); + return ret; +} + +/** + * @brief Interrupt handler + * + * @param dev Pointer to RZ/G3S ADC device + * + * @return none + */ +static void adc_rzg3s_isr(const struct device *dev) +{ + struct adc_rzg3s_data *data = dev->data; + uint32_t status = adc_rzg3s_get_status(dev); + uint8_t first_chan = find_lsb_set(data->channels) - 1; + uint8_t last_chan = find_msb_set(data->channels) - 1; + uint8_t ch; + + /* Abort converting if error detected or no conversion end flag for current channel */ + if ((status & RZG3S_ADSTS_CSEST) || !(status && data->channels)) { + adc_context_complete(&data->ctx, -EIO); + /* Clear status and enter power-saving mode */ + adc_rzg3s_clear_status(dev, status); + adc_rzg3s_set_power(data->dev, false); + return; + } + + /* Get conversion results from all read channels, copy to buffer */ + for (ch = first_chan; ch <= last_chan; ++ch) { + if (data->channels & BIT(ch)) { + *data->buf++ = adc_rzg3s_get_result(dev, ch); + } + } + + adc_rzg3s_clear_status(dev, status); + + /* Enter power-saving mode */ + adc_rzg3s_set_power(data->dev, false); + /* Notify result if all data gathered. */ + adc_context_on_sampling_done(&data->ctx, dev); +} + +/* + * ************************* PUBLIC FUNCTIONS *************************** + */ +void adc_context_start_sampling(struct adc_context *ctx) +{ + struct adc_rzg3s_data *data = CONTAINER_OF(ctx, struct adc_rzg3s_data, ctx); + + data->channels = ctx->sequence.channels; + data->repeat_buf = data->buf; + + adc_rzg3s_set_power(data->dev, true); + + /* Setup channels and start conversion */ + adc_rzg3s_conversion_setup(data->dev, data->channels); + adc_rzg3s_start_stop(data->dev, true); +} + +void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat_sampling) +{ + struct adc_rzg3s_data *data = CONTAINER_OF(ctx, struct adc_rzg3s_data, ctx); + + if (repeat_sampling) { + data->buf = data->repeat_buf; + } +} + +/* + * ************************* DRIVER REGISTER SECTION *************************** + */ +#define ADC_RZG3S_INIT(n) \ + static void adc_rzg3s_irq_configure_func_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + adc_rzg3s_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + static struct adc_driver_api adc_rzg3s_api_##n = { \ + .channel_setup = adc_rzg3s_channel_setup, \ + .read = adc_rzg3s_conversion, \ + .ref_internal = DT_INST_PROP(n, vref_mv), \ + IF_ENABLED(CONFIG_ADC_ASYNC, \ + (.read_async = adc_rzg3s_conversion_async,)) \ + }; \ + static const struct adc_rzg3s_config adc_rzg3s_config_##n = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ + .irq_configure = adc_rzg3s_irq_configure_func_##n, \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .adclk.module = DT_INST_CLOCKS_CELL_BY_NAME(n, adclk, module), \ + .adclk.domain = DT_INST_CLOCKS_CELL_BY_NAME(n, adclk, domain), \ + .pclk.module = DT_INST_CLOCKS_CELL_BY_NAME(n, pclk, module), \ + .pclk.domain = DT_INST_CLOCKS_CELL_BY_NAME(n, pclk, domain), \ + .presetn = RESET_DT_SPEC_INST_GET_BY_IDX(n, 0), \ + .adrstn = RESET_DT_SPEC_INST_GET_BY_IDX(n, 1), \ + }; \ + static struct adc_rzg3s_data adc_rzg3s_data_##n = { \ + ADC_CONTEXT_INIT_TIMER(adc_rzg3s_data_##n, ctx), \ + ADC_CONTEXT_INIT_LOCK(adc_rzg3s_data_##n, ctx), \ + ADC_CONTEXT_INIT_SYNC(adc_rzg3s_data_##n, ctx), \ + .dev = DEVICE_DT_INST_GET(n), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, adc_rzg3s_init, NULL, \ + &adc_rzg3s_data_##n, \ + &adc_rzg3s_config_##n, POST_KERNEL, \ + CONFIG_ADC_INIT_PRIORITY, \ + &adc_rzg3s_api_##n) + +DT_INST_FOREACH_STATUS_OKAY(ADC_RZG3S_INIT); diff --git a/drivers/can/CMakeLists.txt b/drivers/can/CMakeLists.txt index e0420efe7843aa..257fdaf2dc5a5f 100644 --- a/drivers/can/CMakeLists.txt +++ b/drivers/can/CMakeLists.txt @@ -42,5 +42,6 @@ zephyr_library_sources_ifdef(CONFIG_CAN_KVASER_PCI can_kvaser_pci.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE can_handlers.c) zephyr_library_sources_ifdef(CONFIG_CAN_SHELL can_shell.c) zephyr_library_sources_ifdef(CONFIG_CAN_NXP_S32_CANXL can_nxp_s32_canxl.c) +zephyr_library_sources_ifdef(CONFIG_CAN_RZGS_FD can_rzg3s_fd.c) add_subdirectory(transceiver) diff --git a/drivers/can/Kconfig b/drivers/can/Kconfig index 30381b0978069e..72e18faeaaeb6f 100644 --- a/drivers/can/Kconfig +++ b/drivers/can/Kconfig @@ -101,6 +101,7 @@ source "drivers/can/Kconfig.fake" source "drivers/can/Kconfig.nxp_s32" source "drivers/can/Kconfig.tcan4x5x" source "drivers/can/Kconfig.mcp251xfd" +source "drivers/can/Kconfig.rzg3s" source "drivers/can/transceiver/Kconfig" diff --git a/drivers/can/Kconfig.rzg3s b/drivers/can/Kconfig.rzg3s new file mode 100644 index 00000000000000..0ee014a64bae7e --- /dev/null +++ b/drivers/can/Kconfig.rzg3s @@ -0,0 +1,65 @@ +# Renesas RZ G3S CAN-FD configuration options +# +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +config CAN_RZGS_FD + bool "Renesas RZ G3S CAN-FD Driver" + default y + depends on CAN_FD_MODE + depends on DT_HAS_RENESAS_RZG3S_CANFD_ENABLED + help + Enable Renesas RZ G3S CAN-FD Driver. + +if CAN_RZGS_FD + +config CAN_MAX_FILTER + int "Maximum number of concurrent active RX filters" + depends on CAN_RZGS_FD + default 32 + range 1 128 + help + Defines the Maximum number of concurrent active RX filters and the array size of + the callback/msgq pointers. + For RZ G3S Soc the CAN_MAX_FILTER defines number of AFL entries per channel. + All CAN-FD channels will use the same number of AFL entries. + +config CAN_RZGS_FD_MAX_RX + int "Maximum number of RX FIFO buffers" + depends on CAN_RZGS_FD + default 32 + range 4 64 + help + Maximum number of RX FIFO buffers. + Allowed values: 4, 8, 16, 32, 48, 64, 128. + All CAN-FD channels will use the same number of RX FIFO buffers. + +config CAN_RZGS_FD_MAX_RX_DATA_SIZE + int "Maximum size of RX Payload Data Size" + depends on CAN_RZGS_FD + default 64 + range 8 64 + help + Maximum size of RX packet payload data size used for RZ G3S RX FIFO. + Allowed values: 8, 12, 16, 20, 24, 32, 48, 64 + All CAN-FD channels will use the same maximum size of RX packet payload data. + +config CAN_RZGS_FD_MAX_TX + int "Maximum number of TX message buffers" + depends on CAN_RZGS_FD + default 32 + range 1 32 + help + Maximum number of TX message buffers. + All CAN-FD channels will use the same number of TX message buffers. + + +config CAN_RZG3S_CHN_INIT_PRIORITY + int "Renesas RZ G3S GPIO controller init priority" + default 81 + depends on CAN_RZGS_FD + help + The RZ G3S CAN channel driver initialization priority. The priority should be lower + than CAN_INIT_PRIORITY device. + +endif # CAN_RZGS_FD diff --git a/drivers/can/can_rzg3s_fd.c b/drivers/can/can_rzg3s_fd.c new file mode 100644 index 00000000000000..f01b40a77973b5 --- /dev/null +++ b/drivers/can/can_rzg3s_fd.c @@ -0,0 +1,1791 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_rzg3s_canfd + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +LOG_MODULE_REGISTER(can_rzg3s_fd, CONFIG_CAN_LOG_LEVEL); + +#include "can_rzg3s_fd.h" + +#define LOG_DEV_ERR(dev, format, ...) LOG_ERR("%s:" #format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_WRN(dev, format, ...) LOG_WRN("%s:" #format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_INF(dev, format, ...) LOG_INF("%s:" #format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_DBG(dev, format, ...) LOG_DBG("%s:" #format, (dev)->name, ##__VA_ARGS__) + +BUILD_ASSERT((2 * CAN_RZG3S_RX_MAX_PKTS * (12 + CONFIG_CAN_RZGS_FD_MAX_RX_DATA_SIZE)) <= 9728, + "not enough CAN RAM for requested configuration"); + +enum { + CAN_RZG3S_CHN0, + CAN_RZG3S_CHN1, +}; + +STATS_SECT_START(can_rzg3s_ch) +STATS_SECT_ENTRY32(arbitration_lost) +STATS_SECT_ENTRY32(bus_lock) +STATS_SECT_ENTRY32(error_active_state) +STATS_SECT_ENTRY32(error_warning_state) +STATS_SECT_ENTRY32(error_passive_state) +STATS_SECT_ENTRY32(bus_off_state) +STATS_SECT_ENTRY32(bus_off_recovery) +STATS_SECT_ENTRY32(bus_off_recovery_manual) +STATS_SECT_ENTRY32(tdc_violation) +STATS_SECT_END; + +STATS_NAME_START(can_rzg3s_ch) +STATS_NAME(can_rzg3s_ch, arbitration_lost) +STATS_NAME(can_rzg3s_ch, bus_lock) +STATS_NAME(can_rzg3s_ch, error_active_state) +STATS_NAME(can_rzg3s_ch, error_warning_state) +STATS_NAME(can_rzg3s_ch, error_passive_state) +STATS_NAME(can_rzg3s_ch, bus_off_state) +STATS_NAME(can_rzg3s_ch, bus_off_recovery) +STATS_NAME(can_rzg3s_ch, bus_off_recovery_manual) +STATS_NAME(can_rzg3s_ch, tdc_violation) +STATS_NAME_END(can_rzg3s_ch); + +STATS_SECT_START(can_rzg3s_global) +STATS_SECT_ENTRY32(ecc_error_ch0) +STATS_SECT_ENTRY32(ecc_error_ch1) +STATS_SECT_ENTRY32(canfd_msg_payload_overflow) +STATS_SECT_ENTRY32(rx_msg_lost_rfifo0) +STATS_SECT_ENTRY32(rx_msg_lost_rfifo1) +STATS_SECT_END; + +STATS_NAME_START(can_rzg3s_global) +STATS_NAME(can_rzg3s_global, ecc_error_ch0) +STATS_NAME(can_rzg3s_global, ecc_error_ch1) +STATS_NAME(can_rzg3s_global, canfd_msg_payload_overflow) +STATS_NAME(can_rzg3s_global, rx_msg_lost_rfifo0) +STATS_NAME(can_rzg3s_global, rx_msg_lost_rfifo1) +STATS_NAME_END(can_rzg3s_global); + +struct can_rzg3s_chn_config { + const struct device *ctrl_dev; + void (*irq_config)(void); +#ifdef CONFIG_CAN_STATS + const char *stat_gr_name; +#endif /* CONFIG_CAN_STATS */ + uint32_t irq_ch_err; + uint32_t irq_ch_trx; + uint8_t id; + + uint32_t bitrate; + uint32_t sample_point; + uint32_t bitrate_data; + uint32_t sample_point_data; + + const struct device *phy; + uint32_t max_bitrate; + uint8_t tx_delay_comp_offset; + bool tx_delay_comp_offset_only; +}; + +struct can_rzg3s_chn_rx_afl_entry { + can_rx_callback_t rx_cb; + void *cb_arg; + struct can_filter filter; + bool fdf; +}; + +struct can_rzg3s_chn_tx_entry { + can_tx_callback_t tx_cb; + void *cb_arg; +}; + +struct can_rzg3s_chn_data { + struct can_timing timing; + struct can_timing timing_data; + + struct k_sem tx_sem; + struct k_spinlock tx_tmb_lock; + uint32_t tx_tmb_free; + struct can_rzg3s_chn_tx_entry tx_entries[CAN_RZG3S_TX_MAX_PKTS]; + + ATOMIC_DEFINE(rx_allocs, CAN_RZGS_FD_MAX_FILTER); + struct can_rzg3s_chn_rx_afl_entry rx_afl[CAN_RZGS_FD_MAX_FILTER]; + + struct k_mutex ch_mutex; + enum can_state state; + can_mode_t can_mode; + can_state_change_callback_t state_change_cb; + void *state_change_cb_data; + bool f_started; +#ifdef CONFIG_CAN_STATS + STATS_SECT_DECL(can_rzg3s_ch) stats; +#endif /* CONFIG_CAN_STATS */ +}; + +struct can_rzg3s_config { + DEVICE_MMIO_ROM; + const struct pinctrl_dev_config *pcfg; + const struct device *clk_dev_pclk; + struct renesas_cpg_clk clk_mod_pclk; + const struct device *clk_dev_ram; + struct renesas_cpg_clk clk_mod_ram; + const struct device *clk_dev_ext; + uint32_t clk_ext_rate; + struct reset_dt_spec rstc_n; + struct reset_dt_spec rstp_n; + void (*irq_config)(void); +}; + +struct can_rzg3s_data { + DEVICE_MMIO_RAM; + /* channels using rx fifo map */ + const struct device *rx_fifo_ch_devs[CAN_RZG3S_RX_FIFO_NUM]; + + uint32_t clk_pclk_rate; + uint32_t clk_fcan_rate; +#ifdef CONFIG_CAN_STATS + STATS_SECT_DECL(can_rzg3s_global) stats; +#endif /* CONFIG_CAN_STATS */ +}; + +/* RX fifo configuration */ +static const uint32_t can_rzg3s_rx_fifo_cfg[CAN_RZG3S_RX_FIFO_NUM] = { + [0] = (R_CFD_RFCC_RFIM | R_CFD_RFCC_RFDC(CAN_RZGS_RX_RFDC) | + R_CFD_RFCC_RFPLS(CAN_RZGS_RX_RFPLS) | R_CFD_RFCC_RFIE), + [1] = (R_CFD_RFCC_RFIM | R_CFD_RFCC_RFDC(CAN_RZGS_RX_RFDC) | + R_CFD_RFCC_RFPLS(CAN_RZGS_RX_RFPLS) | R_CFD_RFCC_RFIE), + [2] = 0, + [3] = 0, + [4] = 0, + [5] = 0, + [6] = 0, + [7] = 0, +}; + +static int can_rzg3s_g_get_core_clock(const struct device *ctrl_dev); +static int can_rzg3s_g_rfifo_register(const struct device *dev_ctrl, uint8_t rf_idx, + const struct device *ch_dev); + +static void can_rzg3s_write32(const struct device *dev, uint32_t data, uint32_t reg_ofs) +{ + sys_write32(data, DEVICE_MMIO_GET(dev) + reg_ofs); +} + +static uint32_t can_rzg3s_read32(const struct device *dev, uint32_t reg_ofs) +{ + return sys_read32(DEVICE_MMIO_GET(dev) + reg_ofs); +} + +static void can_rzg3s_modify32(const struct device *dev, uint32_t reg_ofs, uint32_t clear, + uint32_t set) +{ + can_rzg3s_write32(dev, (can_rzg3s_read32(dev, reg_ofs) & ~clear) | set, reg_ofs); +} + +static void can_rzg3s_write8(const struct device *dev, uint8_t data, uint32_t reg_ofs) +{ + sys_write8(data, DEVICE_MMIO_GET(dev) + reg_ofs); +} + +static uint8_t can_rzg3s_read8(const struct device *dev, uint32_t reg_ofs) +{ + return sys_read8(DEVICE_MMIO_GET(dev) + reg_ofs); +} + +static int can_rzg3s_wait_bits1(const struct device *dev, uint32_t reg_ofs, uint32_t bits) +{ + uint32_t reg_val; + int i = 100; + + do { + k_busy_wait(10); + reg_val = can_rzg3s_read32(dev, reg_ofs); + } while ((reg_val & bits) != bits && i--); + + if (!i) { + return -EIO; + } + + return 0; +} + +static int can_rzg3s_wait_bits0(const struct device *dev, uint32_t reg_ofs, uint32_t bits) +{ + uint32_t reg_val; + int i = 100; + + do { + k_busy_wait(10); + reg_val = can_rzg3s_read32(dev, reg_ofs); + } while ((reg_val & bits) && i--); + + if (!i) { + return -EIO; + } + + return 0; +} + +static void can_rzg3s_afl_lock(const struct device *dev) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + + can_rzg3s_modify32(cfg->ctrl_dev, R_CFDG_AFL_ECTR, R_CFDG_AFL_ECTR_AFLDAE, 0); +} + +static void can_rzg3s_afl_unlock(const struct device *dev) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + + can_rzg3s_modify32(cfg->ctrl_dev, R_CFDG_AFL_ECTR, 0, R_CFDG_AFL_ECTR_AFLDAE); +} + +static void can_rzg3s_afl_set_page(const struct device *dev, uint32_t afl_num) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + uint32_t afl_pn; + + afl_pn = afl_num / R_CFDG_AFL_ENTRIES_PER_PAGE; + LOG_DEV_DBG(dev, "AFL: set page:%u", afl_pn); + + can_rzg3s_modify32(cfg->ctrl_dev, R_CFDG_AFL_ECTR, R_CFDG_AFL_ECTR_AFLPN, afl_pn); +} + +static void can_rzg3s_afl_add(const struct device *dev, uint32_t afl_num, + const struct can_filter *filter) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + uint32_t afl_pn_ofs; + uint32_t reg_val; + uint32_t afl_idx; + + afl_idx = afl_num; + if (cfg->id == CAN_RZG3S_CHN1) { + afl_idx += CAN_RZGS_FD_MAX_FILTER; + } + afl_pn_ofs = afl_idx % R_CFDG_AFL_ENTRIES_PER_PAGE; + + LOG_DEV_DBG(dev, "AFLADD: num:%d id:%08x mask:%08x flags:%02x idx:%u pn_ofs:%u", + afl_num, filter->id, filter->mask, filter->flags, afl_idx, afl_pn_ofs); + + can_rzg3s_afl_unlock(dev); + can_rzg3s_afl_set_page(dev, afl_idx); + + if (filter->flags & CAN_FILTER_IDE) { + reg_val = filter->id & CAN_EXT_ID_MASK; + reg_val |= R_CFDG_AFL_ID_GAFLIDE; + } else { + reg_val = filter->id & CAN_STD_ID_MASK; + } + if (filter->flags & CAN_FILTER_RTR) { + reg_val |= R_CFDG_AFL_ID_GAFLRTR; + } + can_rzg3s_write32(cfg->ctrl_dev, reg_val, R_CFDG_AFL_ID(afl_pn_ofs)); + + if (filter->flags & CAN_FILTER_IDE) { + reg_val = filter->mask & CAN_EXT_ID_MASK; + } else { + reg_val = filter->mask & CAN_STD_ID_MASK; + } + reg_val |= R_CFDG_AFL_M_GAFLIDEM; + if ((filter->flags & (CAN_FILTER_RTR | CAN_FILTER_DATA)) == + (CAN_FILTER_RTR | CAN_FILTER_DATA)) { + reg_val &= ~R_CFDG_AFL_M_GAFLRTRM; + } else { + reg_val |= R_CFDG_AFL_M_GAFLRTRM; + } + can_rzg3s_write32(cfg->ctrl_dev, reg_val, R_CFDG_AFL_M(afl_pn_ofs)); + + /* save afl_num as GAFLPTR */ + reg_val = (afl_num << R_CFDG_AFL_LP0_GAFLPTR_OFS) & R_CFDG_AFL_LP0_GAFLPTR_MASK; + can_rzg3s_write32(cfg->ctrl_dev, reg_val, R_CFDG_AFL_LP0(afl_pn_ofs)); + /* set RX fifo for channel */ + can_rzg3s_write32(cfg->ctrl_dev, BIT(cfg->id), R_CFDG_AFL_LP1(afl_pn_ofs)); + + can_rzg3s_afl_lock(dev); +} + +static void can_rzg3s_afl_del(const struct device *dev, uint32_t afl_num) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + uint32_t afl_pn_ofs; + uint32_t afl_idx; + + afl_idx = afl_num; + if (cfg->id == CAN_RZG3S_CHN1) { + afl_idx += CAN_RZGS_FD_MAX_FILTER; + } + afl_pn_ofs = afl_idx % R_CFDG_AFL_ENTRIES_PER_PAGE; + + LOG_DEV_DBG(dev, "AFLDEL: num:%d idx:%u pn_ofs:%u", afl_num, afl_idx, afl_pn_ofs); + + can_rzg3s_afl_unlock(dev); + can_rzg3s_afl_set_page(dev, afl_idx); + + can_rzg3s_write32(cfg->ctrl_dev, 0, R_CFDG_AFL_ID(afl_pn_ofs)); + can_rzg3s_write32(cfg->ctrl_dev, 0, R_CFDG_AFL_M(afl_pn_ofs)); + can_rzg3s_write32(cfg->ctrl_dev, 0, R_CFDG_AFL_LP0(afl_pn_ofs)); + can_rzg3s_write32(cfg->ctrl_dev, 0, R_CFDG_AFL_LP1(afl_pn_ofs)); + + can_rzg3s_afl_lock(dev); +} + +static void can_rzg3s_rfifo_get_data(const struct device *dev_ctrl, struct can_frame *frame, + uint32_t rf_idx) +{ + uint32_t i, lwords; + + lwords = DIV_ROUND_UP(can_dlc_to_bytes(frame->dlc), sizeof(uint32_t)); + + for (i = 0; i < lwords; i++) { + frame->data_32[i] = can_rzg3s_read32(dev_ctrl, R_CFD_RF_RFDF(rf_idx, i)); + } +} + +static void can_rzg3s_rfifo_get_frame(const struct device *dev_ctrl, struct can_frame *frame, + uint32_t rf_idx, uint32_t *afl_num) +{ + uint32_t reg_val; + + reg_val = can_rzg3s_read32(dev_ctrl, R_CFD_RF_RFID(rf_idx)); + + if (reg_val & R_CFD_RF_RFID_RFIDE) { + frame->flags = CAN_FRAME_IDE; + frame->id = reg_val & CAN_EXT_ID_MASK; + } else { + frame->id = reg_val & CAN_STD_ID_MASK; + } + if (reg_val & R_CFD_RF_RFID_RFRTR) { + frame->flags |= CAN_FRAME_RTR; + } + + reg_val = can_rzg3s_read32(dev_ctrl, R_CFD_RF_RFPTR(rf_idx)); + frame->dlc = R_CFD_RF_RFPTR_RFDLC(reg_val); +#ifdef CONFIG_CAN_RX_TIMESTAMP + frame->timestamp = R_CFD_RF_RFPTR_RFTS(reg_val) >> 3; +#endif /* CAN_RX_TIMESTAMP */ + + reg_val = can_rzg3s_read32(dev_ctrl, R_CFD_RF_RFFDSTS(rf_idx)); + if (reg_val & R_CFD_RF_RFFDSTS_RFFDF) { + frame->flags |= CAN_FRAME_FDF; + } + if (reg_val & R_CFD_RF_RFFDSTS_RFBRS) { + frame->flags |= CAN_FRAME_BRS; + } + if (reg_val & R_CFD_RF_RFFDSTS_RFESI) { + frame->flags |= CAN_FRAME_ESI; + } + /* get RX FIFO Buffer Pointer Field RFPTR to get afl num*/ + *afl_num = R_CFD_RF_RFFDSTS_RFPTR(reg_val); + + can_rzg3s_rfifo_get_data(dev_ctrl, frame, rf_idx); + + /* Write 0xff to RFPCTR to increment the CPU-side + * pointer for the RX fifo + */ + can_rzg3s_write32(dev_ctrl, 0xff, R_CFD_RFPCTR(rf_idx)); +} + +static uint32_t can_rzg3s_tmb_to_tmbidx(uint32_t tmb_num, uint32_t ch_id) +{ + uint32_t ch_offset = ch_id ? CAN_RZG3S_TM_CH1_OFFSET : 0; + uint32_t tmb_idx = tmb_num / 16; + + /* up to 32 TMB can be used per channels in below ranges + * CH0: TXMB0 - 15 and TXMB32 - 47 are available + * CH1: TXMB64 - 79 and TXMB96 - 111 are available + * so tmp_num need to be converted from [0..31] to the ranges acceptable by HW. + */ + return tmb_idx ? ch_offset + 32 + (tmb_num % 16) : ch_offset + (tmb_num % 16); +} + +static void can_rzg3s_tmb_put_data(const struct device *dev_ctrl, const struct can_frame *frame, + uint32_t tmb_idx) +{ + uint32_t i, lwords; + + lwords = DIV_ROUND_UP(can_dlc_to_bytes(frame->dlc), sizeof(uint32_t)); + + for (i = 0; i < lwords; i++) { + can_rzg3s_write32(dev_ctrl, frame->data_32[i], R_CFD_TM_DF(tmb_idx, i)); + } +} + +static void can_rzg3s_tmb_put_frame(const struct device *dev_ctrl, const struct can_frame *frame, + uint32_t tmb_idx, bool one_shot) +{ + uint32_t reg_val; + uint8_t reg_val8; + + if (frame->flags & CAN_FRAME_IDE) { + reg_val = frame->id & CAN_EXT_ID_MASK; + reg_val |= R_CFD_TM_ID_TMIDE; + } else { + reg_val = frame->id & CAN_STD_ID_MASK; + } + + if (frame->flags & CAN_FRAME_RTR) { + reg_val |= R_CFD_TM_ID_TMRTR; + } + + can_rzg3s_write32(dev_ctrl, reg_val, R_CFD_TM_ID(tmb_idx)); + + reg_val = R_CFD_TM_PTR_DLC(frame->dlc); + can_rzg3s_write32(dev_ctrl, reg_val, R_CFD_TM_PTR(tmb_idx)); + + reg_val = 0; + if (frame->flags & CAN_FRAME_FDF) { + reg_val |= R_CFD_TM_FDCTR_TMFDF; + } + if (frame->flags & CAN_FRAME_BRS) { + reg_val |= R_CFD_TM_FDCTR_TMBRS; + } + /* ESI bit depends on CFDCnFDCFG.ESIC cfg, but default represent node state. + * if CFDCnFDCFG.ESIC = 1 will used from frame unless err passive state. + * So, just set it here and let hw to decide. + */ + if (frame->flags & CAN_FRAME_ESI) { + reg_val |= R_CFD_TM_FDCTR_TMESI; + } + can_rzg3s_write32(dev_ctrl, reg_val, R_CFD_TM_FDCTR(tmb_idx)); + + can_rzg3s_tmb_put_data(dev_ctrl, frame, tmb_idx); + + /* request tx */ + reg_val8 = R_CFDC_TM_C_TMTR; + if (one_shot) { + reg_val8 |= R_CFDC_TM_C_TMOM; + } + can_rzg3s_write8(dev_ctrl, reg_val8, R_CFDC_TM_C(tmb_idx)); +} + +static void can_rzg3s_tmb_irq_en(const struct device *dev, uint32_t tmb_num) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + + uint32_t regs = tmb_num / 16; + uint32_t bits = tmb_num % 16; + int i; + + for (i = 0; i < regs; i++) { + can_rzg3s_write32(cfg->ctrl_dev, 0xffff, R_CFDC_TM_IEC(cfg->id, i)); + } + + can_rzg3s_write32(cfg->ctrl_dev, BIT_MASK(bits), R_CFDC_TM_IEC(cfg->id, i)); +} + +static int can_rzg3s_tmb_get_free(const struct device *dev) +{ + struct can_rzg3s_chn_data *ctx = dev->data; + k_spinlock_key_t key; + int tmb; + + key = k_spin_lock(&ctx->tx_tmb_lock); + + tmb = find_lsb_set(ctx->tx_tmb_free); + if (tmb) { + tmb--; + ctx->tx_tmb_free &= ~BIT(tmb); + } else { + tmb = -EBUSY; + } + + k_spin_unlock(&ctx->tx_tmb_lock, key); + return tmb; +} + +static void can_rzg3s_tmb_handle_compl_one(const struct device *dev, uint32_t tmb_num) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + struct can_rzg3s_chn_data *ctx = dev->data; + uint8_t tx_result, reg_val8; + can_tx_callback_t tx_cb; + k_spinlock_key_t key; + uint32_t tmb_idx; + void *cb_arg; + int status = 0; + + tmb_idx = can_rzg3s_tmb_to_tmbidx(tmb_num, cfg->id); + + /* get and clear tmb status */ + reg_val8 = can_rzg3s_read8(cfg->ctrl_dev, R_CFDC_TM_STS(tmb_idx)); + tx_result = R_CFDC_TM_STS_TMTRF(reg_val8); + reg_val8 &= ~R_CFDC_TM_STS_TMTRF_MASK; + can_rzg3s_write8(cfg->ctrl_dev, reg_val8, R_CFDC_TM_STS(tmb_idx)); + + if (tx_result == R_CFDC_TM_STS_TMTRF_NORES) { + LOG_DEV_WRN(dev, "TXC: no result. tmb:%u sts:%u", tmb_num, tx_result); + return; + } else if (tx_result == R_CFDC_TM_STS_TMTRF_ABORT) { + if (ctx->state == CAN_STATE_BUS_OFF) { + status = -ENETUNREACH; + } else if (ctx->state == CAN_STATE_STOPPED) { + status = -ENETDOWN; + } else { + status = -EIO; + } + } + + key = k_spin_lock(&ctx->tx_tmb_lock); + + tx_cb = ctx->tx_entries[tmb_num].tx_cb; + cb_arg = ctx->tx_entries[tmb_num].cb_arg; + ctx->tx_entries[tmb_num].tx_cb = NULL; + ctx->tx_entries[tmb_num].cb_arg = NULL; + ctx->tx_tmb_free |= BIT(tmb_num); + + k_spin_unlock(&ctx->tx_tmb_lock, key); + + if (tx_cb) { + LOG_DEV_DBG(dev, "TXC: tmb:%d tmb_idx:%u tx_result:%u", tmb_num, tmb_idx, + tx_result); + k_sem_give(&ctx->tx_sem); + tx_cb(dev, status, cb_arg); + } else { + LOG_DEV_DBG(dev, "TXC: no tx_cb. tmb:%u sts:%u", tmb_num, tx_result); + } +} + +static void can_rzg3s_tmb_handle_compl(const struct device *dev, bool aborted) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + uint32_t reg_ofs; + uint32_t tx_sts; + uint32_t tmb; + + if (aborted) { + reg_ofs = R_CFDC_TM_TASTS(cfg->id, 0); + } else { + reg_ofs = R_CFDC_TM_TCSTS(cfg->id, 0); + } + + tx_sts = can_rzg3s_read32(cfg->ctrl_dev, reg_ofs); + for (tmb = 0; (tmb < 16) && tx_sts; tmb++) { + /* process one tmb */ + if (tx_sts & BIT(tmb)) { + can_rzg3s_tmb_handle_compl_one(dev, tmb); + } + tx_sts = can_rzg3s_read32(cfg->ctrl_dev, reg_ofs); + } + + reg_ofs += 0x4; + tx_sts = can_rzg3s_read32(cfg->ctrl_dev, reg_ofs); + for (tmb = 16; (tmb < CAN_RZG3S_TX_MAX_PKTS) && tx_sts; tmb++) { + /* process one tmb */ + if (tx_sts & BIT(tmb - 16)) { + can_rzg3s_tmb_handle_compl_one(dev, tmb); + } + tx_sts = can_rzg3s_read32(cfg->ctrl_dev, reg_ofs); + } +} + +static void can_rzg3s_tmb_abort_all(const struct device *dev) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + uint32_t reg_ofs; + uint8_t reg_val8; + uint32_t tmb_idx; + uint32_t tx_sts; + uint32_t tmb; + + reg_ofs = R_CFDC_TM_TRSTS(cfg->id, 0); + + tx_sts = can_rzg3s_read32(cfg->ctrl_dev, reg_ofs); + for (tmb = 0; (tmb < 16) && tx_sts; tmb++) { + if (tx_sts & BIT(tmb)) { + tmb_idx = can_rzg3s_tmb_to_tmbidx(tmb, cfg->id); + + reg_val8 = can_rzg3s_read8(cfg->ctrl_dev, R_CFDC_TM_C(tmb_idx)); + reg_val8 |= R_CFDC_TM_C_TMTAR; + can_rzg3s_write8(cfg->ctrl_dev, reg_val8, R_CFDC_TM_C(tmb_idx)); + } + tx_sts = can_rzg3s_read32(cfg->ctrl_dev, reg_ofs); + } + + reg_ofs += 0x4; + tx_sts = can_rzg3s_read32(cfg->ctrl_dev, reg_ofs); + for (tmb = 16; (tmb < CAN_RZG3S_TX_MAX_PKTS) && tx_sts; tmb++) { + if (tx_sts & BIT(tmb - 16)) { + tmb_idx = can_rzg3s_tmb_to_tmbidx(tmb, cfg->id); + + reg_val8 = can_rzg3s_read8(cfg->ctrl_dev, R_CFDC_TM_C(tmb_idx)); + reg_val8 |= R_CFDC_TM_C_TMTAR; + can_rzg3s_write8(cfg->ctrl_dev, reg_val8, R_CFDC_TM_C(tmb_idx)); + } + tx_sts = can_rzg3s_read32(cfg->ctrl_dev, reg_ofs); + } +} + +static int can_rzg3s_chn_set_hw_mode(const struct device *dev, uint8_t chn, uint8_t mode) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + const struct device *dev_ctrl = cfg->ctrl_dev; + int ret = -EINVAL; + uint32_t reg_val; + + reg_val = can_rzg3s_read32(dev_ctrl, R_CFDC_CTR(chn)) & R_CFDC_CTR_CHDC_MASK; + + if (reg_val == mode) { + return 0; + } + + /* no SLEEP support */ + can_rzg3s_modify32(dev_ctrl, R_CFDC_CTR(chn), R_CFDC_CTR_CHDC_MASK, mode); + + if (mode == R_CFDC_CTR_CHDC_OPM) { + ret = can_rzg3s_wait_bits0(dev_ctrl, R_CFDC_STS(chn), R_CFDC_STS_CNOPM); + } else if (mode == R_CFDC_CTR_CHDC_RESET) { + ret = can_rzg3s_wait_bits1(dev_ctrl, R_CFDC_STS(chn), R_CFDC_STS_RSTSTS); + } else if (mode == R_CFDC_CTR_CHDC_HALT) { + ret = can_rzg3s_wait_bits1(dev_ctrl, R_CFDC_STS(chn), R_CFDC_STS_HLTSTS); + } + + return ret; +} + +static void can_rzg3s_chn_set_nrate(const struct device *dev) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + struct can_rzg3s_chn_data *ctx = dev->data; + const struct device *dev_ctrl = cfg->ctrl_dev; + uint32_t reg_ncfg; + + reg_ncfg = (ctx->timing.prescaler - 1) & GENMASK(9, 0); + reg_ncfg |= ((ctx->timing.sjw - 1) << 10) & GENMASK(16, 10); + reg_ncfg |= ((ctx->timing.prop_seg + ctx->timing.phase_seg1 - 1) << 17) & GENMASK(24, 17); + reg_ncfg |= ((ctx->timing.phase_seg2 - 1) << 25) & GENMASK(31, 25); + + can_rzg3s_write32(dev_ctrl, reg_ncfg, R_CFDC_NCFG(cfg->id)); +} + +static void can_rzg3s_chn_set_drate(const struct device *dev) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + struct can_rzg3s_chn_data *ctx = dev->data; + const struct device *dev_ctrl = cfg->ctrl_dev; + uint32_t reg_ncfg; + + reg_ncfg = (ctx->timing_data.prescaler - 1) & GENMASK(7, 0); + reg_ncfg |= ((ctx->timing_data.prop_seg + ctx->timing_data.phase_seg1 - 1) << 8) & + GENMASK(12, 8); + reg_ncfg |= ((ctx->timing_data.phase_seg2 - 1) << 16) & GENMASK(19, 16); + reg_ncfg |= ((ctx->timing_data.sjw - 1) << 24) & GENMASK(27, 24); + + can_rzg3s_write32(dev_ctrl, reg_ncfg, R_CFDC_DCFG(cfg->id)); +} + +static void can_rzg3s_chn_set_tdco(const struct device *dev) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + const struct device *dev_ctrl = cfg->ctrl_dev; + uint32_t reg_val; + + if (!cfg->tx_delay_comp_offset) { + return; + } + reg_val = can_rzg3s_read32(dev_ctrl, R_CFDC_FDCFG(cfg->id)); + reg_val &= ~R_CFDC_FDCFG_TDCO_MSK; + reg_val |= (cfg->tx_delay_comp_offset << R_CFDC_FDCFG_TDCO_OFS) & R_CFDC_FDCFG_TDCO_MSK; + if (cfg->tx_delay_comp_offset_only) { + reg_val |= R_CFDC_FDCFG_TDCO_TDCOC; + } + reg_val |= R_CFDC_FDCFG_TDCO_TDCE; + + can_rzg3s_write32(dev_ctrl, reg_val, R_CFDC_FDCFG(cfg->id)); +} + +static int can_rzg3s_chn_get_core_clock(const struct device *dev, uint32_t *rate) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + + if (rate) { + *rate = can_rzg3s_g_get_core_clock(cfg->ctrl_dev); + } + + return 0; +} + +static int can_rzg3s_get_max_filters(const struct device *dev, bool ide) +{ + ARG_UNUSED(ide); + + return CAN_RZGS_FD_MAX_FILTER; +} + +static int can_rzg3s_chn_get_max_bitrate(const struct device *dev, uint32_t *max_bitrate) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + + *max_bitrate = cfg->max_bitrate; + return 0; +} + +static int can_rzg3s_chn_set_timing(const struct device *dev, const struct can_timing *timing) +{ + struct can_rzg3s_chn_data *ctx = dev->data; + int ret = 0; + + if (!timing) { + return -EINVAL; + } + + k_mutex_lock(&ctx->ch_mutex, K_FOREVER); + if (ctx->f_started) { + ret = -EBUSY; + goto unlock; + + } + + ctx->timing = *timing; + LOG_DEV_DBG(dev, "set nominal presc %d, seg1:%d, seg2:%d sjw:%d", ctx->timing.prescaler, + ctx->timing.phase_seg1, ctx->timing.phase_seg2, ctx->timing.sjw); + +unlock: + k_mutex_unlock(&ctx->ch_mutex); + return ret; +} + +static int can_rzg3s_chn_set_timing_data(const struct device *dev, + const struct can_timing *timing_data) +{ + struct can_rzg3s_chn_data *ctx = dev->data; + int ret = 0; + + if (!timing_data) { + return -EINVAL; + } + + k_mutex_lock(&ctx->ch_mutex, K_FOREVER); + if (ctx->f_started) { + ret = -EBUSY; + goto unlock; + } + + ctx->timing_data = *timing_data; + LOG_DEV_DBG(dev, "set data presc:%d, seg1:%d, seg2:%d sjw:%d", ctx->timing_data.prescaler, + ctx->timing_data.phase_seg1, ctx->timing_data.phase_seg2, ctx->timing_data.sjw); + +unlock: + k_mutex_unlock(&ctx->ch_mutex); + return ret; +} + +static int can_rzg3s_chn_get_capabilities(const struct device *dev, can_mode_t *cap) +{ + if (!cap) { + return -EIO; + } + + *cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_FD | + CAN_MODE_ONE_SHOT; + + return 0; +} + +static int can_rzg3s_chn_set_mode(const struct device *dev, can_mode_t mode) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + struct can_rzg3s_chn_data *ctx = dev->data; + uint32_t ctm = 0; + int ret = 0; + + if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_FD | CAN_MODE_ONE_SHOT))) { + LOG_DEV_ERR(dev, "mode: unsupported mode: 0x%08x", mode); + return -ENOTSUP; + } + + if ((mode & (CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY)) == + (CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY)) { + LOG_DEV_ERR(dev, "mode: both loopback and listen-only modes not supported"); + return -ENOTSUP; + } + + k_mutex_lock(&ctx->ch_mutex, K_FOREVER); + + if (ctx->f_started) { + ret = -EBUSY; + goto unlock; + } + + ret = can_rzg3s_chn_set_hw_mode(dev, cfg->id, R_CFDC_CTR_CHDC_HALT); + if (ret) { + LOG_DEV_ERR(dev, "mode: failed to set halt mode %d", ret); + goto unlock; + } + + ctx->can_mode = mode; + LOG_DEV_DBG(dev, "set mode %d", mode); + + if (!(mode & (CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY))) { + can_rzg3s_modify32(cfg->ctrl_dev, R_CFDC_CTR(cfg->id), + R_CFDC_CTR_CTME | R_CFDC_CTR_CTMS_MASK, 0); + goto unlock; + } + + if (mode & CAN_MODE_LOOPBACK) { + ctm = R_CFDC_CTR_CTME | R_CFDC_CTR_CTMS(R_CFDC_CTR_CTMS_INT_LOOPBACK); + } else if (mode & CAN_MODE_LISTENONLY) { + ctm = R_CFDC_CTR_CTME | R_CFDC_CTR_CTMS(R_CFDC_CTR_CTMS_LISTENONLY); + } + + can_rzg3s_modify32(cfg->ctrl_dev, R_CFDC_CTR(cfg->id), + R_CFDC_CTR_CTME | R_CFDC_CTR_CTMS_MASK, ctm); + +unlock: + k_mutex_unlock(&ctx->ch_mutex); + return ret; +} + +static int can_rzg3s_chn_start(const struct device *dev) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + struct can_rzg3s_chn_data *ctx = dev->data; + int ret = 0; + + k_mutex_lock(&ctx->ch_mutex, K_FOREVER); + + if (ctx->f_started) { + LOG_DEV_INF(dev, "start: already started"); + ret = -EALREADY; + goto unlock; + } + + LOG_DEV_DBG(dev, "start enter"); + + if (cfg->phy) { + ret = can_transceiver_enable(cfg->phy); + if (ret) { + LOG_DEV_ERR(dev, "start: failed to enable can-transceiver %d", ret); + goto unlock; + } + } + + can_rzg3s_chn_set_nrate(dev); + can_rzg3s_chn_set_drate(dev); + can_rzg3s_chn_set_tdco(dev); + + /* restore can (test) mode cfg */ + ret = can_rzg3s_chn_set_mode(dev, ctx->can_mode); + if (ret) { + goto unlock; + } + + can_rzg3s_write32(cfg->ctrl_dev, 0, R_CFDC_ERFL(cfg->id)); + + ret = can_rzg3s_chn_set_hw_mode(dev, cfg->id, R_CFDC_CTR_CHDC_OPM); + if (ret) { + can_rzg3s_chn_set_hw_mode(dev, cfg->id, R_CFDC_CTR_CHDC_RESET); + goto unlock; + } + + irq_enable(cfg->irq_ch_err); + irq_enable(cfg->irq_ch_trx); + /* Enable Rx FIFO */ + can_rzg3s_modify32(cfg->ctrl_dev, R_CFD_RFCC(cfg->id), 0, R_CFD_RFCC_RFE); + + ctx->state = CAN_STATE_ERROR_ACTIVE; + ctx->f_started = true; + STATS_INC(ctx->stats, error_active_state); + +unlock: + k_mutex_unlock(&ctx->ch_mutex); + return ret; +} + +static int can_rzg3s_chn_stop(const struct device *dev) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + struct can_rzg3s_chn_data *ctx = dev->data; + int ret = 0; + + k_mutex_lock(&ctx->ch_mutex, K_FOREVER); + + if (!ctx->f_started) { + LOG_DEV_DBG(dev, "stop: already stopped"); + ret = -EALREADY; + goto unlock; + } + + LOG_DEV_DBG(dev, "stop enter"); + + ret = can_rzg3s_chn_set_hw_mode(dev, cfg->id, R_CFDC_CTR_CHDC_HALT); + if (ret) { + LOG_DEV_ERR(dev, "stop: failed to set halt mode %d", ret); + } + + ctx->state = CAN_STATE_STOPPED; + ctx->f_started = false; + + if (cfg->phy) { + ret = can_transceiver_disable(cfg->phy); + if (ret) { + LOG_DEV_ERR(dev, "stop: failed to disable can-stransceiver %d", ret); + } + } + + /* Disable Rx FIFO */ + can_rzg3s_modify32(cfg->ctrl_dev, R_CFD_RFCC(cfg->id), R_CFD_RFCC_RFE, 0); + + /* clean up TX */ + can_rzg3s_tmb_abort_all(dev); + + k_sleep(K_MSEC(100)); + if (k_sem_count_get(&ctx->tx_sem) != CAN_RZG3S_TX_MAX_PKTS) { + LOG_DEV_ERR(dev, "stop: not all tmb are freed (%d < %d)", + k_sem_count_get(&ctx->tx_sem), CAN_RZG3S_TX_MAX_PKTS); + } + + irq_disable(cfg->irq_ch_err); + irq_disable(cfg->irq_ch_trx); + + ret = can_rzg3s_chn_set_hw_mode(dev, cfg->id, R_CFDC_CTR_CHDC_RESET); + if (ret) { + LOG_DEV_ERR(dev, "stop: failed to set reset mode %d", ret); + } + +unlock: + k_mutex_unlock(&ctx->ch_mutex); + return ret; +} + +static int can_rzg3s_chn_get_state(const struct device *dev, enum can_state *state, + struct can_bus_err_cnt *err_cnt) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + struct can_rzg3s_chn_data *ctx = dev->data; + uint32_t reg_val; + + k_mutex_lock(&ctx->ch_mutex, K_FOREVER); + + if (state) { + *state = ctx->state; + } + + if (err_cnt) { + reg_val = can_rzg3s_read32(cfg->ctrl_dev, R_CFDC_STS(cfg->id)); + err_cnt->tx_err_cnt = R_CFDC_STS_TEC(reg_val); + err_cnt->rx_err_cnt = R_CFDC_STS_REC(reg_val); + } + + k_mutex_unlock(&ctx->ch_mutex); + + return 0; +} + +static int can_rzg3s_chn_send(const struct device *dev, const struct can_frame *frame, + k_timeout_t timeout, can_tx_callback_t callback, void *user_data) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + struct can_rzg3s_chn_data *ctx = dev->data; + int ret = 0; + int tmb; + + __ASSERT(frame, "frame is null"); + + if (ctx->can_mode & CAN_MODE_FD) { + if ((frame->flags & ~(CAN_FRAME_IDE | CAN_FRAME_FDF | CAN_FRAME_BRS | + CAN_FRAME_RTR | CAN_FRAME_ESI))) { + LOG_DEV_ERR(dev, "TX: unsupported framefd flags 0x%02x", frame->flags); + return -ENOTSUP; + } + if (frame->dlc > CANFD_MAX_DLC) { + LOG_DEV_ERR(dev, "TX: framefd dlc %u exceeds maximum (%d)", frame->dlc, + CANFD_MAX_DLC); + return -EINVAL; + } + } else { + if ((frame->flags & ~(CAN_FRAME_IDE | CAN_FRAME_RTR))) { + LOG_DEV_ERR(dev, "TX: unsupported frame flags 0x%02x", frame->flags); + return -ENOTSUP; + } + if (frame->dlc > CAN_MAX_DLC) { + LOG_DEV_ERR(dev, "TX: frame dlc %u exceeds maximum (%d)", frame->dlc, + CAN_MAX_DLC); + return -EINVAL; + } + } + + k_mutex_lock(&ctx->ch_mutex, K_FOREVER); + + if (!ctx->f_started) { + LOG_DEV_DBG(dev, "TX: in stopped state"); + ret = -ENETDOWN; + goto unlock; + } + + if (ctx->state == CAN_STATE_BUS_OFF) { + LOG_DEV_ERR(dev, "TX: in bus-off state"); + ret = -ENETUNREACH; + goto unlock; + } + + if (ctx->can_mode & CAN_MODE_LISTENONLY) { + LOG_DEV_ERR(dev, "TX: in listen-only mode"); + ret = -ENETUNREACH; + goto unlock; + } + + ret = k_sem_take(&ctx->tx_sem, timeout); + if (ret) { + LOG_DEV_DBG(dev, "TX: no more tx buffers"); + ret = -EAGAIN; + goto unlock; + } + + tmb = can_rzg3s_tmb_get_free(dev); + if (ret < 0) { + k_sem_give(&ctx->tx_sem); + ret = tmb; + goto unlock; + } + + LOG_DEV_DBG(dev, "TX: frame id:%08x dlc:%u flags:%02x tmb:%d tmb_idx:%u", frame->id, + frame->dlc, frame->flags, tmb, can_rzg3s_tmb_to_tmbidx(tmb, cfg->id)); + + ctx->tx_entries[tmb].tx_cb = callback; + ctx->tx_entries[tmb].cb_arg = user_data; + can_rzg3s_tmb_put_frame(cfg->ctrl_dev, frame, can_rzg3s_tmb_to_tmbidx(tmb, cfg->id), + !!(ctx->can_mode & CAN_MODE_ONE_SHOT)); + +unlock: + k_mutex_unlock(&ctx->ch_mutex); + return ret; +} + +void can_rzg3s_chn_handle_rx(const struct device *dev, uint32_t rf_idx) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + struct can_rzg3s_chn_data *ctx = dev->data; + uint32_t rf_sts, rf_empty, afl_num; + + rf_sts = can_rzg3s_read32(cfg->ctrl_dev, R_CFD_RFSTS(rf_idx)); + LOG_DEV_DBG(dev, "RX: rfifo stst %08x", rf_sts); + + rf_empty = can_rzg3s_read32(cfg->ctrl_dev, R_CFD_RF_ESTS); + + while (!(rf_empty & BIT(rf_idx))) { + struct can_frame frame = {0}; + + can_rzg3s_rfifo_get_frame(cfg->ctrl_dev, &frame, rf_idx, &afl_num); + + LOG_DEV_DBG(dev, "RX: frame id:%08x dlc:%u flags:%02x afl:%u", frame.id, + frame.dlc, frame.flags, afl_num); +#ifdef CONFIG_CAN_RX_TIMESTAMP + LOG_DEV_DBG(dev, "RX: frame timestamp:%04x", frame.timestamp); +#endif /* CAN_RX_TIMESTAMP */ + + if (atomic_test_bit(ctx->rx_allocs, afl_num)) { + /* FDF filter - no hw support */ + if (!(ctx->rx_afl[afl_num].fdf && !(frame.flags | CAN_FRAME_FDF))) { + ctx->rx_afl[afl_num].rx_cb(dev, &frame, + ctx->rx_afl[afl_num].cb_arg); + } else { + LOG_DEV_ERR(dev, "RX: fdf filter drop afl:%u", afl_num); + } + } else { + LOG_DEV_DBG(dev, "RX: frame for removed afl:%u", afl_num); + } + + rf_empty = can_rzg3s_read32(cfg->ctrl_dev, R_CFD_RF_ESTS); + } + + can_rzg3s_modify32(cfg->ctrl_dev, R_CFD_RFSTS(cfg->id), R_CFD_RFSTS_RFIF, 0); +} + +static int can_rzg3s_chn_add_rx_filter(const struct device *dev, can_rx_callback_t callback, + void *user_data, const struct can_filter *filter) +{ + uint8_t supported = CAN_FILTER_IDE | CAN_FILTER_DATA | CAN_FILTER_RTR | CAN_FILTER_FDF; + struct can_rzg3s_chn_data *ctx = dev->data; + int afl_alloc = -ENOSPC; + int i; + + __ASSERT(filter, "rx_filter can not be null"); + __ASSERT(callback, "rx_callback can not be null"); + + if ((filter->flags & ~(supported)) != 0) { + LOG_DEV_ERR(dev, "AFLADD: unsupported filter flags 0x%02x", filter->flags); + return -ENOTSUP; + } + + k_mutex_lock(&ctx->ch_mutex, K_FOREVER); + + /* Find and allocate RX message buffer */ + for (i = 0; i < CAN_RZGS_FD_MAX_FILTER; i++) { + if (!atomic_test_and_set_bit(ctx->rx_allocs, i)) { + afl_alloc = i; + break; + } + } + + if (afl_alloc == -ENOSPC) { + LOG_DEV_ERR(dev, "AFLADD: no free entries"); + goto unlock; + } + + ctx->rx_afl[afl_alloc].rx_cb = callback; + ctx->rx_afl[afl_alloc].cb_arg = user_data; + ctx->rx_afl[afl_alloc].fdf = !!(filter->flags & CAN_FILTER_FDF); + can_rzg3s_afl_add(dev, afl_alloc, filter); + +unlock: + k_mutex_unlock(&ctx->ch_mutex); + + return afl_alloc; +} + +static void can_rzg3s_chn_remove_rx_filter(const struct device *dev, int filter_id) +{ + struct can_rzg3s_chn_data *ctx = dev->data; + + if (filter_id >= CAN_RZGS_FD_MAX_FILTER) { + LOG_DEV_ERR(dev, "AFLDEL: filter id >= max (%d >= %d)", filter_id, + CAN_RZGS_FD_MAX_FILTER); + return; + } + + k_mutex_lock(&ctx->ch_mutex, K_FOREVER); + + if (atomic_test_and_clear_bit(ctx->rx_allocs, filter_id)) { + ctx->rx_afl[filter_id].rx_cb = NULL; + ctx->rx_afl[filter_id].cb_arg = NULL; + can_rzg3s_afl_del(dev, filter_id); + } else { + LOG_DEV_WRN(dev, "AFLDEL: filter id %d already detached", filter_id); + } + + k_mutex_unlock(&ctx->ch_mutex); +} + +static void can_rzg3s_chn_state_change(const struct device *dev, uint32_t newstate) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + struct can_rzg3s_chn_data *ctx = dev->data; + struct can_bus_err_cnt err_cnt; + uint32_t reg_val; + + if (ctx->state == newstate) { + return; + } + + LOG_DEV_DBG(dev, "can state change new: %u old:%u", newstate, ctx->state); + + ctx->state = newstate; + + if (!ctx->state_change_cb) { + return; + } + + reg_val = can_rzg3s_read32(cfg->ctrl_dev, R_CFDC_STS(cfg->id)); + err_cnt.tx_err_cnt = R_CFDC_STS_TEC(reg_val); + err_cnt.rx_err_cnt = R_CFDC_STS_REC(reg_val); + + ctx->state_change_cb(dev, newstate, err_cnt, ctx->state_change_cb_data); +} + +static void can_rzg3s_chn_set_state_change_callback(const struct device *dev, + can_state_change_callback_t callback, + void *user_data) +{ + struct can_rzg3s_chn_data *ctx = dev->data; + + k_mutex_lock(&ctx->ch_mutex, K_FOREVER); + ctx->state_change_cb = callback; + ctx->state_change_cb_data = user_data; + k_mutex_unlock(&ctx->ch_mutex); +} + +#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY +static int can_rzg3s_chn_recover(const struct device *dev, k_timeout_t timeout) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + struct can_rzg3s_chn_data *ctx = dev->data; + struct can_bus_err_cnt err_cnt; + int64_t start_time; + uint32_t reg_val; + int ret = 0; + + k_mutex_lock(&ctx->ch_mutex, K_FOREVER); + + if (!ctx->f_started) { + ret = -ENETDOWN; + goto unlock; + } + + if (ctx->state != CAN_STATE_BUS_OFF) { + goto unlock; + } + + start_time = k_uptime_ticks(); + + ret = can_rzg3s_chn_set_hw_mode(dev, cfg->id, R_CFDC_CTR_CHDC_OPM); + if (ret) { + LOG_DEV_ERR(dev, "recover: failed to set OPM mode %d", ret); + goto unlock; + } + + if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT)) { + while (ctx->state != CAN_STATE_BUS_OFF) { + if (!K_TIMEOUT_EQ(timeout, K_FOREVER) && + k_uptime_ticks() - start_time >= timeout.ticks) { + ret = -EAGAIN; + LOG_DEV_INF(dev, "recover: timeout"); + goto unlock; + } + } + } + + STATS_INC(ctx->stats, bus_off_recovery_manual); + + reg_val = can_rzg3s_read32(cfg->ctrl_dev, R_CFDC_STS(cfg->id)); + err_cnt.tx_err_cnt = R_CFDC_STS_TEC(reg_val); + err_cnt.rx_err_cnt = R_CFDC_STS_REC(reg_val); + if (err_cnt.tx_err_cnt < 96 && err_cnt.tx_err_cnt < 96) { + STATS_INC(ctx->stats, error_active_state); + can_rzg3s_chn_state_change(dev, CAN_STATE_ERROR_ACTIVE); + } + +unlock: + k_mutex_unlock(&ctx->ch_mutex); + return ret; +} +#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */ + +static void can_rzg3s_isr_trx(const struct device *dev) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + uint8_t tx_gsts; + + tx_gsts = can_rzg3s_read8(cfg->ctrl_dev, R_CFDG_TINTSTS0(cfg->id)); + LOG_DEV_DBG(dev, "ch_trx: %02x", tx_gsts); + + while (tx_gsts) { + if (tx_gsts & R_CFDG_TINTSTS0_TSIF) { + /* handle TX Successful*/ + can_rzg3s_tmb_handle_compl(dev, false); + } + + if (tx_gsts & R_CFDG_TINTSTS0_TAIF) { + /* handle TX Abort */ + can_rzg3s_tmb_handle_compl(dev, true); + } + + tx_gsts = can_rzg3s_read8(cfg->ctrl_dev, R_CFDG_TINTSTS0(cfg->id)); + LOG_DEV_DBG(dev, "ch_trx: 1 %02x", tx_gsts); + } +} + +static void can_rzg3s_isr_err(const struct device *dev) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + struct can_rzg3s_chn_data *ctx = dev->data; + uint32_t erfl, fdsts; + + ARG_UNUSED(ctx); + + erfl = can_rzg3s_read32(cfg->ctrl_dev, R_CFDC_ERFL(cfg->id)); + LOG_DEV_DBG(dev, "ch_err: %08x", erfl); + fdsts = can_rzg3s_read32(cfg->ctrl_dev, R_CFDC_FDSTS(cfg->id)); + + if (erfl & R_CFDC_ERFL_ADERR) { + CAN_STATS_ACK_ERROR_INC(dev); + } + if (erfl & R_CFDC_ERFL_B0ERR) { + CAN_STATS_BIT0_ERROR_INC(dev); + } + if (erfl & R_CFDC_ERFL_B1ERR) { + CAN_STATS_BIT1_ERROR_INC(dev); + } + if (erfl & R_CFDC_ERFL_CERR) { + CAN_STATS_CRC_ERROR_INC(dev); + } + if (erfl & R_CFDC_ERFL_AERR) { + CAN_STATS_ACK_ERROR_INC(dev); + } + if (erfl & R_CFDC_ERFL_FERR) { + CAN_STATS_FORM_ERROR_INC(dev); + } + if (erfl & R_CFDC_ERFL_SERR) { + CAN_STATS_STUFF_ERROR_INC(dev); + } + if (erfl & R_CFDC_ERFL_OVLF) { + CAN_STATS_RX_OVERRUN_INC(dev); + } + + if (erfl & R_CFDC_ERFL_ALF) { + STATS_INC(ctx->stats, arbitration_lost); + LOG_DEV_DBG(dev, "arbitration lost flag"); + } + + if (erfl & R_CFDC_ERFL_BLF) { + STATS_INC(ctx->stats, bus_lock); + LOG_DEV_ERR(dev, "bus lock detected"); + can_rzg3s_chn_state_change(dev, CAN_STATE_BUS_OFF); + } + + if (erfl & R_CFDC_ERFL_BORF) { + STATS_INC(ctx->stats, bus_off_recovery); + STATS_INC(ctx->stats, error_active_state); + can_rzg3s_chn_state_change(dev, CAN_STATE_ERROR_ACTIVE); + } + + if (erfl & R_CFDC_ERFL_EWF) { + STATS_INC(ctx->stats, error_warning_state); + can_rzg3s_chn_state_change(dev, CAN_STATE_ERROR_WARNING); + } + + if (erfl & R_CFDC_ERFL_EPF) { + STATS_INC(ctx->stats, error_passive_state); + can_rzg3s_chn_state_change(dev, CAN_STATE_ERROR_PASSIVE); + } + + if (erfl & R_CFDC_ERFL_BOEF) { + STATS_INC(ctx->stats, bus_off_state); + can_rzg3s_chn_state_change(dev, CAN_STATE_BUS_OFF); + } + + can_rzg3s_write32(cfg->ctrl_dev, ~erfl, R_CFDC_ERFL(cfg->id)); + + if (fdsts & R_CFDC_FDSTS_TDCO_TDCVF) { + STATS_INC(ctx->stats, tdc_violation); + LOG_DEV_DBG(dev, "transceiver delay compensation violation %02x", + (uint32_t)(fdsts & R_CFDC_FDSTS_TDCO_TDCR)); + can_rzg3s_write32(cfg->ctrl_dev, ~R_CFDC_FDSTS_TDCO_TDCVF, R_CFDC_FDSTS(cfg->id)); + } +} + +static const struct can_driver_api can_rzg3s_can_api = { + .get_capabilities = can_rzg3s_chn_get_capabilities, + .start = can_rzg3s_chn_start, + .stop = can_rzg3s_chn_stop, + .set_mode = can_rzg3s_chn_set_mode, + .set_timing = can_rzg3s_chn_set_timing, + .set_timing_data = can_rzg3s_chn_set_timing_data, + .send = can_rzg3s_chn_send, + .add_rx_filter = can_rzg3s_chn_add_rx_filter, + .remove_rx_filter = can_rzg3s_chn_remove_rx_filter, + .get_state = can_rzg3s_chn_get_state, +#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY + .recover = can_rzg3s_chn_recover, +#endif + .set_state_change_callback = can_rzg3s_chn_set_state_change_callback, + .get_core_clock = can_rzg3s_chn_get_core_clock, + .get_max_filters = can_rzg3s_get_max_filters, + .get_max_bitrate = can_rzg3s_chn_get_max_bitrate, + /* + * Note that the values here are the "physical" timing limits, whereas + * the register field limits are physical values minus 1 + */ + .timing_min = {.sjw = 2, .prop_seg = 0, .phase_seg1 = 2, .phase_seg2 = 2, .prescaler = 1}, + .timing_max = {.sjw = 128, + .prop_seg = 0, + .phase_seg1 = 256, + .phase_seg2 = 128, + .prescaler = 1024}, + .timing_data_min = { + .sjw = 1, .prop_seg = 0, .phase_seg1 = 2, .phase_seg2 = 2, .prescaler = 1}, + .timing_data_max = { + .sjw = 16, .prop_seg = 0, .phase_seg1 = 32, .phase_seg2 = 16, .prescaler = 256}, +}; + +static int can_rzg3s_chn_init(const struct device *dev) +{ + const struct can_rzg3s_chn_config *cfg = dev->config; + struct can_rzg3s_chn_data *ctx = dev->data; + uint32_t reg_val; + int ret; + + ret = can_calc_timing(dev, &ctx->timing, cfg->bitrate, cfg->sample_point); + if (ret < 0) { + LOG_DEV_ERR(dev, "can't find nom timing for given param %d", ret); + return ret; + } + if (ret) { + LOG_DEV_INF(dev, "nominal sample-point err : %d", ret); + } + + ret = can_calc_timing_data(dev, &ctx->timing_data, cfg->bitrate_data, + cfg->sample_point_data); + if (ret < 0) { + LOG_DEV_ERR(dev, "can't find data timing for given param %d", ret); + return ret; + } + if (ret) { + LOG_DEV_INF(dev, "data sample-point err : %d", ret); + } + + /* Validate initial timing parameters */ + ret = can_set_timing(dev, &ctx->timing); + if (ret) { + LOG_DEV_ERR(dev, "failed to set nom timing %d", ret); + return ret; + } + /* Validate initial data phase timing parameters */ + ret = can_set_timing_data(dev, &ctx->timing_data); + if (ret) { + LOG_DEV_ERR(dev, "failed to set data phase timing %d", ret); + return ret; + } + + k_sem_init(&ctx->tx_sem, CAN_RZG3S_TX_MAX_PKTS, CAN_RZG3S_TX_MAX_PKTS); + k_mutex_init(&ctx->ch_mutex); + ctx->tx_tmb_free = UINT32_MAX; + + cfg->irq_config(); + + /* clear channels sleep */ + can_rzg3s_modify32(cfg->ctrl_dev, R_CFDC_CTR(cfg->id), R_CFDC_CTR_CSLPR, 0); + + /* Error Display Mode - all */ + can_rzg3s_modify32(cfg->ctrl_dev, R_CFDC_CTR(cfg->id), 0, R_CFDC_CTR_ERRD); + +#ifdef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY + /* Bus-Off Recovery Mode - 00: ISO11898-1 compliant */ + can_rzg3s_modify32(cfg->ctrl_dev, R_CFDC_CTR(cfg->id), R_CFDC_CTR_BOM_MASK, + R_CFDC_CTR_BOM(R_CFDC_CTR_BOM_ISO)); +#else + /* Bus-Off Recovery Mode - 01: Entry to Channel Halt mode automatically at bus-off entry */ + can_rzg3s_modify32(cfg->ctrl_dev, R_CFDC_CTR(cfg->id), R_CFDC_CTR_BOM_MASK, + R_CFDC_CTR_BOM(R_CFDC_CTR_BOM_BENTRY)); +#endif + + /* Channel interrupts setup */ + reg_val = (R_CFDC_CTR_TAIE | R_CFDC_CTR_ALIE | R_CFDC_CTR_BLIE | R_CFDC_CTR_OLIE | + R_CFDC_CTR_BORIE | R_CFDC_CTR_BOEIE | R_CFDC_CTR_EPIE | R_CFDC_CTR_EWIE | + R_CFDC_CTR_BEIE); + if (cfg->tx_delay_comp_offset) { + reg_val |= R_CFDC_CTR_TDCVFIE; + } + can_rzg3s_modify32(cfg->ctrl_dev, R_CFDC_CTR(cfg->id), 0, reg_val); + + can_rzg3s_tmb_irq_en(dev, CAN_RZG3S_TX_MAX_PKTS); + +#ifdef CONFIG_CAN_STATS + stats_init_and_reg(&ctx->stats.s_hdr, sizeof(uint32_t), + (sizeof(ctx->stats) - sizeof(struct stats_hdr)) / sizeof(uint32_t), + STATS_NAME_INIT_PARMS(can_rzg3s_ch), cfg->stat_gr_name); +#endif /* CONFIG_CAN_STATS */ + + can_rzg3s_g_rfifo_register(cfg->ctrl_dev, cfg->id, dev); + + LOG_DEV_INF(dev, "init done"); + + return 0; +} + +static void can_rzg3s_g_err_isr(const struct device *dev) +{ + struct can_rzg3s_data *ctx = dev->data; + uint32_t reg_gerfl; + uint32_t rx_gsts; + uint8_t rf_idx; + + ARG_UNUSED(ctx); + + /* Handle global error interrupts */ + reg_gerfl = can_rzg3s_read32(dev, R_CFDG_ERFL); + LOG_DEV_DBG(dev, "gerr %08x", reg_gerfl); + + if (reg_gerfl & R_CFDG_ERFL_EEF1) { + STATS_INC(ctx->stats, ecc_error_ch1); + LOG_DEV_ERR(dev, "ecc error has occurred on chn1"); + } + if (reg_gerfl & R_CFDG_ERFL_EEF0) { + STATS_INC(ctx->stats, ecc_error_ch0); + LOG_DEV_ERR(dev, "ecc error has occurred on chn0"); + } + if (reg_gerfl & R_CFDG_ERFL_CMPOF) { + STATS_INC(ctx->stats, canfd_msg_payload_overflow); + LOG_DEV_DBG(dev, "can-fd message payload overflow"); + } + + if (reg_gerfl & R_CFDG_ERFL_MES) { + LOG_DEV_DBG(dev, "message lost error"); + + rx_gsts = can_rzg3s_read32(dev, R_CFD_RF_MSTS) & 0xff; + LOG_DEV_DBG(dev, "gerr rfifo msts %08x", rx_gsts); + + while (rx_gsts) { + rf_idx = find_lsb_set(rx_gsts) - 1; + + can_rzg3s_modify32(dev, R_CFD_RFSTS(rf_idx), R_CFD_RFSTS_RFMLT, 0); + if (!rf_idx) { + STATS_INC(ctx->stats, rx_msg_lost_rfifo0); + } else if (rf_idx == 1) { + STATS_INC(ctx->stats, rx_msg_lost_rfifo1); + } + + rx_gsts = can_rzg3s_read32(dev, R_CFD_RF_MSTS) & 0xff; + LOG_DEV_DBG(dev, "gerr rfifo msts 1 %08x", rx_gsts); + } + } + + can_rzg3s_write32(dev, ~reg_gerfl, R_CFDG_ERFL); +} + +static void can_rzg3s_g_recc_isr(const struct device *dev) +{ + struct can_rzg3s_data *ctx = dev->data; + uint32_t rx_gsts; + uint8_t rf_idx; + + rx_gsts = can_rzg3s_read32(dev, R_CFD_RF_ISTS) & 0xff; + LOG_DEV_DBG(dev, "grecc rfifo ists %08x", rx_gsts); + + while (rx_gsts) { + rf_idx = find_lsb_set(rx_gsts) - 1; + + can_rzg3s_chn_handle_rx(ctx->rx_fifo_ch_devs[rf_idx], rf_idx); + + rx_gsts = can_rzg3s_read32(dev, R_CFD_RF_ISTS) & 0xff; + LOG_DEV_DBG(dev, "grecc rfifo ists 1 %08x", rx_gsts); + } +} + +static int can_rzg3s_g_get_core_clock(const struct device *ctrl_dev) +{ + struct can_rzg3s_data *ctx = ctrl_dev->data; + + return ctx->clk_fcan_rate; +} + +static int can_rzg3s_g_rfifo_register(const struct device *dev_ctrl, uint8_t rf_idx, + const struct device *ch_dev) +{ + struct can_rzg3s_data *ctx = dev_ctrl->data; + + ctx->rx_fifo_ch_devs[rf_idx] = ch_dev; + return 0; +} + +static int can_rzg3s_g_init_hw(const struct device *dev) +{ + const struct can_rzg3s_config *cfg = dev->config; + uint32_t reg_val; + int ret, i; + + /* Check RAMINIT flag as CAN RAM initialization takes place after the MCU reset */ + ret = can_rzg3s_wait_bits0(dev, R_CFDG_STS, R_CFDG_STS_GRAMINIT); + if (ret) { + return ret; + } + + /* Transition to Global Reset mode */ + can_rzg3s_modify32(dev, R_CFDG_CTR, R_CFDG_CTR_GSLPR, 0); + can_rzg3s_modify32(dev, R_CFDG_CTR, R_CFDG_CTR_GMDC_MASK, R_CFDG_CTR_GMDC_GRESET); + + /* Ensure Global reset mode */ + ret = can_rzg3s_wait_bits1(dev, R_CFDG_STS, R_CFDG_STS_GRSTSTS); + if (ret) { + return ret; + } + + /* Reset Global error flags */ + can_rzg3s_write32(dev, 0, R_CFDG_ERFL); + + /* Global configuration settings */ + reg_val = R_CFDG_CFG_CMPOC; + + /* Set External Clock if selected */ + if (cfg->clk_ext_rate) + reg_val |= R_CFDG_CFG_DCS; + + can_rzg3s_write32(dev, reg_val, R_CFDG_CFG); + + /* RES Bit Protocol Exception Disable + * The RPED bit configures the protocol exception event handling according to ISO 11898-1. + */ + can_rzg3s_modify32(dev, R_CFDG_FDCFG, 0, R_CFDG_FDCFG_RPED); + + /* set num afl entries */ + can_rzg3s_write32(dev, + (CAN_RZGS_FD_MAX_FILTER << 16) | CAN_RZGS_FD_MAX_FILTER, + R_CFDG_AFL_CFG); + + /* Channel's generic Rx fifo cfg */ + can_rzg3s_write32(dev, R_CFD_RMNB_CFG, R_CFD_RMNB); + for (i = 0; i < CAN_RZG3S_RX_FIFO_NUM; i++) { + can_rzg3s_write32(dev, can_rzg3s_rx_fifo_cfg[i], R_CFD_RFCC(i)); + } + + /* enable global irqs */ + reg_val = R_CFDG_CTR_MEIE | R_CFDG_CTR_CFMPOFIE; + can_rzg3s_modify32(dev, R_CFDG_CTR, R_CFDG_CTR_GSLPR, reg_val); + + /* Start Global operation mode */ + can_rzg3s_modify32(dev, R_CFDG_CTR, R_CFDG_CTR_GMDC_MASK, R_CFDG_CTR_GMDC_GOPM); + + /* Verify mode change */ + ret = can_rzg3s_wait_bits0(dev, R_CFDG_STS, R_CFDG_STS_GNOPM); + if (ret) { + LOG_DEV_ERR(dev, "global op mode failed"); + return ret; + } + + return 0; +} + +static int can_rzg3s_g_init(const struct device *dev) +{ + const struct can_rzg3s_config *cfg = dev->config; + struct can_rzg3s_data *ctx = dev->data; + int ret; + + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_DEV_ERR(dev, "Failed to configure CAN pins"); + return ret; + } + + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + + if (!device_is_ready(cfg->clk_dev_ram) || !device_is_ready(cfg->clk_dev_pclk)) { + LOG_DEV_ERR(dev, "clks dev not ready"); + return -ENODEV; + } + + if (!device_is_ready(cfg->rstp_n.dev) || !device_is_ready(cfg->rstc_n.dev)) { + LOG_DEV_ERR(dev, "resets dev not ready"); + return -ENODEV; + } + + ret = clock_control_on(cfg->clk_dev_pclk, (clock_control_subsys_t)&cfg->clk_mod_pclk); + if (ret) { + LOG_DEV_ERR(dev, "failed to configure clk_pclk"); + return ret; + } + + ret = clock_control_on(cfg->clk_dev_ram, (clock_control_subsys_t)&cfg->clk_mod_ram); + if (ret) { + LOG_DEV_ERR(dev, "failed to configure clk_ram"); + return ret; + } + + ret = clock_control_get_rate(cfg->clk_dev_pclk, + (clock_control_subsys_t)&cfg->clk_mod_pclk, + &ctx->clk_pclk_rate); + if (ret) { + LOG_DEV_ERR(dev, "failed to get clk rate"); + return ret; + } + + ctx->clk_fcan_rate = cfg->clk_ext_rate; + if (!ctx->clk_fcan_rate) { + /* DLL clock is pclk div 2 internaly */ + ctx->clk_fcan_rate = ctx->clk_pclk_rate / 2; + } + + (void)reset_line_deassert_dt(&cfg->rstp_n); + (void)reset_line_deassert_dt(&cfg->rstc_n); + +#ifdef CONFIG_CAN_STATS + stats_init_and_reg(&ctx->stats.s_hdr, sizeof(uint32_t), + (sizeof(ctx->stats) - sizeof(struct stats_hdr)) / sizeof(uint32_t), + STATS_NAME_INIT_PARMS(can_rzg3s_global), "can_rzg3s_global"); +#endif /* CONFIG_CAN_STATS */ + ret = can_rzg3s_g_init_hw(dev); + if (ret) { + LOG_DEV_ERR(dev, "failed to init"); + return ret; + } + + cfg->irq_config(); + + LOG_DEV_INF(dev, "CANFD IP init done ver:%08x pclk:%uHz ext_clk:%uHz", + can_rzg3s_read32(dev, R_CFDG_IPV), ctx->clk_pclk_rate, cfg->clk_ext_rate); + return 0; +} + +#define CAN_RZG3S_CHN_DATA_NAME(node_id) _CONCAT(can_rzg3s_chn_data, DT_DEP_ORD(node_id)) +#define CAN_RZG3S_CHN_CFG_NAME(node_id) _CONCAT(can_rzg3s_chn_config, DT_DEP_ORD(node_id)) +#define CAN_RZG3S_CHN_IRQC_NAME(node_id) _CONCAT(can_rzg3s_chn_irq_config, DT_DEP_ORD(node_id)) + +#define CAN_RZG3S_CH_IRQ_CONFIG_FUNC(p_node) \ + static void CAN_RZG3S_CHN_IRQC_NAME(p_node)(void) \ + { \ + IRQ_CONNECT(DT_IRQ_BY_NAME(p_node, ch_err, irq), \ + DT_IRQ_BY_NAME(p_node, ch_err, priority), can_rzg3s_isr_err, \ + DEVICE_DT_GET(p_node), 0); \ + IRQ_CONNECT(DT_IRQ_BY_NAME(p_node, ch_trx, irq), \ + DT_IRQ_BY_NAME(p_node, ch_trx, priority), can_rzg3s_isr_trx, \ + DEVICE_DT_GET(p_node), 0); \ + } + +#ifdef CONFIG_CAN_STATS +#define CAN_RZG3S_CHN_STATS_NAME(p_node) \ + .stat_gr_name = "can_rzg3s_ch" STRINGIFY(DT_REG_ADDR(p_node)), +#else +#define CAN_RZG3S_CHN_STATS_NAME(p_node) +#endif /* CONFIG_CAN_STATS */ + +#define CAN_RZG3S_CHN_INIT(p_node) \ + CAN_RZG3S_CH_IRQ_CONFIG_FUNC(p_node); \ + static const struct can_rzg3s_chn_config CAN_RZG3S_CHN_CFG_NAME(p_node) = { \ + .ctrl_dev = DEVICE_DT_GET(DT_PARENT(p_node)), \ + .bitrate = DT_PROP(p_node, bus_speed), \ + .sample_point = DT_PROP(p_node, sample_point), \ + .bitrate_data = DT_PROP(p_node, bus_speed_data), \ + .sample_point_data = DT_PROP(p_node, sample_point_data), \ + .phy = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(p_node, phys)), \ + .max_bitrate = DT_CAN_TRANSCEIVER_MAX_BITRATE(p_node, CAN_RZG3S_MAXBITRATE), \ + .tx_delay_comp_offset = DT_PROP_OR(p_node, tx_delay_comp_offset, 0), \ + .tx_delay_comp_offset_only = \ + DT_PROP_OR(p_node, renesas_tx_delay_comp_offset_only, 0), \ + .id = DT_REG_ADDR(p_node), \ + .irq_config = CAN_RZG3S_CHN_IRQC_NAME(p_node), \ + .irq_ch_err = DT_IRQ_BY_NAME(p_node, ch_err, irq), \ + .irq_ch_trx = DT_IRQ_BY_NAME(p_node, ch_trx, irq), \ + CAN_RZG3S_CHN_STATS_NAME(p_node)}; \ + static struct can_rzg3s_chn_data CAN_RZG3S_CHN_DATA_NAME(p_node) = {}; \ + \ + CAN_DEVICE_DT_DEFINE(p_node, can_rzg3s_chn_init, NULL, &CAN_RZG3S_CHN_DATA_NAME(p_node), \ + &CAN_RZG3S_CHN_CFG_NAME(p_node), POST_KERNEL, \ + CONFIG_CAN_RZG3S_CHN_INIT_PRIORITY, &can_rzg3s_can_api); + +#define CAN_RZG3S_IRQ_CONFIG_FUNC(inst) \ + static void can_rzg3s_irq_config##inst(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, g_err, irq), \ + DT_INST_IRQ_BY_NAME(inst, g_err, priority), can_rzg3s_g_err_isr, \ + DEVICE_DT_INST_GET(inst), 0); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, g_recc, irq), \ + DT_INST_IRQ_BY_NAME(inst, g_recc, priority), can_rzg3s_g_recc_isr, \ + DEVICE_DT_INST_GET(inst), 0); \ + irq_enable(DT_INST_IRQ_BY_NAME(inst, g_err, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(inst, g_recc, irq)); \ + } + +#define CAN_RZG3S_DEVICE_INIT(inst) \ + PINCTRL_DT_INST_DEFINE(inst); \ + CAN_RZG3S_IRQ_CONFIG_FUNC(inst) \ + \ + static const struct can_rzg3s_config can_rzg3s_cfg_##inst = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(inst)), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ + .clk_dev_pclk = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_NAME(inst, canfd)), \ + .clk_mod_pclk.module = DT_INST_CLOCKS_CELL_BY_NAME(inst, canfd, module), \ + .clk_mod_pclk.domain = DT_INST_CLOCKS_CELL_BY_NAME(inst, canfd, domain), \ + .clk_dev_ram = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_NAME(inst, fck)), \ + .clk_mod_ram.module = DT_INST_CLOCKS_CELL_BY_NAME(inst, fck, module), \ + .clk_mod_ram.domain = DT_INST_CLOCKS_CELL_BY_NAME(inst, fck, domain), \ + .clk_ext_rate = \ + DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(inst, can_clk), clock_frequency), \ + .rstp_n = RESET_DT_SPEC_INST_GET_BY_IDX(inst, 0), \ + .rstc_n = RESET_DT_SPEC_INST_GET_BY_IDX(inst, 1), \ + .irq_config = can_rzg3s_irq_config##inst, \ + }; \ + \ + static struct can_rzg3s_data can_rzg3s_data_##inst; \ + DEVICE_DT_INST_DEFINE(inst, can_rzg3s_g_init, NULL, &can_rzg3s_data_##inst, \ + &can_rzg3s_cfg_##inst, POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, NULL); \ + DT_INST_FOREACH_CHILD_STATUS_OKAY(inst, CAN_RZG3S_CHN_INIT); + +DT_INST_FOREACH_STATUS_OKAY(CAN_RZG3S_DEVICE_INIT) diff --git a/drivers/can/can_rzg3s_fd.h b/drivers/can/can_rzg3s_fd.h new file mode 100644 index 00000000000000..4297b3a3ece9dd --- /dev/null +++ b/drivers/can/can_rzg3s_fd.h @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_CAN_CAN_RZG3S_FD_H_ +#define ZEPHYR_DRIVERS_CAN_CAN_RZG3S_FD_H_ + +#define CAN_RZG3S_MAXBITRATE 8000000 +/* per-channel: number of AFL entries */ +#define CAN_RZGS_FD_MAX_FILTER CONFIG_CAN_MAX_FILTER + +/* RX Max number of buffers per channel */ +#define CAN_RZG3S_RX_MAX_PKTS CONFIG_CAN_RZGS_FD_MAX_RX +/* RX FIFO RFDC value */ +#if (CONFIG_CAN_RZGS_FD_MAX_RX == 4) +#define CAN_RZGS_RX_RFDC 0x1 +#elif (CONFIG_CAN_RZGS_FD_MAX_RX == 8) +#define CAN_RZGS_RX_RFDC 0x2 +#elif (CONFIG_CAN_RZGS_FD_MAX_RX == 16) +#define CAN_RZGS_RX_RFDC 0x3 +#elif (CONFIG_CAN_RZGS_FD_MAX_RX == 32) +#define CAN_RZGS_RX_RFDC 0x4 +#elif (CONFIG_CAN_RZGS_FD_MAX_RX == 48) +#define CAN_RZGS_RX_RFDC 0x5 +#elif (CONFIG_CAN_RZGS_FD_MAX_RX == 64) +#define CAN_RZGS_RX_RFDC 0x6 +#elif (CONFIG_CAN_RZGS_FD_MAX_RX == 128) +#define CAN_RZGS_RX_RFDC 0x7 +#else +BUILD_ASSERT(0, "incorrect value for CONFIG_CAN_RZGS_FD_MAX_RX"); +#endif /* CONFIG_CAN_RZGS_FD_MAX_RX */ + +/* RX Max CAN Payload Data Size, RX FIFO RFPLS value */ +#if (CONFIG_CAN_RZGS_FD_MAX_RX_DATA_SIZE == 8) +#define CAN_RZGS_RX_RFPLS 0x0 +#elif (CONFIG_CAN_RZGS_FD_MAX_RX_DATA_SIZE == 12) +#define CAN_RZGS_RX_RFPLS 0x1 +#elif (CONFIG_CAN_RZGS_FD_MAX_RX_DATA_SIZE == 16) +#define CAN_RZGS_RX_RFPLS 0x2 +#elif (CONFIG_CAN_RZGS_FD_MAX_RX_DATA_SIZE == 20) +#define CAN_RZGS_RX_RFPLS 0x3 +#elif (CONFIG_CAN_RZGS_FD_MAX_RX_DATA_SIZE == 24) +#define CAN_RZGS_RX_RFPLS 0x4 +#elif (CONFIG_CAN_RZGS_FD_MAX_RX_DATA_SIZE == 32) +#define CAN_RZGS_RX_RFPLS 0x5 +#elif (CONFIG_CAN_RZGS_FD_MAX_RX_DATA_SIZE == 48) +#define CAN_RZGS_RX_RFPLS 0x6 +#elif (CONFIG_CAN_RZGS_FD_MAX_RX_DATA_SIZE == 64) +#define CAN_RZGS_RX_RFPLS 0x7 +#else +BUILD_ASSERT(0, "incorrect value for CONFIG_CAN_RZGS_FD_MAX_RX_DATA_SIZE"); +#endif /* CONFIG_CAN_RZGS_FD_MAX_RX_DATA_SIZE */ + +/* TX Max number of TX Message Buffer per channel to use */ +#define CAN_RZG3S_TX_MAX_PKTS CONFIG_CAN_RZGS_FD_MAX_TX +#if (CONFIG_CAN_RZGS_FD_MAX_TX > 32) +BUILD_ASSERT(0, "incorrect value for CONFIG_CAN_RZGS_FD_MAX_TX"); +#endif + +/* Rx FIFO is a global resource of the controller. There are 8 such FIFOs + * available. Each channel gets a dedicated one RX FIFO + */ +#define CAN_RZG3S_RX_FIFO_NUM 8 + +/* TX Message Buffers a per channel resource. + * Each channel has up to 64 TX Message Buffers dedicated to them, but can use only 32 of them. + * CH0: TXMB0 - 15 and TXMB32 - 47 are available + * CH1: TXMB64 - 79 and TXMB96 - 111 are available + */ +#define CAN_RZG3S_TM_CH1_OFFSET 64 + +/* RX Message buffers are not used */ +#define R_CFD_RMNB_CFG 0x0 + +/* + * Global registers + */ +/* CFDGIPV */ +#define R_CFDG_IPV 0x0080 +/* CFDGCFG */ +#define R_CFDG_CFG 0x0084 +/* CFDGCTR */ +#define R_CFDG_CTR 0x0088 +/* CFDGSTS */ +#define R_CFDG_STS 0x008c +/* CFDGERFL */ +#define R_CFDG_ERFL 0x0090 +/* CFDGTSC */ +#define R_CFDG_TSC 0x0094 +/* (CFDRMNB) */ +#define R_CFD_RMNB 0x00a4 +/* ((CFDGTINTSTS0) 8bit access */ +#define R_CFDG_TINTSTS0(ch) (0x1300 + (ch)) +/* (CFDGFDCFG) */ +#define R_CFDG_FDCFG 0x1314 +/* + * Global registers fields + */ +/* CFDGCFG */ +#define R_CFDG_CFG_TSSS BIT(12) +#define R_CFDG_CFG_CMPOC BIT(5) +#define R_CFDG_CFG_DCS BIT(4) +#define R_CFDG_CFG_MME BIT(3) +#define R_CFDG_CFG_DRE BIT(2) +#define R_CFDG_CFG_DCE BIT(1) +#define R_CFDG_CFG_TPRI BIT(0) +/* CFDGCTR */ +#define R_CFDG_CTR_TSRST BIT(16) +#define R_CFDG_CTR_MOWEIE BIT(15) +#define R_CFDG_CTR_QMEIE BIT(14) +#define R_CFDG_CTR_CFMPOFIE BIT(11) +#define R_CFDG_CTR_THLEIE BIT(10) +#define R_CFDG_CTR_MEIE BIT(9) +#define R_CFDG_CTR_DEIE BIT(8) +#define R_CFDG_CTR_GSLPR BIT(2) +#define R_CFDG_CTR_GMDC_MASK (0x3) +#define R_CFDG_CTR_GMDC_GOPM (0x0) +#define R_CFDG_CTR_GMDC_GRESET (0x1) +#define R_CFDG_CTR_GMDC_GHALT (0x2) +#define R_CFDG_CTR_GMDC_KEEP (0x3) +/* CFDGSTS */ +#define R_CFDG_STS_GRAMINIT BIT(3) +#define R_CFDG_STS_GSLPSTS BIT(2) +#define R_CFDG_STS_GHLTSTS BIT(1) +#define R_CFDG_STS_GRSTSTS BIT(0) +/* CFDGERFL */ +#define R_CFDG_ERFL_EEF1 BIT(17) +#define R_CFDG_ERFL_EEF0 BIT(16) +#define R_CFDG_ERFL_CMPOF BIT(3) +#define R_CFDG_ERFL_MES BIT(1) + +/* Non-operational status */ +#define R_CFDG_STS_GNOPM (BIT(0) | BIT(1) | BIT(2) | BIT(3)) +/* ((CFDGTINTSTS0) */ +#define R_CFDG_TINTSTS0_CFOTIF BIT(6) +#define R_CFDG_TINTSTS0_TQOFIF BIT(5) +#define R_CFDG_TINTSTS0_THIF BIT(4) +#define R_CFDG_TINTSTS0_CFTIF BIT(3) +#define R_CFDG_TINTSTS0_TQIF BIT(2) +#define R_CFDG_TINTSTS0_TAIF BIT(1) +#define R_CFDG_TINTSTS0_TSIF BIT(0) +/* (CFDGFDCFG) */ +#define R_CFDG_FDCFG_RPED BIT(0) + +/* + * Channel Registers + */ +/* CFDCnNCFG */ +#define R_CFDC_NCFG(idx) (0x0000 + (0x10 * (idx))) +/* CFDCnCTR */ +#define R_CFDC_CTR(idx) (0x0004 + (0x10 * (idx))) +/* CFDCnSTS */ +#define R_CFDC_STS(idx) (0x0008 + (0x10 * (idx))) +/* CFDCnERFL */ +#define R_CFDC_ERFL(idx) (0x000C + (0x10 * (idx))) +/* CAN FD mode specific registers */ +/* CFDCnDCFG */ +#define R_CFDC_DCFG(idx) (0x1400 + (0x20 * (idx))) +/* CFDCnFDCFG */ +#define R_CFDC_FDCFG(idx) (0x1400 + 0x04 + (0x20 * (idx))) +/* CFDCnFDCTR */ +#define R_CFDC_FDCTR(idx) (0x1400 + 0x08 + (0x20 * (idx))) +/* CFDCnFDSTS */ +#define R_CFDC_FDSTS(idx) (0x1400 + 0x0c + (0x20 * (idx))) +/* CFDCnFDCRC */ +#define R_CFDC_FDCRC(idx) (0x1400 + 0x10 + (0x20 * (idx))) +/* + * Channel Registers fields + */ +/* CFDCnCTR */ +#define R_CFDC_CTR_CTMS_MASK GENMASK(26, 25) +#define R_CFDC_CTR_CTMS(val) (((val) << 25) & R_CFDC_CTR_CTMS_MASK) +#define R_CFDC_CTR_CTMS_STANDARD (0x0) +#define R_CFDC_CTR_CTMS_LISTENONLY (0x1) +#define R_CFDC_CTR_CTMS_EXT_LOOPBACK (0x2) +#define R_CFDC_CTR_CTMS_INT_LOOPBACK (0x3) +#define R_CFDC_CTR_CTME BIT(24) +#define R_CFDC_CTR_ERRD BIT(23) +#define R_CFDC_CTR_BOM_MASK GENMASK(22, 21) +#define R_CFDC_CTR_BOM(val) (((val) << 21) & GENMASK(22, 21)) +#define R_CFDC_CTR_BOM_ISO (0x0) +#define R_CFDC_CTR_BOM_BENTRY (0x1) +#define R_CFDC_CTR_BOM_BEND (0x2) +#define R_CFDC_CTR_TDCVFIE BIT(19) +#define R_CFDC_CTR_TAIE BIT(16) +#define R_CFDC_CTR_ALIE BIT(15) +#define R_CFDC_CTR_BLIE BIT(14) +#define R_CFDC_CTR_OLIE BIT(13) +#define R_CFDC_CTR_BORIE BIT(12) +#define R_CFDC_CTR_BOEIE BIT(11) +#define R_CFDC_CTR_EPIE BIT(10) +#define R_CFDC_CTR_EWIE BIT(9) +#define R_CFDC_CTR_BEIE BIT(8) +#define R_CFDC_CTR_CSLPR BIT(2) +#define R_CFDC_CTR_CHDC_MASK GENMASK(1, 0) +#define R_CFDC_CTR_CHDC_OPM (0x0) +#define R_CFDC_CTR_CHDC_RESET (0x1) +#define R_CFDC_CTR_CHDC_HALT (0x2) +#define R_CFDC_CTR_CHDC_KEEP (0x3) +/* CFDCnSTS */ +#define R_CFDC_STS_TEC(reg) (((reg) & GENMASK(31, 24)) >> 24) +#define R_CFDC_STS_REC(reg) (((reg) & GENMASK(23, 16)) >> 16) +#define R_CFDC_STS_ESIF BIT(8) +#define R_CFDC_STS_COMSTS BIT(7) +#define R_CFDC_STS_RECSTS BIT(6) +#define R_CFDC_STS_TRMSTS BIT(5) +#define R_CFDC_STS_BOSTS BIT(4) +#define R_CFDC_STS_EPSTS BIT(3) +#define R_CFDC_STS_SLPSTS BIT(2) +#define R_CFDC_STS_HLTSTS BIT(1) +#define R_CFDC_STS_RSTSTS BIT(0) +/* Channel Non-operational status */ +#define R_CFDC_STS_CNOPM (BIT(0) | BIT(1) | BIT(2) | BIT(3)) +/* CFDCnERFL */ +#define R_CFDC_ERFL_ADERR BIT(14) +#define R_CFDC_ERFL_B0ERR BIT(13) +#define R_CFDC_ERFL_B1ERR BIT(12) +#define R_CFDC_ERFL_CERR BIT(11) +#define R_CFDC_ERFL_AERR BIT(10) +#define R_CFDC_ERFL_FERR BIT(9) +#define R_CFDC_ERFL_SERR BIT(8) +#define R_CFDC_ERFL_ALF BIT(7) +#define R_CFDC_ERFL_BLF BIT(6) +#define R_CFDC_ERFL_OVLF BIT(5) +#define R_CFDC_ERFL_BORF BIT(4) +#define R_CFDC_ERFL_BOEF BIT(3) +#define R_CFDC_ERFL_EPF BIT(2) +#define R_CFDC_ERFL_EWF BIT(1) +#define R_CFDC_ERFL_BEF BIT(0) +/* CFDCnFDCFG */ +#define R_CFDC_FDCFG_TDCO_MSK GENMASK(23, 16) +#define R_CFDC_FDCFG_TDCO_OFS 16 +#define R_CFDC_FDCFG_TDCO_TDCE BIT(9) +#define R_CFDC_FDCFG_TDCO_TDCOC BIT(8) +/* CFDCnFDSTS */ +#define R_CFDC_FDSTS_TDCO_TDCVF BIT(15) +#define R_CFDC_FDSTS_TDCO_TDCR GENMASK(7, 0) + +/* + * RX FIFO Registers + */ +/* CFDRFCCn */ +#define R_CFD_RFCC(x) (0x00c0 + (0x04 * (x))) +/* (CFDRFSTSn) */ +#define R_CFD_RFSTS(x) (0x00e0 + (0x04 * (x))) +/* (CFDRFPCTRn) */ +#define R_CFD_RFPCTR(x) (0x0100 + (0x04 * (x))) +/*(CFDFESTS)*/ +#define R_CFD_RF_ESTS 0x02a0 +/* (CFDFMSTS) */ +#define R_CFD_RF_MSTS 0x02a8 +/* (CFDRFISTS) */ +#define R_CFD_RF_ISTS 0x02ac +/* + * RX FIFO Registers fields + */ +/* CFDRFCCn */ +#define R_CFD_RFCC_RFFIE BIT(16) +#define R_CFD_RFCC_RFIGCV(x) (((x) & 0x7) << 13) +#define R_CFD_RFCC_RFIM BIT(12) +#define R_CFD_RFCC_RFDC(x) (((x) & 0x7) << 8) +#define R_CFD_RFCC_RFPLS(x) (((x) & 0x7) << 4) +#define R_CFD_RFCC_RFIE BIT(1) +#define R_CFD_RFCC_RFE BIT(0) +/* (CFDRFSTSn) */ +#define R_CFD_RFSTS_RFIF BIT(3) +#define R_CFD_RFSTS_RFMLT BIT(2) +/* + * RX FIFO Access Message Buffer Component (CFDRFMBCPb[i]) + */ +#define R_CFD_RF_OFFSET 0x6000 +#define R_CFD_RF_RFID(x) (R_CFD_RF_OFFSET + (0x80 * (x))) +#define R_CFD_RF_RFPTR(x) (R_CFD_RF_OFFSET + (0x80 * (x)) + 0x04) +#define R_CFD_RF_RFFDSTS(x) (R_CFD_RF_OFFSET + (0x80 * (x)) + 0x08) +#define R_CFD_RF_RFDF(x, dw) (R_CFD_RF_OFFSET + (0x80 * (x)) + 0x0c + (0x04 * (dw))) +/* + * RX FIFO Access Message Buffer Component fields + */ +/* (CFDRFIDn) */ +#define R_CFD_RF_RFID_RFIDE BIT(31) +#define R_CFD_RF_RFID_RFRTR BIT(30) +/* (CFDRFPTRn) */ +#define R_CFD_RF_RFPTR_RFDLC(x) (((x) >> 28) & 0xf) +#define R_CFD_RF_RFPTR_RFTS(x) (((x) >> 0) & 0xffff) +/* (CFDRFFDSTSn) */ +#define R_CFD_RF_RFFDSTS_RFPTR(x) (((x) & GENMASK(31, 16)) >> 16) +#define R_CFD_RF_RFFDSTS_RFFDF BIT(2) +#define R_CFD_RF_RFFDSTS_RFBRS BIT(1) +#define R_CFD_RF_RFFDSTS_RFESI BIT(0) + +/* + * TX Message Buffer + */ +/* (CFDTMCn) */ +#define R_CFDC_TM_C(idx) (0x02d0 + (0x01 * (idx))) +/* (CFDTMSTSn) */ +#define R_CFDC_TM_STS(idx) (0x07D0 + (0x01 * (idx))) +/* (CFDTMTRSTSn) */ +#define R_CFDC_TM_TRSTS(ch, y) (0x0cd0 + (0x04 * (((ch) * 2) + (y)))) +/* (CFDTMTARSTSn) */ +#define R_CFDC_TM_TARSTS(ch, y) (0x0d70 + (0x04 * (((ch) * 2) + (y)))) +/* (CFDTMTCSTSn) */ +#define R_CFDC_TM_TCSTS(ch, y) (0x0e10 + (0x04 * (((ch) * 2) + (y)))) +/* (CFDTMTASTSn) */ +#define R_CFDC_TM_TASTS(ch, y) (0x0eb0 + (0x04 * (((ch) * 2) + (y)))) +/* (CFDTMIECn) */ +#define R_CFDC_TM_IEC(ch, y) (0x0f50 + (0x04 * (((ch) * 2) + (y)))) +/* + * TX Message Buffer fields + */ +/* (CFDTMCn) */ +#define R_CFDC_TM_C_TMOM BIT(2) +#define R_CFDC_TM_C_TMTAR BIT(1) +#define R_CFDC_TM_C_TMTR BIT(0) +/* (CFDTMSTSn) */ +#define R_CFDC_TM_STS_TMTRF_MASK GENMASK(2, 1) +#define R_CFDC_TM_STS_TMTRF(reg) (((reg) & R_CFDC_TM_STS_TMTRF_MASK) >> 1) +#define R_CFDC_TM_STS_TMTRF_TOK_ABORT 0x3 +#define R_CFDC_TM_STS_TMTRF_TOK 0x2 +#define R_CFDC_TM_STS_TMTRF_ABORT 0x1 +#define R_CFDC_TM_STS_TMTRF_NORES 0x0 +/* + * TX Message Buffer Access Message Buffer Component (CFDTMBCPb[i]) + */ +#define R_CFD_TM_OFFSET 0x10000 +#define R_CFD_TM_ID(idx) (R_CFD_TM_OFFSET + (0x80 * (idx))) +#define R_CFD_TM_PTR(idx) (R_CFD_TM_OFFSET + (0x80 * (idx)) + 0x04) +#define R_CFD_TM_FDCTR(idx) (R_CFD_TM_OFFSET + (0x80 * (idx)) + 0x08) +#define R_CFD_TM_DF(idx, dw) (R_CFD_TM_OFFSET + (0x80 * (idx)) + 0x0c + (0x04 * (dw))) +/* + * TX Message Buffer Access Message Buffer Component fields + */ +/* (CFDTMIDn */ +#define R_CFD_TM_ID_TMIDE BIT(31) +#define R_CFD_TM_ID_TMRTR BIT(30) +#define R_CFD_TM_ID_THLEN BIT(29) +/* (CFDTMPTRn) */ +#define R_CFD_TM_PTR_DLC(x) (((x) & 0xf) << 28) +/* (CFDTMFDCTRn) */ +#define R_CFD_TM_FDCTR_TMFDF BIT(2) +#define R_CFD_TM_FDCTR_TMBRS BIT(1) +#define R_CFD_TM_FDCTR_TMESI BIT(0) + +/* + * Acceptance Filter List Entry Control Register + */ +/* (CFDGAFLECTR) */ +#define R_CFDG_AFL_ECTR 0x0098 +/* (CFDGAFLCFG0) */ +#define R_CFDG_AFL_CFG 0x009C +#define R_CFDG_AFL_OFFSET 0x1800 +/* (CFDGAFLIDn) */ +#define R_CFDG_AFL_ID(j) (R_CFDG_AFL_OFFSET + (0x10 * (j))) +/* (CFDGAFLMn) */ +#define R_CFDG_AFL_M(j) (R_CFDG_AFL_OFFSET + 0x04 + (0x10 * (j))) +/* (CFDGAFLP0n) */ +#define R_CFDG_AFL_LP0(j) (R_CFDG_AFL_OFFSET + 0x08 + (0x10 * (j))) +/* (CFDGAFLP1n) */ +#define R_CFDG_AFL_LP1(j) (R_CFDG_AFL_OFFSET + 0x0c + (0x10 * (j))) +/* + * Acceptance Filter List Entry Control fields + */ +#define R_CFDG_AFL_ENTRIES_PER_PAGE 16 +/* (CFDGAFLECTR) */ +#define R_CFDG_AFL_ECTR_AFLDAE BIT(8) +#define R_CFDG_AFL_ECTR_AFLPN GENMASK(6, 0) +/* (CFDGAFLIDn) */ +#define R_CFDG_AFL_ID_GAFLIDE BIT(31) +#define R_CFDG_AFL_ID_GAFLRTR BIT(30) +#define R_CFDG_AFL_ID_GAFLLB BIT(29) +/* (CFDGAFLMn) */ +#define R_CFDG_AFL_M_GAFLIDEM BIT(31) +#define R_CFDG_AFL_M_GAFLRTRM BIT(30) +/* (CFDGAFLP0n) */ +#define R_CFDG_AFL_LP0_GAFLPTR_MASK GENMASK(31, 16) +#define R_CFDG_AFL_LP0_GAFLPTR_OFS 16 + +#endif /* ZEPHYR_DRIVERS_CAN_CAN_RZG3S_FD_H_ */ diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index cca600dcc324e8..dbd3e6658065ad 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -70,5 +70,6 @@ if(CONFIG_CLOCK_CONTROL_RENESAS_CPG_MSSR) zephyr_library_sources_ifdef(CONFIG_DT_HAS_RENESAS_R8A7795_CPG_MSSR_ENABLED clock_control_r8a7795_cpg_mssr.c) zephyr_library_sources_ifdef(CONFIG_DT_HAS_RENESAS_R7S9210_CPG_MSSR_ENABLED clock_control_r7s9210_cpg_mssr.c) endif() +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RENESAS_RZG3S clock_control_r9a08g045_cpg_mssr.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AST10X0 clock_control_ast10x0.c) diff --git a/drivers/clock_control/Kconfig.renesas b/drivers/clock_control/Kconfig.renesas index 32fbb3cecf3ed7..8004b219002c23 100644 --- a/drivers/clock_control/Kconfig.renesas +++ b/drivers/clock_control/Kconfig.renesas @@ -1,5 +1,5 @@ # Copyright (c) 2021-2022 IoT.bzh -# Copyright (c) 2023 EPAM Systems +# Copyright (c) 2024 EPAM Systems # SPDX-License-Identifier: Apache-2.0 config CLOCK_CONTROL_RENESAS_CPG_MSSR @@ -8,3 +8,13 @@ config CLOCK_CONTROL_RENESAS_CPG_MSSR depends on DT_HAS_RENESAS_R8A7795_CPG_MSSR_ENABLED || DT_HAS_RENESAS_R7S9210_CPG_MSSR_ENABLED help Enable support for Renesas RCar CPG MSSR driver. + +config CLOCK_CONTROL_RENESAS_RZG3S + bool "Renesas RZ/G3S family clock support" + default y + depends on DT_HAS_RENESAS_R9A08G045_CPG_MSSR_ENABLED + depends on CLOCK_CONTROL + help + Enable support for Renesas RZ/G3S CPG Clock Pulse Generator (CPG) driver. + The CPG driver supports only module's clocks. + The PLLs and core clocks are not configured by the CPG driver. diff --git a/drivers/clock_control/clock_control_r9a08g045_cpg_mssr.c b/drivers/clock_control/clock_control_r9a08g045_cpg_mssr.c new file mode 100644 index 00000000000000..dc9d3c874173ae --- /dev/null +++ b/drivers/clock_control/clock_control_r9a08g045_cpg_mssr.c @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * Renesas RZ/G3S r9a08g045 Clock Pulse Generator, Module Standby controller + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_r9a08g045_cpg_mssr + +#include +#include +#include +#include +#define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL +#include +LOG_MODULE_REGISTER(clock_control_rzg3s); + +#define LOG_DEV_ERR(dev, format, ...) LOG_ERR("%s:"#format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_WRN(dev, format, ...) LOG_WRN("%s:"#format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_INF(dev, format, ...) LOG_INF("%s:"#format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_DBG(dev, format, ...) LOG_DBG("%s:"#format, (dev)->name, ##__VA_ARGS__) + +#define MON_REG_WAIT_US 50 +#define CPG_NUM_DOMAINS 2 + +/* Specific MSTOP register offsets of RZ/G3S */ +#define ACPU_MSTOP (0xB60) +#define MCPU1_MSTOP (0xB64) +#define MCPU2_MSTOP (0xB68) +#define PERI_COM_MSTOP (0xB6C) +#define PERI_CPU_MSTOP (0xB70) +#define PERI_DDR_MSTOP (0xB74) +#define PERI_VIDEO_MSTOP (0xB78) +#define REG0_MSTOP (0xB7C) +#define REG1_MSTOP (0xB80) +#define TZCDDR_MSTOP (0xB84) +#define MHU_MSTOP (0xB88) +#define PERI_STP_MSTOP (0xB8C) +#define MCPU3_MSTOP (0xB90) +#define PERI_CPU2_MSTOP (0xB94) + +#define CLK_MON_R(reg) (0x180 + (reg)) + +enum rzg3s_clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R9A08G045_OSCCLK2, + + /* External Input Clocks */ + CLK_EXTAL, + + /* Internal Core Clocks */ + CLK_OSC_DIV1000, + CLK_PLL1, + CLK_PLL2, + CLK_PLL2_DIV2, + CLK_PLL2_DIV2_8, + CLK_PLL2_DIV6, + CLK_PLL3, + CLK_PLL3_DIV2, + CLK_PLL3_DIV2_2, + CLK_PLL3_DIV2_4, + CLK_PLL3_DIV2_8, + CLK_PLL3_DIV6, + CLK_PLL4, + CLK_PLL6, + CLK_PLL6_DIV2, + CLK_SEL_SPI, + CLK_SEL_OCTA, + CLK_SEL_SDHI0, + CLK_SEL_SDHI1, + CLK_SEL_SDHI2, + CLK_SEL_PLL4, + CLK_P1_DIV2, + CLK_P0_DIV2, + CLK_P4_DIV2, + CLK_P3_DIV2, + CLK_SD0_DIV4, + CLK_SD1_DIV4, + CLK_SD2_DIV4, + + /* Module Clocks */ + MOD_CLK_BASE, +}; + +struct rzg3s_cpg_core_clk { + uint16_t parent; + uint32_t out_freq; +}; + +#define DEF_INPUT(_id, _freq) \ + [_id] = {.out_freq = _freq, .parent = (-1)} + +#define DEF_FIXED(_id, _parent, _freq) \ + [_id] = {.out_freq = _freq, .parent = _parent} + +static const struct rzg3s_cpg_core_clk rzg3s_core_clks[MOD_CLK_BASE] = { + /* External Clock Inputs */ + DEF_INPUT(CLK_EXTAL, 24000000), + + DEF_FIXED(R9A08G045_OSCCLK, CLK_EXTAL, 24000000), + DEF_FIXED(R9A08G045_OSCCLK2, CLK_EXTAL, 8000000), + DEF_FIXED(R9A08G045_CLK_SD0, CLK_SEL_SDHI0, 133333000), + DEF_FIXED(R9A08G045_CLK_SD1, CLK_SEL_SDHI1, 133333000), + DEF_FIXED(R9A08G045_CLK_SD2, CLK_SEL_SDHI2, 133333000), + + DEF_FIXED(R9A08G045_CLK_I, CLK_PLL1, 1100000000), + DEF_FIXED(R9A08G045_CLK_I2, CLK_PLL6_DIV2, 250000000), + DEF_FIXED(R9A08G045_CLK_I3, CLK_PLL6_DIV2, 250000000), + DEF_FIXED(R9A08G045_CLK_S0, CLK_SEL_PLL4, 400000000), + DEF_FIXED(R9A08G045_CLK_P0, CLK_PLL2_DIV2_8, 100000000), + DEF_FIXED(R9A08G045_CLK_P1, CLK_PLL3_DIV2_4, 200000000), + DEF_FIXED(R9A08G045_CLK_P2, CLK_PLL3_DIV2_8, 100000000), + DEF_FIXED(R9A08G045_CLK_P3, CLK_PLL3_DIV2_4, 200000000), + DEF_FIXED(R9A08G045_CLK_P4, CLK_PLL2_DIV2, 160000000), + DEF_FIXED(R9A08G045_CLK_P5, CLK_PLL2_DIV2, 200000000), + DEF_FIXED(R9A08G045_CLK_M0, CLK_PLL3_DIV2_4, 200000000), + DEF_FIXED(R9A08G045_CLK_ZT, CLK_PLL3_DIV2_8, 100000000), + DEF_FIXED(R9A08G045_CLK_HP, CLK_PLL6, 250000000), + DEF_FIXED(R9A08G045_CLK_SPI0, CLK_SEL_SPI, 33333000), + DEF_FIXED(R9A08G045_CLK_SPI1, R9A08G045_CLK_SPI0, 16667000), + DEF_FIXED(R9A08G045_CLK_OC0, CLK_SEL_OCTA, 33333000), + DEF_FIXED(R9A08G045_CLK_OC1, CLK_SEL_OCTA, 16667000), + DEF_FIXED(R9A08G045_CLK_TSU, CLK_PLL2_DIV2, 100000000), + DEF_FIXED(R9A08G045_CLK_AT, CLK_PLL3_DIV2_2, 400000000), + DEF_FIXED(CLK_P4_DIV2, R9A08G045_CLK_P4, 80000000), +}; + +struct rzg3s_mod_clk { + uint16_t parent; + uint16_t clkon_off; + uint16_t clkon_bit; + uint16_t mstop_off; + uint16_t mstop_bits; +}; + +#define DEF_MOD(_id, _parent, _off, _bit, _mstop_off, _mstop_bit) \ + [_id] = { \ + .parent = (_parent), \ + .clkon_off = (_off), \ + .clkon_bit = (_bit), \ + .mstop_off = (_mstop_off), \ + .mstop_bits = (_mstop_bit), \ + } + +static const struct rzg3s_mod_clk rzg3s_mod_clks[R9A08G045_LAST_CLK] = { + DEF_MOD(R9A08G045_GIC600_GICCLK, R9A08G045_CLK_P1, 0x514, 0, 0, 0), + DEF_MOD(R9A08G045_IA55_PCLK, R9A08G045_CLK_P2, 0x518, 0, 0, 0), + DEF_MOD(R9A08G045_IA55_CLK, R9A08G045_CLK_P1, + 0x518, 1, PERI_CPU_MSTOP, BIT(13)), + DEF_MOD(R9A08G045_DMAC_ACLK, R9A08G045_CLK_P3, + 0x52c, 0, REG1_MSTOP, BIT(2) | BIT(3)), + DEF_MOD(R9A08G045_DMAC_PCLK, CLK_P3_DIV2, 0x52c, 1, 0, 0), + DEF_MOD(R9A08G045_OSTM0_PCLK, R9A08G045_CLK_P0, + 0x534, 0, REG0_MSTOP, BIT(4)), + DEF_MOD(R9A08G045_OSTM1_PCLK, R9A08G045_CLK_P0, + 0x534, 1, REG0_MSTOP, BIT(5)), + DEF_MOD(R9A08G045_OSTM2_PCLK, R9A08G045_CLK_P0, + 0x534, 2, REG0_MSTOP, BIT(6)), + DEF_MOD(R9A08G045_OSTM3_PCLK, R9A08G045_CLK_P0, + 0x534, 3, REG0_MSTOP, BIT(7)), + DEF_MOD(R9A08G045_OSTM4_PCLK, R9A08G045_CLK_P0, + 0x534, 4, REG0_MSTOP, BIT(8)), + DEF_MOD(R9A08G045_OSTM5_PCLK, R9A08G045_CLK_P0, + 0x534, 5, REG0_MSTOP, BIT(9)), + DEF_MOD(R9A08G045_OSTM6_PCLK, R9A08G045_CLK_P0, + 0x534, 6, REG0_MSTOP, BIT(10)), + DEF_MOD(R9A08G045_OSTM7_PCLK, R9A08G045_CLK_P0, + 0x534, 7, REG0_MSTOP, BIT(11)), + DEF_MOD(R9A08G045_MTU_X_MCK_MTU3, R9A08G045_CLK_P0, + 0x538, 0, MCPU1_MSTOP, BIT(2)), + DEF_MOD(R9A08G045_POE3_CLKM_POE, R9A08G045_CLK_P0, + 0x53C, 0, MCPU1_MSTOP, BIT(9)), + DEF_MOD(R9A08G045_GPT_PCLK, R9A08G045_CLK_P0, + 0x540, 0, MCPU3_MSTOP, BIT(5)), + DEF_MOD(R9A08G045_POEG_A_CLKP, R9A08G045_CLK_P0, + 0x544, 0, 0, 0), + DEF_MOD(R9A08G045_POEG_B_CLKP, R9A08G045_CLK_P0, + 0x544, 1, 0, 0), + DEF_MOD(R9A08G045_POEG_C_CLKP, R9A08G045_CLK_P0, + 0x544, 2, 0, 0), + DEF_MOD(R9A08G045_POEG_D_CLKP, R9A08G045_CLK_P0, + 0x544, 3, 0, 0), + DEF_MOD(R9A08G045_WDT0_PCLK, R9A08G045_CLK_P0, + 0x548, 0, 0, 0), + DEF_MOD(R9A08G045_WDT0_CLK, R9A08G045_OSCCLK, + 0x548, 1, REG0_MSTOP, BIT(0)), + DEF_MOD(R9A08G045_WDT1_PCLK, R9A08G045_CLK_P0, + 0x548, 2, 0, 0), + DEF_MOD(R9A08G045_WDT1_CLK, R9A08G045_OSCCLK, + 0x548, 3, REG0_MSTOP, BIT(1)), + DEF_MOD(R9A08G045_WDT2_PCLK, R9A08G045_CLK_P0, + 0x548, 4, 0, 0), + DEF_MOD(R9A08G045_WDT2_CLK, R9A08G045_OSCCLK, + 0x548, 5, REG0_MSTOP, BIT(2)), + DEF_MOD(R9A08G045_SPI_HCLK, R9A08G045_CLK_P3, + 0x550, 0, 0, 0), + DEF_MOD(R9A08G045_SPI_ACLK, R9A08G045_CLK_P3, + 0x550, 1, 0, 0), + DEF_MOD(R9A08G045_SPI_CLK, R9A08G045_CLK_SPI1, + 0x550, 2, MCPU1_MSTOP, BIT(1)), + DEF_MOD(R9A08G045_SPI_CLKX2, R9A08G045_CLK_SPI0, + 0x550, 3, 0, 0), + DEF_MOD(R9A08G045_SDHI0_IMCLK, CLK_SD0_DIV4, + 0x554, 0, PERI_COM_MSTOP, BIT(0)), + DEF_MOD(R9A08G045_SDHI0_IMCLK2, CLK_SD0_DIV4, + 0x554, 1, 0, 0), + DEF_MOD(R9A08G045_SDHI0_CLK_HS, R9A08G045_CLK_SD0, + 0x554, 2, 0, 0), + DEF_MOD(R9A08G045_SDHI0_ACLK, R9A08G045_CLK_P1, + 0x554, 3, 0, 0), + DEF_MOD(R9A08G045_SDHI1_IMCLK, CLK_SD1_DIV4, + 0x554, 4, PERI_COM_MSTOP, BIT(1)), + DEF_MOD(R9A08G045_SDHI1_IMCLK2, CLK_SD1_DIV4, + 0x554, 5, 0, 0), + DEF_MOD(R9A08G045_SDHI1_CLK_HS, R9A08G045_CLK_SD1, + 0x554, 6, 0, 0), + DEF_MOD(R9A08G045_SDHI1_ACLK, R9A08G045_CLK_P1, + 0x554, 7, 0, 0), + DEF_MOD(R9A08G045_SDHI2_IMCLK, CLK_SD2_DIV4, + 0x554, 8, 0, 0), + DEF_MOD(R9A08G045_SDHI2_IMCLK2, CLK_SD2_DIV4, + 0x554, 9, 0, 0), + DEF_MOD(R9A08G045_SDHI2_CLK_HS, R9A08G045_CLK_SD2, + 0x554, 10, 0, 0), + DEF_MOD(R9A08G045_SDHI2_ACLK, R9A08G045_CLK_P1, + 0x554, 11, 0, 0), + DEF_MOD(R9A08G045_SSI0_PCLK2, R9A08G045_CLK_P0, + 0x570, 0, MCPU1_MSTOP, BIT(10)), + DEF_MOD(R9A08G045_SSI0_PCLK_SFR, R9A08G045_CLK_P0, + 0x570, 1, 0, 0), + DEF_MOD(R9A08G045_SSI1_PCLK2, R9A08G045_CLK_P0, + 0x570, 2, MCPU1_MSTOP, BIT(11)), + DEF_MOD(R9A08G045_SSI1_PCLK_SFR, R9A08G045_CLK_P0, + 0x570, 3, 0, 0), + DEF_MOD(R9A08G045_SSI2_PCLK2, R9A08G045_CLK_P0, + 0x570, 4, MCPU1_MSTOP, BIT(12)), + DEF_MOD(R9A08G045_SSI2_PCLK_SFR, R9A08G045_CLK_P0, + 0x570, 5, 0, 0), + DEF_MOD(R9A08G045_SSI3_PCLK2, R9A08G045_CLK_P0, + 0x570, 6, MCPU1_MSTOP, BIT(13)), + DEF_MOD(R9A08G045_SSI3_PCLK_SFR, R9A08G045_CLK_P0, + 0x570, 7, 0, 0), + DEF_MOD(R9A08G045_SRC_CLKP, R9A08G045_CLK_P0, + 0x574, 0, MCPU1_MSTOP, BIT(3)), + DEF_MOD(R9A08G045_USB_U2H0_HCLK, R9A08G045_CLK_P1, + 0x578, 0, 0, 0), + DEF_MOD(R9A08G045_USB_U2H1_HCLK, R9A08G045_CLK_P1, + 0x578, 1, 0, 0), + DEF_MOD(R9A08G045_USB_U2P_EXR_CPUCLK, R9A08G045_CLK_P1, + 0x578, 2, 0, 0), + DEF_MOD(R9A08G045_USB_PCLK, R9A08G045_CLK_P1, + 0x578, 3, PERI_COM_MSTOP, + BIT(4) | BIT(5) | BIT(6) | BIT(7)), + DEF_MOD(R9A08G045_ETH0_CLK_AXI, R9A08G045_CLK_M0, + 0x57c, 0, PERI_COM_MSTOP, BIT(2)), + DEF_MOD(R9A08G045_ETH0_REFCLK, R9A08G045_CLK_HP, + 0x57c, 8, 0, 0), + DEF_MOD(R9A08G045_ETH1_CLK_AXI, R9A08G045_CLK_M0, + 0x57c, 1, PERI_COM_MSTOP, BIT(3)), + DEF_MOD(R9A08G045_ETH1_REFCLK, R9A08G045_CLK_HP, + 0x57c, 9, 0, 0), + DEF_MOD(R9A08G045_I2C0_PCLK, R9A08G045_CLK_P0, + 0x580, 0, MCPU2_MSTOP, BIT(10)), + DEF_MOD(R9A08G045_I2C1_PCLK, R9A08G045_CLK_P0, + 0x580, 1, MCPU2_MSTOP, BIT(11)), + DEF_MOD(R9A08G045_I2C2_PCLK, R9A08G045_CLK_P0, + 0x580, 2, MCPU2_MSTOP, BIT(12)), + DEF_MOD(R9A08G045_I2C3_PCLK, R9A08G045_CLK_P0, + 0x580, 3, MCPU2_MSTOP, BIT(13)), + DEF_MOD(R9A08G045_SCIF0_CLK_PCK, R9A08G045_CLK_P0, + 0x584, 0, MCPU2_MSTOP, BIT(1)), + DEF_MOD(R9A08G045_SCIF1_CLK_PCK, R9A08G045_CLK_P0, + 0x584, 1, MCPU2_MSTOP, BIT(2)), + DEF_MOD(R9A08G045_SCIF2_CLK_PCK, R9A08G045_CLK_P0, + 0x584, 2, MCPU2_MSTOP, BIT(3)), + DEF_MOD(R9A08G045_SCIF3_CLK_PCK, R9A08G045_CLK_P0, + 0x584, 3, MCPU2_MSTOP, BIT(4)), + DEF_MOD(R9A08G045_SCIF4_CLK_PCK, R9A08G045_CLK_P0, + 0x584, 4, MCPU2_MSTOP, BIT(5)), + DEF_MOD(R9A08G045_SCIF5_CLK_PCK, R9A08G045_CLK_P0, + 0x584, 5, MCPU3_MSTOP, BIT(4)), + DEF_MOD(R9A08G045_SCI0_CLKP, R9A08G045_CLK_P0, + 0x588, 0, MCPU2_MSTOP, BIT(7)), + DEF_MOD(R9A08G045_SCI1_CLKP, R9A08G045_CLK_P0, + 0x588, 1, MCPU2_MSTOP, BIT(8)), + DEF_MOD(R9A08G045_RSPI0_CLKB, R9A08G045_CLK_P0, + 0x590, 0, MCPU1_MSTOP, BIT(14)), + DEF_MOD(R9A08G045_RSPI1_CLKB, R9A08G045_CLK_P0, + 0x590, 1, MCPU1_MSTOP, BIT(15)), + DEF_MOD(R9A08G045_RSPI2_CLKB, R9A08G045_CLK_P0, + 0x590, 2, MCPU2_MSTOP, BIT(0)), + DEF_MOD(R9A08G045_RSPI3_CLKB, R9A08G045_CLK_P0, + 0x590, 3, MCPU3_MSTOP, BIT(2)), + DEF_MOD(R9A08G045_RSPI4_CLKB, R9A08G045_CLK_P0, + 0x590, 4, MCPU3_MSTOP, BIT(3)), + DEF_MOD(R9A08G045_CANFD_PCLK, CLK_P4_DIV2, + 0x594, 0, MCPU2_MSTOP, BIT(9)), + DEF_MOD(R9A08G045_CANFD_CLK_RAM, R9A08G045_CLK_P4, + 0x594, 1, 0, 0), + DEF_MOD(R9A08G045_GPIO_HCLK, R9A08G045_OSCCLK, + 0x598, 0, 0, 0), + DEF_MOD(R9A08G045_ADC_ADCLK, R9A08G045_CLK_TSU, + 0x5a8, 0, MCPU2_MSTOP, BIT(14)), + DEF_MOD(R9A08G045_ADC_PCLK, R9A08G045_CLK_TSU, + 0x5a8, 1, 0, 0), + DEF_MOD(R9A08G045_TSU_PCLK, R9A08G045_CLK_TSU, + 0x5ac, 0, MCPU2_MSTOP, BIT(15)), + DEF_MOD(R9A08G045_OCTA_ACLK, R9A08G045_CLK_OC1, + 0x5f4, 0, 0, 0), + DEF_MOD(R9A08G045_OCTA_MCLK, R9A08G045_CLK_OC0, + 0x5f4, 1, MCPU3_MSTOP, BIT(0)), + DEF_MOD(R9A08G045_PDM_PCLK, R9A08G045_CLK_P0, + 0x604, 0, 0, 0), + DEF_MOD(R9A08G045_PDM_CCLK, R9A08G045_OSCCLK2, + 0x604, 1, MCPU3_MSTOP, BIT(9)), + DEF_MOD(R9A08G045_PCI_ACLK, R9A08G045_CLK_M0, + 0x608, 0, 0, 0), + DEF_MOD(R9A08G045_PCI_CLKL1PM, R9A08G045_CLK_ZT, + 0x608, 1, 0, 0), + DEF_MOD(R9A08G045_SPDIF_PCLK, R9A08G045_CLK_P0, + 0x60c, 0, MCPU3_MSTOP, BIT(6)), + DEF_MOD(R9A08G045_I3C_TCLK, R9A08G045_CLK_P5, + 0x610, 1, MCPU3_MSTOP, BIT(10)), + DEF_MOD(R9A08G045_I3C_PCLK, R9A08G045_CLK_TSU, + 0x610, 0, 0, 0), + DEF_MOD(R9A08G045_VBAT_BCLK, R9A08G045_OSCCLK, + 0x614, 0, MCPU3_MSTOP, BIT(8)), + DEF_MOD(R9A08G045_MHU_PCLK, R9A08G045_CLK_P2, + 0x520, 0, MHU_MSTOP, BIT(0)), +}; + +struct rzg3s_cpg_config { + DEVICE_MMIO_ROM; /* Must be first */ + + const struct rzg3s_cpg_core_clk *core_clks; + const struct rzg3s_mod_clk *mod_clks; +}; + +struct rzg3s_cpg_data { + DEVICE_MMIO_RAM; /* Must be first */ + + struct k_spinlock lock; +}; + +static int rzg3s_cpg_module_checkpar(const struct device *dev, clock_control_subsys_t sys) +{ + struct renesas_cpg_clk *clk = (struct renesas_cpg_clk *)sys; + + if (!dev || !sys) { + return -EINVAL; + } + + if (clk->domain != CPG_MOD && clk->domain != CPG_CORE) { + return -EINVAL; + } + + if (clk->domain == CPG_MOD && clk->module >= R9A08G045_LAST_CLK) { + LOG_DEV_ERR(dev, "wrong module id %u", clk->module); + return -EINVAL; + } + + if (clk->domain == CPG_CORE && clk->module >= MOD_CLK_BASE) { + LOG_DEV_ERR(dev, "wrong core module id %u", clk->module); + return -EINVAL; + } + + return 0; +} + +static int rzg3s_cpg_clk_get_rate(const struct device *dev, + clock_control_subsys_t sys, uint32_t *rate) +{ + struct renesas_cpg_clk *clk = (struct renesas_cpg_clk *)sys; + const struct rzg3s_cpg_config *cfg = dev->config; + int32_t ret = -EINVAL; + uint32_t parent_id; + + if (!rate) { + LOG_DEV_ERR(dev, "received null ptr rate"); + return ret; + } + + ret = rzg3s_cpg_module_checkpar(dev, sys); + if (ret) { + return ret; + } + + if (clk->domain == CPG_MOD) { + parent_id = cfg->mod_clks[clk->module].parent; + + if (parent_id >= MOD_CLK_BASE) { + LOG_DEV_ERR(dev, "wrong module:%u parent id %u", clk->module, parent_id); + return -EINVAL; + } + + ret = cfg->core_clks[parent_id].out_freq; + } else if (clk->domain == CPG_CORE) { + ret = cfg->core_clks[clk->module].out_freq; + } + + *rate = ret; + return 0; +} + +static void rzg3s_cpg_change_reg_bits(mm_reg_t reg, uint32_t bitmask, bool set) +{ + uint32_t reg_val = (bitmask << 16); + + if (set) { + reg_val |= bitmask; + } + + sys_write32(reg_val, reg); +} + +static int rzg3s_cpg_wait_bit_val(mm_reg_t reg_addr, uint32_t mask, uint32_t val, + int32_t us_wait) +{ + uint32_t reg_val; + int32_t wait_cnt = (us_wait / 5); + + do { + reg_val = sys_read32(reg_addr) & mask; + + if (reg_val == val) { + break; + } + + if (wait_cnt > 0) { + int loops = 500; + + while (loops-- > 0) { + arch_nop(); + } + } + } while (wait_cnt-- > 0); + + return wait_cnt; +} + +static int rzg3s_cpg_mod_clock_on(const struct device *dev, uint32_t module) +{ + const struct rzg3s_cpg_config *cfg = dev->config; + const struct rzg3s_mod_clk *mod_clk; + mm_reg_t reg_addr; + uint32_t val; + int ret; + + mod_clk = &cfg->mod_clks[module]; + + /* enable mod clock */ + reg_addr = DEVICE_MMIO_GET(dev) + mod_clk->clkon_off; + val = BIT(mod_clk->clkon_bit); + rzg3s_cpg_change_reg_bits(reg_addr, val, true); + + /* monitor mod clock */ + reg_addr = DEVICE_MMIO_GET(dev) + CLK_MON_R(mod_clk->clkon_off); + ret = rzg3s_cpg_wait_bit_val(reg_addr, val, val, MON_REG_WAIT_US); + if (!ret) { + return -EIO; + } + + /* clear mod mstop */ + reg_addr = DEVICE_MMIO_GET(dev) + mod_clk->mstop_off; + val = mod_clk->mstop_bits; + rzg3s_cpg_change_reg_bits(reg_addr, val, false); + + return 0; +} + +static int rzg3s_cpg_mod_clock_off(const struct device *dev, uint32_t module) +{ + const struct rzg3s_cpg_config *cfg = dev->config; + const struct rzg3s_mod_clk *mod_clk; + mm_reg_t reg_addr; + uint32_t val; + int ret; + + mod_clk = &cfg->mod_clks[module]; + + /* set mod mstop */ + reg_addr = DEVICE_MMIO_GET(dev) + mod_clk->mstop_off; + val = mod_clk->mstop_bits; + rzg3s_cpg_change_reg_bits(reg_addr, val, true); + + /* disable mod clock */ + reg_addr = DEVICE_MMIO_GET(dev) + mod_clk->clkon_off; + val = BIT(mod_clk->clkon_bit); + rzg3s_cpg_change_reg_bits(reg_addr, val, false); + + /* monitor mod clock */ + reg_addr = DEVICE_MMIO_GET(dev) + CLK_MON_R(mod_clk->clkon_off); + ret = rzg3s_cpg_wait_bit_val(reg_addr, val, 0, MON_REG_WAIT_US); + if (!ret) { + LOG_DEV_DBG(dev, "module id %u enable tmo", module); + return -EIO; + } + + return 0; +} + +static int rzg3s_cpg_module_start(const struct device *dev, clock_control_subsys_t sys) +{ + struct renesas_cpg_clk *clk = (struct renesas_cpg_clk *)sys; + struct rzg3s_cpg_data *data = dev->data; + k_spinlock_key_t key; + int ret; + + ret = rzg3s_cpg_module_checkpar(dev, sys); + if (ret) { + return ret; + } + + if (clk->domain == CPG_CORE) { + LOG_DEV_WRN(dev, "en/dis of core clocks aren't supported by this controller"); + return -ENOTSUP; + } + + key = k_spin_lock(&data->lock); + ret = rzg3s_cpg_mod_clock_on(dev, clk->module); + k_spin_unlock(&data->lock, key); + + return ret; +} + +static int rzg3s_cpg_module_stop(const struct device *dev, clock_control_subsys_t sys) +{ + struct renesas_cpg_clk *clk = (struct renesas_cpg_clk *)sys; + struct rzg3s_cpg_data *data = dev->data; + k_spinlock_key_t key; + int ret; + + ret = rzg3s_cpg_module_checkpar(dev, sys); + if (ret) { + return ret; + } + + if (clk->domain == CPG_CORE) { + LOG_DEV_WRN(dev, "en/dis of core clocks aren't supported by this controller"); + return -ENOTSUP; + } + + key = k_spin_lock(&data->lock); + ret = rzg3s_cpg_mod_clock_off(dev, clk->module); + k_spin_unlock(&data->lock, key); + + return ret; +} + +static int rzg3s_cpg_init(const struct device *dev) +{ + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + + return 0; +} + +static const struct clock_control_driver_api rzg3s_cpg_api = { + .on = rzg3s_cpg_module_start, + .off = rzg3s_cpg_module_stop, + .get_rate = rzg3s_cpg_clk_get_rate, +}; + +#define RZG3S_CPG_INIT(inst) \ + static const struct rzg3s_cpg_config rzg3s_cpg_##inst##_config = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(inst)), \ + .core_clks = rzg3s_core_clks, \ + .mod_clks = rzg3s_mod_clks, \ + }; \ + \ + static struct rzg3s_cpg_data rzg3s_cpg_##inst##_data = { \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, rzg3s_cpg_init, NULL, &rzg3s_cpg_##inst##_data, \ + &rzg3s_cpg_##inst##_config, PRE_KERNEL_1, \ + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &rzg3s_cpg_api); + +DT_INST_FOREACH_STATUS_OKAY(RZG3S_CPG_INIT) diff --git a/drivers/counter/CMakeLists.txt b/drivers/counter/CMakeLists.txt index 3a59312da249b2..f80de14bbc8b11 100644 --- a/drivers/counter/CMakeLists.txt +++ b/drivers/counter/CMakeLists.txt @@ -48,3 +48,4 @@ zephyr_library_sources_ifdef(CONFIG_COUNTER_TIMER_GD32 counter_gd32_timer.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_SNPS_DW counter_dw_timer.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_SHELL counter_timer_shell.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_TIMER_RPI_PICO counter_rpi_pico_timer.c) +zephyr_library_sources_ifdef(CONFIG_COUNTER_RZ_GTM_COUNTER counter_rz_gtm.c) diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index 956c5d59f642ab..825aec31b4dd6b 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -94,4 +94,6 @@ source "drivers/counter/Kconfig.dw" source "drivers/counter/Kconfig.rpi_pico" +source "drivers/counter/Kconfig.rz" + endif # COUNTER diff --git a/drivers/counter/Kconfig.rz b/drivers/counter/Kconfig.rz new file mode 100644 index 00000000000000..365c85b4125571 --- /dev/null +++ b/drivers/counter/Kconfig.rz @@ -0,0 +1,10 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +config COUNTER_RZ_GTM_COUNTER + bool "Renesas RZ General Timer (GTM) Counter driver" + default y + depends on DT_HAS_RENESAS_OSTM_ENABLED + help + This module implements a kernel Counter driver for the Renesas RZ A2M/G3S + General Timer (GTM/OSTM). diff --git a/drivers/counter/counter_rz_gtm.c b/drivers/counter/counter_rz_gtm.c new file mode 100644 index 00000000000000..5e104deda15c07 --- /dev/null +++ b/drivers/counter/counter_rz_gtm.c @@ -0,0 +1,632 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_ostm + +#include +#include +#include +#include +#include +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045) +#include +#else +#include +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045) */ + +#include +LOG_MODULE_REGISTER(counter_rz_gtm, CONFIG_COUNTER_LOG_LEVEL); + +#define LOG_DEV_ERR(dev, format, ...) LOG_ERR("%s:" #format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_WRN(dev, format, ...) LOG_WRN("%s:" #format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_INF(dev, format, ...) LOG_INF("%s:" #format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_DBG(dev, format, ...) LOG_DBG("%s:" #format, (dev)->name, ##__VA_ARGS__) + +/* + * GTM/OSTM counter can't support both alarms and changing top value in free-running mode, + * so this drivers allows to use either alarms + free-running (counting up), + * either changing top value + interval mode (counting down). + * Therefore: + * - driver starts with counter in free-running mode with alarms support by default + * - set top is rejected if alarm is active + * - set top causes counter to switch to interval mode and disables alarms + * - set top to RZ_GTM_TIMER_TOP_VALUE switch counter back to free-running mode + * and enables alarms + * Over all it's practical to use counter instance as either free-running with alarms or as + * interval counter with supporting of changing top value, but not both. + */ + +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045) +#define counter_rz_gtm_clear_pending(irq) NVIC_ClearPendingIRQ(irq) +#define counter_rz_gtm_set_pending(irq) NVIC_SetPendingIRQ(irq) +#define counter_rz_gtm_is_pending(irq) NVIC_GetPendingIRQ(irq) +#else +#define counter_rz_gtm_clear_pending(irq) arm_gic_irq_clear_pending(irq) +#define counter_rz_gtm_set_pending(irq) arm_gic_irq_set_pending(irq) +#define counter_rz_gtm_is_pending(irq) arm_gic_irq_is_pending(irq) +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045) */ + +#define R_GTM_CMP 0x0 /* compare register */ +#define R_GTM_CNT 0x4 /* counter register */ +#define R_GTM_TE 0x10 /* count enable status register */ +#define R_GTM_TS 0x14 /* count start trigger register */ +#define R_GTM_TT 0x18 /* count stop trigger register */ +#define R_GTM_CTL 0x20 /* control register */ + +/* count enable status register */ +#define R_GTM_TE_ENABLED BIT(0) /* timer enabled */ +/* count start trigger register */ +#define R_GTM_TS_START BIT(0) /* trigger start of the timer */ +/* count stop trigger register */ +#define R_GTM_TT_STOP BIT(0) /* trigger stop of the timer */ +/* control register */ +#define R_GTM_CTL_IRQ_START_ENABLE BIT(0) +#define R_GTM_CTL_MODE_SHIFT 1 +#define R_GTM_CTL_MODE_INTERVAL 0 +#define R_GTM_CTL_MODE_FREERUN BIT(1) + +#define RZ_GTM_TIMER_TOP_VALUE UINT32_MAX + +struct counter_rz_gtm_config { + struct counter_config_info info; + + DEVICE_MMIO_NAMED_ROM(cnt_regs); + const struct device *clk_dev; + struct renesas_cpg_clk clk_mod; +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045) + struct reset_dt_spec reset_z; +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045) */ + uint8_t irqn; + void (*irq_config)(const struct device *dev); +}; + +struct counter_rz_gtm_data { + DEVICE_MMIO_NAMED_RAM(cnt_regs); + /* top callback function */ + counter_top_callback_t top_cb; + /* alarm callback function */ + counter_alarm_callback_t alarm_cb; + void *user_data; + uint32_t clk_freq; + struct k_spinlock lock; + uint32_t guard_period; + uint32_t top_val; + bool f_started:1; + bool f_periodic:1; +}; + +#define DEV_DATA(dev) ((struct counter_rz_gtm_data *)((dev)->data)) +#define DEV_CFG(dev) ((struct counter_rz_gtm_config *)((dev)->config)) + +static uint32_t counter_rz_gtm_read(const struct device *dev) +{ + return sys_read32(DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_CNT); +} + +static void counter_rz_gtm_stop_int(const struct device *dev) +{ + /* disable counter */ + sys_write8(R_GTM_TT_STOP, DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_TT); + + while ((sys_read8(DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_TE) & R_GTM_TE_ENABLED) == + R_GTM_TE_ENABLED) + ; +} + +static void counter_rz_gtm_start_freerun(const struct device *dev) +{ + /* enable counter in free running mode */ + sys_write8(R_GTM_CTL_MODE_FREERUN, DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_CTL); + + sys_write8(R_GTM_TS_START, DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_TS); +} + +static void counter_rz_gtm_start_interval(const struct device *dev) +{ + struct counter_rz_gtm_data *ctx = dev->data; + + /* start timer in interval mode */ + sys_write32(ctx->top_val, DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_CMP); + sys_write8(R_GTM_CTL_MODE_INTERVAL, DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_CTL); + sys_write8(R_GTM_TS_START, DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_TS); +} + +static uint32_t counter_rz_gtm_get_freq(const struct device *dev) +{ + struct counter_rz_gtm_data *ctx = dev->data; + + return ctx->clk_freq; +} + +static uint32_t counter_rz_gtm_get_top_value(const struct device *dev) +{ + struct counter_rz_gtm_data *ctx = dev->data; + uint32_t top_val = RZ_GTM_TIMER_TOP_VALUE; + + if (ctx->f_periodic) { + top_val = sys_read32(DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_CMP); + } + + return top_val; +} + +static int counter_rz_gtm_set_top_value(const struct device *dev, + const struct counter_top_cfg *top_cfg) +{ + const struct counter_rz_gtm_config *cfg = dev->config; + struct counter_rz_gtm_data *ctx = dev->data; + k_spinlock_key_t key; + uint32_t cur_tick; + int ret = 0; + + if (!top_cfg) { + LOG_DEV_ERR(dev, "top: invalid top value configuration"); + return -EINVAL; + } + + /* top value cannot be updated if the alarm is active */ + if (ctx->alarm_cb) { + LOG_DEV_ERR(dev, "top: value cannot be updated, alarm is active!"); + return -EBUSY; + } + + key = k_spin_lock(&ctx->lock); + + if (!ctx->f_periodic && top_cfg->ticks == RZ_GTM_TIMER_TOP_VALUE) { + goto exit_unlock; + } + + if (top_cfg->ticks == RZ_GTM_TIMER_TOP_VALUE) { + /* restore free running mode */ + counter_rz_gtm_stop_int(dev); + irq_disable(cfg->irqn); + counter_rz_gtm_clear_pending(cfg->irqn); + ctx->top_cb = NULL; + ctx->user_data = NULL; + ctx->top_val = RZ_GTM_TIMER_TOP_VALUE; + ctx->f_periodic = false; + LOG_DEV_DBG(dev, "top: restore to free-running"); + + if (ctx->f_started) { + counter_rz_gtm_start_freerun(dev); + counter_rz_gtm_clear_pending(cfg->irqn); + } + goto exit_unlock; + } + + ctx->top_cb = top_cfg->callback; + ctx->user_data = top_cfg->user_data; + ctx->top_val = top_cfg->ticks; + LOG_DEV_DBG(dev, "top: set periodic %08x irq:%d", top_cfg->ticks, !!(ctx->top_cb)); + + if (!ctx->f_started) { + ctx->f_periodic = true; + goto exit_unlock; + } + + if (!ctx->f_periodic) { + /* switch to interval mode first time, restart timer */ + counter_rz_gtm_stop_int(dev); + irq_disable(cfg->irqn); + ctx->f_periodic = true; + counter_rz_gtm_start_interval(dev); + if (ctx->top_cb) { + counter_rz_gtm_clear_pending(cfg->irqn); + irq_enable(cfg->irqn); + } + LOG_DEV_DBG(dev, "top: restart timer"); + goto exit_unlock; + } + + if (!ctx->top_cb) { + /* new top cfg is without callback - stop IRQs */ + irq_disable(cfg->irqn); + counter_rz_gtm_clear_pending(cfg->irqn); + } + + /* timer already in interval mode - only change top value */ + sys_write32(ctx->top_val, DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_CMP); + + /* check if counter reset is required */ + if (top_cfg->flags & COUNTER_TOP_CFG_DONT_RESET) { + /* Don't reset counter */ + cur_tick = counter_rz_gtm_read(dev); + if (cur_tick >= ctx->top_val) { + ret = -ETIME; + LOG_DEV_DBG(dev, "top: late"); + if (top_cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE) { + /* Reset counter if current is late */ + sys_write8(R_GTM_TS_START, + DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_TS); + LOG_DEV_DBG(dev, "top: late reset"); + } + } + } else { + /* reset counter by setting TS */ + sys_write8(R_GTM_TS_START, DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_TS); + LOG_DEV_DBG(dev, "top: reset"); + } + + LOG_DEV_DBG(dev, "top: updated"); + +exit_unlock: + k_spin_unlock(&ctx->lock, key); + return ret; +} + +static int counter_rz_gtm_get_value(const struct device *dev, uint32_t *ticks) +{ + if (ticks) { + *ticks = counter_rz_gtm_read(dev); + } + + return 0; +} + +static uint32_t counter_rz_gtm_get_guard_period(const struct device *dev, uint32_t flags) +{ + struct counter_rz_gtm_data *ctx = dev->data; + + ARG_UNUSED(flags); + return ctx->guard_period; +} + +static int counter_rz_gtm_set_guard_period(const struct device *dev, uint32_t guard, uint32_t flags) +{ + struct counter_rz_gtm_data *ctx = dev->data; + + ARG_UNUSED(flags); + __ASSERT_NO_MSG(guard < counter_rz_gtm_get_top_value(dev)); + + ctx->guard_period = guard; + LOG_DEV_DBG(dev, "guard_period: %08x", guard); + + return 0; +} + +static int counter_rz_gtm_start(const struct device *dev) +{ + const struct counter_rz_gtm_config *cfg = dev->config; + struct counter_rz_gtm_data *ctx = dev->data; + k_spinlock_key_t key; + + key = k_spin_lock(&ctx->lock); + + if (ctx->f_started) { + k_spin_unlock(&ctx->lock, key); + return -EALREADY; + } + + if (ctx->f_periodic) { + counter_rz_gtm_start_interval(dev); + } else { + counter_rz_gtm_start_freerun(dev); + } + + counter_rz_gtm_clear_pending(cfg->irqn); + ctx->f_started = true; + + if (ctx->top_cb) { + irq_enable(cfg->irqn); + } + + k_spin_unlock(&ctx->lock, key); + + LOG_DEV_DBG(dev, "start"); + + return 0; +} + +static int counter_rz_gtm_stop(const struct device *dev) +{ + const struct counter_rz_gtm_config *cfg = dev->config; + struct counter_rz_gtm_data *ctx = dev->data; + k_spinlock_key_t key; + + key = k_spin_lock(&ctx->lock); + + if (!ctx->f_started) { + k_spin_unlock(&ctx->lock, key); + return 0; + } + + /* disable counter */ + counter_rz_gtm_stop_int(dev); + + /* dis irq */ + irq_disable(cfg->irqn); + counter_rz_gtm_clear_pending(cfg->irqn); + + ctx->top_cb = NULL; + ctx->alarm_cb = NULL; + ctx->user_data = NULL; + + ctx->f_started = false; + + k_spin_unlock(&ctx->lock, key); + + LOG_DEV_DBG(dev, "stop"); + + return 0; +} + +static int counter_rz_gtm_set_alarm(const struct device *dev, uint8_t chan, + const struct counter_alarm_cfg *alarm_cfg) +{ + const struct counter_rz_gtm_config *cfg = dev->config; + struct counter_rz_gtm_data *ctx = dev->data; + bool absolute = alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE; + uint32_t val = alarm_cfg->ticks; + k_spinlock_key_t key; + bool irq_on_late; + uint32_t max_rel_val; + uint32_t now, diff; + int err = 0; + + if (!alarm_cfg) { + LOG_DEV_ERR(dev, "alarm: invalid configuration"); + return -EINVAL; + } + + /* Alarm callback is mandatory */ + if (!alarm_cfg->callback) { + LOG_DEV_ERR(dev, "alarm: callback function cannot be null"); + return -EINVAL; + } + + LOG_DEV_DBG(dev, "alarm: set tick:%08x flags:%x", alarm_cfg->ticks, alarm_cfg->flags); + + key = k_spin_lock(&ctx->lock); + + if (!ctx->f_started) { + k_spin_unlock(&ctx->lock, key); + LOG_DEV_ERR(dev, "alarm: counter not started"); + return -EINVAL; + } + + if (ctx->f_periodic) { + k_spin_unlock(&ctx->lock, key); + LOG_DEV_ERR(dev, "alarm: not supported in interval mode"); + return -ENOTSUP; + } + + if (ctx->alarm_cb) { + k_spin_unlock(&ctx->lock, key); + LOG_DEV_DBG(dev, "alarm: already set"); + return -EBUSY; + } + + now = counter_rz_gtm_read(dev); + ctx->alarm_cb = alarm_cfg->callback; + ctx->user_data = alarm_cfg->user_data; + + if (absolute) { + max_rel_val = RZ_GTM_TIMER_TOP_VALUE - ctx->guard_period; + irq_on_late = alarm_cfg->flags & COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE; + } else { + /* If relative value is smaller than half of the counter range + * it is assumed that there is a risk of setting value too late + * and late detection algorithm must be applied. When late + * setting is detected, interrupt shall be triggered for + * immediate expiration of the timer. Detection is performed + * by limiting relative distance between CC and counter. + * + * Note that half of counter range is an arbitrary value. + */ + irq_on_late = val < (RZ_GTM_TIMER_TOP_VALUE / 2U); + /* limit max to detect short relative being set too late. */ + max_rel_val = irq_on_late ? RZ_GTM_TIMER_TOP_VALUE / 2U : RZ_GTM_TIMER_TOP_VALUE; + val = (now + val) & RZ_GTM_TIMER_TOP_VALUE; + } + + sys_write32(val, DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_CMP); + + /* Decrement value to detect also case when val == counter_rz_gtm_read(dev). Otherwise, + * condition would need to include comparing diff against 0. + */ + diff = ((val - 1U) - counter_rz_gtm_read(dev)) & RZ_GTM_TIMER_TOP_VALUE; + if (diff > max_rel_val) { + if (absolute) { + err = -ETIME; + } + + /* Interrupt is triggered always for relative alarm and + * for absolute depending on the flag. + */ + if (irq_on_late) { + irq_enable(cfg->irqn); + counter_rz_gtm_set_pending(cfg->irqn); + LOG_DEV_DBG(dev, "alarm: trig1"); + } else { + ctx->alarm_cb = NULL; + LOG_DEV_DBG(dev, "alarm: skip"); + } + } else { + if (diff == 0) { + /* RELOAD value could be set just in time for interrupt + * trigger or too late. In any case time is interrupt + * should be triggered. No need to enable interrupt + * on TIMER just make sure interrupt is pending. + */ + irq_enable(cfg->irqn); + counter_rz_gtm_set_pending(cfg->irqn); + LOG_DEV_DBG(dev, "alarm: trig2"); + } else { + counter_rz_gtm_clear_pending(cfg->irqn); + irq_enable(cfg->irqn); + } + } + + k_spin_unlock(&ctx->lock, key); + + LOG_DEV_DBG(dev, "alarm: set done late:%d cmp:%08x now:%08x", irq_on_late, val, now); + + return err; +} + +static int counter_rz_gtm_cancel_alarm(const struct device *dev, uint8_t chan) +{ + const struct counter_rz_gtm_config *cfg = dev->config; + struct counter_rz_gtm_data *ctx = dev->data; + k_spinlock_key_t key; + + ARG_UNUSED(chan); + + key = k_spin_lock(&ctx->lock); + + if (!ctx->f_started) { + k_spin_unlock(&ctx->lock, key); + return -EINVAL; + } + + if (!ctx->alarm_cb) { + k_spin_unlock(&ctx->lock, key); + LOG_DEV_DBG(dev, "alarm: cancel with no alarm"); + return 0; + } + + irq_disable(cfg->irqn); + counter_rz_gtm_clear_pending(cfg->irqn); + ctx->alarm_cb = NULL; + ctx->user_data = NULL; + + k_spin_unlock(&ctx->lock, key); + LOG_DEV_DBG(dev, "alarm: cancel"); + return 0; +} + +static uint32_t counter_rz_gtm_get_pending_int(const struct device *dev) +{ + const struct counter_rz_gtm_config *config = dev->config; + + /* There is no register to check TIMER peripheral to check for interrupt + * pending, check directly in NVIC. + */ + return counter_rz_gtm_is_pending(config->irqn); +} + +static const struct counter_driver_api counter_rz_gtm_driver_api = { + .start = counter_rz_gtm_start, + .stop = counter_rz_gtm_stop, + .get_value = counter_rz_gtm_get_value, + .set_alarm = counter_rz_gtm_set_alarm, + .cancel_alarm = counter_rz_gtm_cancel_alarm, + .set_top_value = counter_rz_gtm_set_top_value, + .get_pending_int = counter_rz_gtm_get_pending_int, + .get_top_value = counter_rz_gtm_get_top_value, + .get_guard_period = counter_rz_gtm_get_guard_period, + .set_guard_period = counter_rz_gtm_set_guard_period, + .get_freq = counter_rz_gtm_get_freq, +}; + +void counter_rz_gtm_irq_handler(const struct device *dev) +{ + const struct counter_rz_gtm_config *cfg = dev->config; + struct counter_rz_gtm_data *ctx = dev->data; + counter_alarm_callback_t alarm_callback = ctx->alarm_cb; + k_spinlock_key_t key; + uint32_t now; + + key = k_spin_lock(&ctx->lock); + + now = counter_rz_gtm_read(dev); + LOG_DEV_DBG(dev, "irq_x: %08x", now); + + if (alarm_callback) { + irq_disable(cfg->irqn); + ctx->alarm_cb = NULL; + alarm_callback(dev, 0, now, ctx->user_data); + LOG_DEV_DBG(dev, "irq_alarm: now:%08x cmp:%08x", now, + sys_read32(DEVICE_MMIO_NAMED_GET(dev, cnt_regs) + R_GTM_CMP)); + } else if (ctx->top_cb) { + ctx->top_cb(dev, ctx->user_data); + LOG_DEV_DBG(dev, "irq_top:"); + } + + k_spin_unlock(&ctx->lock, key); +} + +static int counter_rz_gtm_init_timer(const struct device *dev) +{ + const struct counter_rz_gtm_config *cfg = dev->config; + struct counter_rz_gtm_data *ctx = dev->data; + int ret; + + DEVICE_MMIO_NAMED_MAP(dev, cnt_regs, K_MEM_CACHE_NONE); + + if (!device_is_ready(cfg->clk_dev)) { + LOG_DEV_ERR(dev, "clks dev not ready"); + return -ENODEV; + } +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045) + if (!device_is_ready(cfg->reset_z.dev)) { + LOG_DEV_ERR(dev, "resets dev not ready"); + return -ENODEV; + } +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045) */ + + ret = clock_control_on(cfg->clk_dev, (clock_control_subsys_t)&cfg->clk_mod); + if (ret) { + LOG_DEV_ERR(dev, "failed to configure clk_pclk"); + return ret; + } + + ret = clock_control_get_rate(cfg->clk_dev, (clock_control_subsys_t)&cfg->clk_mod, + &ctx->clk_freq); + if (ret) { + LOG_DEV_ERR(dev, "failed to get clk rate"); + return ret; + } + +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045) + (void)reset_line_deassert_dt(&cfg->reset_z); +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045) */ + + /* config/enable IRQ */ + cfg->irq_config(dev); + + LOG_DEV_INF(dev, "init done freq:%u", ctx->clk_freq); + return 0; +} + +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045) +#define COUNTER_RZ_GTM_GET_RST(inst) .reset_z = RESET_DT_SPEC_INST_GET_BY_IDX(inst, 0), +#define COUNTER_RZ_GTM_IRQ_FLAG(inst) 0 +#else +#define COUNTER_RZ_GTM_GET_RST(inst) +#define COUNTER_RZ_GTM_IRQ_FLAG(inst) DT_INST_IRQ(inst, flags) +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045) */ + +#define COUNTER_RZ_GTM_INIT(inst) \ + \ + static struct counter_rz_gtm_data counter_data_##inst; \ + \ + static void counter_rz_gtm_irq_cfg_##inst(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(inst), DT_INST_IRQ(inst, priority), \ + counter_rz_gtm_irq_handler, DEVICE_DT_INST_GET(inst), \ + COUNTER_RZ_GTM_IRQ_FLAG(inst)); \ + } \ + \ + static const struct counter_rz_gtm_config counter_cfg_##inst = { \ + DEVICE_MMIO_NAMED_ROM_INIT(cnt_regs, DT_DRV_INST(inst)), \ + .info = { \ + .max_top_value = RZ_GTM_TIMER_TOP_VALUE, \ + .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ + .channels = 1, \ + }, \ + .clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_IDX(inst, 0)), \ + .clk_mod.module = DT_INST_CLOCKS_CELL_BY_IDX(inst, 0, module), \ + .clk_mod.domain = DT_INST_CLOCKS_CELL_BY_IDX(inst, 0, domain), \ + COUNTER_RZ_GTM_GET_RST(inst).irq_config = counter_rz_gtm_irq_cfg_##inst, \ + .irqn = DT_INST_IRQN(inst), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, counter_rz_gtm_init_timer, NULL, &counter_data_##inst, \ + &counter_cfg_##inst, PRE_KERNEL_1, CONFIG_COUNTER_INIT_PRIORITY, \ + &counter_rz_gtm_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(COUNTER_RZ_GTM_INIT) diff --git a/drivers/dma/Kconfig.rza2 b/drivers/dma/Kconfig.rza2 index 9bbf78b1212450..15676b390d10d0 100644 --- a/drivers/dma/Kconfig.rza2 +++ b/drivers/dma/Kconfig.rza2 @@ -2,9 +2,9 @@ # SPDX-License-Identifier: Apache-2.0 config DMA_RZA2 - bool "Renesas RZA2 General Purpose DMA driver" - depends on DT_HAS_RENESAS_RZA2_DMA_ENABLED - select NOCACHE_MEMORY + bool "Renesas RZA2 and RZG3 General Purpose DMA driver" + depends on DT_HAS_RENESAS_RZA2_DMA_ENABLED || DT_HAS_RENESAS_RZG3_DMA_ENABLED + select NOCACHE_MEMORY if DT_HAS_RENESAS_RZA2_DMA_ENABLED default y help General Purpose DMA for Renesas RZA2 series. Please note that the buffers diff --git a/drivers/dma/dma_rza2.c b/drivers/dma/dma_rza2.c index 981d547a7f9942..f4ef567159a274 100644 --- a/drivers/dma/dma_rza2.c +++ b/drivers/dma/dma_rza2.c @@ -5,7 +5,6 @@ */ #include #include -#include #include #ifdef CONFIG_PINCTRL #include @@ -13,8 +12,21 @@ #include #include #include +#include +#include +#include +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rza2_dma) #define DT_DRV_COMPAT renesas_rza2_dma +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3_dma) +#define DT_DRV_COMPAT renesas_rzg3_dma +#endif + +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rza2_dma) +#include +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3_dma) +#include +#endif #define RZA2_DMA_CH_OFFT 0x40 #define RZA2_DMA_CH_8_15_OFFSET 0x400 @@ -165,6 +177,14 @@ struct dma_rza2_config { void (*irq_configure)(void); const struct pinctrl_dev_config *pcfg; uint32_t addr_alignment; +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3_dma) + const struct device *clock_dev; + struct renesas_cpg_clk aclk; + struct renesas_cpg_clk pclk; + /* reset controllers */ + struct reset_dt_spec aresetn; + struct reset_dt_spec rst_async; +#endif }; enum channel_mode { @@ -203,6 +223,7 @@ BUILD_ASSERT(CONFIG_DMA_RZA2_DESCRS_CHUNKS <= 32, static const struct dma_hw_config dma_hw_config_table[] = { /* resource, DMARS, CHCFG AM / TM , CHCFG LVL , CHCFG REQD */ +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rza2_dma) {DMA_MEM_2_MEM, 0x0, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE | DMAC_PRV_CHCFG_SET_TM, DMAC_PRV_CHCFG_SET_LVL_LEVEL, DMAC_PRV_CHCFG_REQD_UNDEFINED}, @@ -635,7 +656,581 @@ static const struct dma_hw_config dma_hw_config_table[] = { DMAC_PRV_CHCFG_SET_REQD_DST}, {DREQ0, 0x003, 0, 0, DMAC_PRV_CHCFG_REQD_UNDEFINED}, +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3_dma) + {DMA_MEM_2_MEM, 0x0, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE | DMAC_PRV_CHCFG_SET_TM, + DMAC_PRV_CHCFG_SET_LVL_LEVEL, DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0000_1000 0x8 << 2 | 0b11 */ + {DMA_RS_GTM_OSTM0TINT, 0x23, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0000_1001 0x9 << 2 | 0b11 */ + {DMA_RS_GTM_OSTM1TINT, 0x27, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0000_1010 0xa << 2 | 0b11 */ + {DMA_RS_GTM_OSTM2TINT, 0x2b, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0000_1011 0xb << 2 | 0b11 */ + {DMA_RS_GTM_OSTM3TINT, 0x2f, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0000_1100 0xc << 2 | 0b11 */ + {DMA_RS_GTM_OSTM4TINT, 0x33, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0000_1101 0xd << 2 | 0b11 */ + {DMA_RS_GTM_OSTM5TINT, 0x37, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0000_1110 0xe << 2 | 0b11 */ + {DMA_RS_GTM_OSTM6TINT, 0x3b, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0000_1111 0xf << 2 | 0b11 */ + {DMA_RS_GTM_OSTM7TINT, 0x3f, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_0000 0x10 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIA0, 0x43, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_0001 0x11 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIB0, 0x47, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_0010 0x12 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIC0, 0x4b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_0011 0x13 << 2 | 0b11 */ + {DMA_RS_MTU3_TGID0, 0x4f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_0100 0x14 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIA1, 0x53, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_0101 0x15 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIB1, 0x57, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_0110 0x16 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIA2, 0x5b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_0111 0x17 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIB2, 0x5f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_1000 0x18 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIA3, 0x63, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_1001 0x19 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIB3, 0x67, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_1010 0x1a << 2 | 0b11 */ + {DMA_RS_MTU3_TGIC3, 0x6b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_1011 0x1b << 2 | 0b11 */ + {DMA_RS_MTU3_TGID3, 0x6f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_1100 0x1c << 2 | 0b11 */ + {DMA_RS_MTU3_TGIA4, 0x73, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_1101 0x1d << 2 | 0b11 */ + {DMA_RS_MTU3_TGIB4, 0x77, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_1110 0x1e << 2 | 0b11 */ + {DMA_RS_MTU3_TGIC4, 0x7b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0001_1111 0x1f << 2 | 0b11 */ + {DMA_RS_MTU3_TGID4, 0x7f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_0000 0x20 << 2 | 0b11 */ + {DMA_RS_MTU3_TCIV4, 0x83, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_0001 0x21 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIU5, 0x87, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_0010 0x22 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIV5, 0x8b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_0011 0x23 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIW5, 0x8f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_0100 0x24 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIA6, 0x93, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_0101 0x25 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIB6, 0x97, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_0110 0x26 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIC6, 0x9b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_0111 0x27 << 2 | 0b11 */ + {DMA_RS_MTU3_TGID6, 0x9f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_1000 0x28 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIA7, 0xa3, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_1001 0x29 << 2 | 0b11 */ + {DMA_RS_MTU3_TGIB7, 0xa7, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_1010 0x2a << 2 | 0b11 */ + {DMA_RS_MTU3_TGIC7, 0xab, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_1011 0x2b << 2 | 0b11 */ + {DMA_RS_MTU3_TGID7, 0xaf, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_1100 0x2c << 2 | 0b11 */ + {DMA_RS_MTU3_TCIV7, 0xb3, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_1101 0x2d << 2 | 0b11 */ + {DMA_RS_MTU3_TGIA8, 0xb7, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_1110 0x2e << 2 | 0b11 */ + {DMA_RS_MTU3_TGIB8, 0xbb, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0010_1111 0x2f << 2 | 0b11 */ + {DMA_RS_MTU3_TGIC8, 0xbf, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0011_0000 0x30 << 2 | 0b11 */ + {DMA_RS_MTU3_TGID8, 0xc3, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0011_0001 0x31 << 2 | 0b11 */ + {DMA_RS_GPT_CCMPA0, 0xc7, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0011_0010 0x32 << 2 | 0b11 */ + {DMA_RS_GPT_CCMPB0, 0xcb, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0011_0011 0x33 << 2 | 0b11 */ + {DMA_RS_GPT_CMPC0, 0xcf, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0011_0100 0x34 << 2 | 0b11 */ + {DMA_RS_GPT_CMPD0, 0xd3, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0011_0101 0x35 << 2 | 0b11 */ + {DMA_RS_GPT_CMPE0, 0xd7, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0011_0110 0x36 << 2 | 0b11 */ + {DMA_RS_GPT_CMPF0, 0xdb, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0011_0111 0x37 << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGA0, 0xdf, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0011_1000 0x38 << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGB0, 0xe3, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0011_1001 0x39 << 2 | 0b11 */ + {DMA_RS_GPT_OVF0, 0xe7, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0011_1010 0x3a << 2 | 0b11 */ + {DMA_RS_GPT_UNF0, 0xeb, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0011_1110 0x3e << 2 | 0b11 */ + {DMA_RS_GPT_CCMPA1, 0xfb, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0011_1111 0x3f << 2 | 0b11 */ + {DMA_RS_GPT_CCMPB1, 0xff, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0100_0000 0x40 << 2 | 0b11 */ + {DMA_RS_GPT_CMPC1, 0x103, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0100_0001 0x41 << 2 | 0b11 */ + {DMA_RS_GPT_CMPD1, 0x107, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0100_0010 0x42 << 2 | 0b11 */ + {DMA_RS_GPT_CMPE1, 0x10b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0100_0011 0x43 << 2 | 0b11 */ + {DMA_RS_GPT_CMPF1, 0x10f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0100_0100 0x44 << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGA1, 0x113, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0100_0101 0x45 << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGB1, 0x117, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0100_0110 0x46 << 2 | 0b11 */ + {DMA_RS_GPT_OVF1, 0x11b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0100_0111 0x47 << 2 | 0b11 */ + {DMA_RS_GPT_UNF1, 0x11f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0100_1011 0x4b << 2 | 0b11 */ + {DMA_RS_GPT_CCMPA2, 0x12f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0100_1100 0x4c << 2 | 0b11 */ + {DMA_RS_GPT_CCMPB2, 0x133, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0100_1101 0x4d << 2 | 0b11 */ + {DMA_RS_GPT_CMPC2, 0x137, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0100_1110 0x4e << 2 | 0b11 */ + {DMA_RS_GPT_CMPD2, 0x13b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0100_1111 0x4f << 2 | 0b11 */ + {DMA_RS_GPT_CMPE2, 0x13f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0101_0000 0x50 << 2 | 0b11 */ + {DMA_RS_GPT_CMPF2, 0x143, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0101_0001 0x51 << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGA2, 0x147, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0101_0010 0x52 << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGB2, 0x14b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0101_0011 0x53 << 2 | 0b11 */ + {DMA_RS_GPT_OVF2, 0x14f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0101_0100 0x54 << 2 | 0b11 */ + {DMA_RS_GPT_UNF2, 0x153, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0101_1000 0x58 << 2 | 0b11 */ + {DMA_RS_GPT_CCMPA3, 0x163, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0101_1001 0x59 << 2 | 0b11 */ + {DMA_RS_GPT_CCMPB3, 0x167, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0101_1010 0x5a << 2 | 0b11 */ + {DMA_RS_GPT_CMPC3, 0x16b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0101_1011 0x5b << 2 | 0b11 */ + {DMA_RS_GPT_CMPD3, 0x16f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0101_1100 0x5c << 2 | 0b11 */ + {DMA_RS_GPT_CMPE3, 0x173, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0101_1101 0x5d << 2 | 0b11 */ + {DMA_RS_GPT_CMPF3, 0x177, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0101_1110 0x5e << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGA3, 0x17b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0101_1111 0x5f << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGB3, 0x17f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0110_0000 0x60 << 2 | 0b11 */ + {DMA_RS_GPT_OVF3, 0x183, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0110_0001 0x61 << 2 | 0b11 */ + {DMA_RS_GPT_UNF3, 0x187, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0110_0101 0x65 << 2 | 0b11 */ + {DMA_RS_GPT_CCMPA4, 0x197, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0110_0110 0x66 << 2 | 0b11 */ + {DMA_RS_GPT_CCMPB4, 0x19b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0110_0111 0x67 << 2 | 0b11 */ + {DMA_RS_GPT_CMPC4, 0x19f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0110_1000 0x68 << 2 | 0b11 */ + {DMA_RS_GPT_CMPD4, 0x1a3, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0110_1001 0x69 << 2 | 0b11 */ + {DMA_RS_GPT_CMPE4, 0x1a7, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0110_1010 0x6a << 2 | 0b11 */ + {DMA_RS_GPT_CMPF4, 0x1ab, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0110_1011 0x6b << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGA4, 0x1af, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0110_1100 0x6c << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGB4, 0x1b3, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0110_1101 0x6d << 2 | 0b11 */ + {DMA_RS_GPT_OVF4, 0x1b7, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0110_1110 0x6e << 2 | 0b11 */ + {DMA_RS_GPT_UNF4, 0x1bb, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0111_0010 0x72 << 2 | 0b11 */ + {DMA_RS_GPT_CCMPA5, 0x1cb, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0111_0011 0x73 << 2 | 0b11 */ + {DMA_RS_GPT_CCMPB5, 0x1cf, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0111_0100 0x74 << 2 | 0b11 */ + {DMA_RS_GPT_CMPC5, 0x1d3, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0111_0101 0x75 << 2 | 0b11 */ + {DMA_RS_GPT_CMPD5, 0x1d7, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0111_0110 0x76 << 2 | 0b11 */ + {DMA_RS_GPT_CMPE5, 0x1db, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0111_0111 0x77 << 2 | 0b11 */ + {DMA_RS_GPT_CMPF5, 0x1df, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0111_1000 0x78 << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGA5, 0x1e3, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0111_1001 0x79 << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGB5, 0x1e7, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0111_1010 0x7a << 2 | 0b11 */ + {DMA_RS_GPT_OVF5, 0x1eb, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0111_1011 0x7b << 2 | 0b11 */ + {DMA_RS_GPT_UNF5, 0x1ef, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 0111_1111 0x7f << 2 | 0b11 */ + {DMA_RS_GPT_CCMPA6, 0x1ff, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1000_0000 0x80 << 2 | 0b11 */ + {DMA_RS_GPT_CCMPB6, 0x203, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1000_0001 0x81 << 2 | 0b11 */ + {DMA_RS_GPT_CMPC6, 0x207, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1000_0010 0x82 << 2 | 0b11 */ + {DMA_RS_GPT_CMPD6, 0x20b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1000_0011 0x83 << 2 | 0b11 */ + {DMA_RS_GPT_CMPE6, 0x20f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1000_0100 0x84 << 2 | 0b11 */ + {DMA_RS_GPT_CMPF6, 0x213, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1000_0101 0x85 << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGA6, 0x217, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1000_0110 0x86 << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGB6, 0x21b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1000_0111 0x87 << 2 | 0b11 */ + {DMA_RS_GPT_OVF6, 0x21f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1000_1000 0x88 << 2 | 0b11 */ + {DMA_RS_GPT_UNF6, 0x223, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1000_1100 0x8c << 2 | 0b11 */ + {DMA_RS_GPT_CCMPA7, 0x233, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1000_1101 0x8d << 2 | 0b11 */ + {DMA_RS_GPT_CCMPB7, 0x237, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1000_1110 0x8e << 2 | 0b11 */ + {DMA_RS_GPT_CMPC7, 0x23b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1000_1111 0x8f << 2 | 0b11 */ + {DMA_RS_GPT_CMPD7, 0x23f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1001_0000 0x90 << 2 | 0b11 */ + {DMA_RS_GPT_CMPE7, 0x243, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1001_0001 0x91 << 2 | 0b11 */ + {DMA_RS_GPT_CMPF7, 0x247, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1001_0010 0x92 << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGA7, 0x24b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1001_0011 0x93 << 2 | 0b11 */ + {DMA_RS_GPT_ADTRGB7, 0x24f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1001_0100 0x94 << 2 | 0b11 */ + {DMA_RS_GPT_OVF7, 0x253, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1001_0101 0x95 << 2 | 0b11 */ + {DMA_RS_GPT_UNF7, 0x257, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1001_1001 0x99 << 2 | 0b10 */ + {DMA_RS_SSIF_DMA_RX0, 0x266, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1001_1001 0x99 << 2 | 0b1 */ + {DMA_RS_SSIF_DMA_TX0, 0x265, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1001_1010 0x9a << 2 | 0b10 */ + {DMA_RS_SSIF_DMA_RX1, 0x26a, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1001_1010 0x9a << 2 | 0b1 */ + {DMA_RS_SSIF_DMA_TX1, 0x269, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1001_1011 0x9b << 2 | 0b10 */ + {DMA_RS_SSIF_DMA_RX2, 0x26e, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1001_1011 0x9b << 2 | 0b1 */ + {DMA_RS_SSIF_DMA_TX2, 0x26d, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1001_1100 0x9c << 2 | 0b10 */ + {DMA_RS_SSIF_DMA_RX3, 0x272, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1001_1100 0x9c << 2 | 0b1 */ + {DMA_RS_SSIF_DMA_TX3, 0x271, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1001_1101 0x9d << 2 | 0b10 */ + {DMA_RS_SRC_IDEI, 0x276, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1001_1101 0x9d << 2 | 0b1 */ + {DMA_RS_SRC_ODFI, 0x275, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_0010 0xa2 << 2 | 0b10 */ + {DMA_RS_I2C_INTRIIC_RI0, 0x28a, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, + DMAC_PRV_CHCFG_SET_LVL_EDGE, DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_0010 0xa2 << 2 | 0b1 */ + {DMA_RS_I2C_INTRIIC_TI0, 0x289, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, + DMAC_PRV_CHCFG_SET_LVL_EDGE, DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1010_0011 0xa3 << 2 | 0b10 */ + {DMA_RS_I2C_INTRIIC_RI1, 0x28e, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, + DMAC_PRV_CHCFG_SET_LVL_EDGE, DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_0011 0xa3 << 2 | 0b1 */ + {DMA_RS_I2C_INTRIIC_TI1, 0x28d, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, + DMAC_PRV_CHCFG_SET_LVL_EDGE, DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1010_0100 0xa4 << 2 | 0b10 */ + {DMA_RS_I2C_INTRIIC_RI2, 0x292, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, + DMAC_PRV_CHCFG_SET_LVL_EDGE, DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_0100 0xa4 << 2 | 0b1 */ + {DMA_RS_I2C_INTRIIC_TI2, 0x291, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, + DMAC_PRV_CHCFG_SET_LVL_EDGE, DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1010_0101 0xa5 << 2 | 0b10 */ + {DMA_RS_I2C_INTRIIC_RI3, 0x296, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, + DMAC_PRV_CHCFG_SET_LVL_EDGE, DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_0101 0xa5 << 2 | 0b1 */ + {DMA_RS_I2C_INTRIIC_TI3, 0x295, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, + DMAC_PRV_CHCFG_SET_LVL_EDGE, DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1010_0110 0xa6 << 2 | 0b11 */ + {DMA_RS_I3C_INTRESP, 0x29b, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_0111 0xa7 << 2 | 0b11 */ + {DMA_RS_I3C_INTCMD, 0x29f, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1010_1000 0xa8 << 2 | 0b11 */ + {DMA_RS_I3C_INTIBI, 0x2a3, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_1001 0xa9 << 2 | 0b10 */ + {DMA_RS_I3C_INTRX, 0x2a6, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_1001 0xa9 << 2 | 0b1 */ + {DMA_RS_I3C_INTTX, 0x2a5, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1010_1010 0xaa << 2 | 0b11 */ + {DMA_RS_I3C_INTRCV, 0x2ab, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_1011 0xab << 2 | 0b11 */ + {DMA_RS_I3C_INTHRESP, 0x2af, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_1100 0xac << 2 | 0b11 */ + {DMA_RS_I3C_INTHCMD, 0x2b3, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1010_1101 0xad << 2 | 0b10 */ + {DMA_RS_I3C_INTHRX, 0x2b6, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_1101 0xad << 2 | 0b1 */ + {DMA_RS_I3C_INTHTX, 0x2b5, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1010_1110 0xae << 2 | 0b10 */ + {DMA_RS_SCIF_RXI0, 0x2ba, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_1110 0xae << 2 | 0b1 */ + {DMA_RS_SCIF_TXI0, 0x2b9, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1010_1111 0xaf << 2 | 0b10 */ + {DMA_RS_SCIF_RXI1, 0x2be, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_1111 0xaf << 2 | 0b1 */ + {DMA_RS_SCIF_TXI1, 0x2bd, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1011_0000 0xb0 << 2 | 0b10 */ + {DMA_RS_SCIF_RXI2, 0x2c2, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1011_0000 0xb0 << 2 | 0b1 */ + {DMA_RS_SCIF_TXI2, 0x2c1, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1011_0001 0xb1 << 2 | 0b10 */ + {DMA_RS_SCIF_RXI3, 0x2c6, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1011_0001 0xb1 << 2 | 0b1 */ + {DMA_RS_SCIF_TXI3, 0x2c5, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1011_0010 0xb2 << 2 | 0b10 */ + {DMA_RS_SCIF_RXI4, 0x2ca, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1011_0010 0xb2 << 2 | 0b1 */ + {DMA_RS_SCIF_TXI4, 0x2c9, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1011_0011 0xb3 << 2 | 0b10 */ + {DMA_RS_SCIF_RXI5, 0x2ce, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1011_0011 0xb3 << 2 | 0b1 */ + {DMA_RS_SCIF_TXI5, 0x2cd, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1011_0100 0xb4 << 2 | 0b10 */ + {DMA_RS_SCIg_RXI0, 0x2d2, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1011_0100 0xb4 << 2 | 0b1 */ + {DMA_RS_SCIg_TXI0, 0x2d1, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1011_0101 0xb5 << 2 | 0b10 */ + {DMA_RS_SCIg_RXI1, 0x2d6, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1011_0101 0xb5 << 2 | 0b1 */ + {DMA_RS_SCIg_TXI1, 0x2d5, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1011_0110 0xb6 << 2 | 0b10 */ + {DMA_RS_RSPI_SPRI0, 0x2da, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1011_0110 0xb6 << 2 | 0b1 */ + {DMA_RS_RSPI_SPTI0, 0x2d9, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1011_0111 0xb7 << 2 | 0b10 */ + {DMA_RS_RSPI_SPRI1, 0x2de, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1011_0111 0xb7 << 2 | 0b1 */ + {DMA_RS_RSPI_SPTI1, 0x2dd, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1011_1000 0xb8 << 2 | 0b10 */ + {DMA_RS_RSPI_SPRI2, 0x2e2, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1011_1000 0xb8 << 2 | 0b1 */ + {DMA_RS_RSPI_SPTI2, 0x2e1, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1011_1001 0xb9 << 2 | 0b10 */ + {DMA_RS_RSPI_SPRI3, 0x2e6, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1011_1001 0xb9 << 2 | 0b1 */ + {DMA_RS_RSPI_SPTI3, 0x2e5, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1011_1010 0xba << 2 | 0b10 */ + {DMA_RS_RSPI_SPRI4, 0x2ea, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1011_1010 0xba << 2 | 0b1 */ + {DMA_RS_RSPI_SPTI4, 0x2e9, DMAC_PRV_CHCFG_SET_AM_BUS_CYCLE, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1011_1011 0xbb << 2 | 0b11 */ + {DMA_RS_CANFD_RXF_DMA0, 0x2ef, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1011_1100 0xbc << 2 | 0b11 */ + {DMA_RS_CANFD_RXF_DMA1, 0x2f3, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1011_1101 0xbd << 2 | 0b11 */ + {DMA_RS_CANFD_RXF_DMA2, 0x2f7, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1011_1110 0xbe << 2 | 0b11 */ + {DMA_RS_CANFD_RXF_DMA3, 0x2fb, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1011_1111 0xbf << 2 | 0b11 */ + {DMA_RS_CANFD_RXF_DMA4, 0x2ff, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1100_0000 0xc0 << 2 | 0b11 */ + {DMA_RS_CANFD_RXF_DMA5, 0x303, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1100_0001 0xc1 << 2 | 0b11 */ + {DMA_RS_CANFD_RXF_DMA6, 0x307, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1100_0010 0xc2 << 2 | 0b11 */ + {DMA_RS_CANFD_RXF_DMA7, 0x30b, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1100_0011 0xc3 << 2 | 0b11 */ + {DMA_RS_CANFD_COM_DMA0, 0x30f, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1100_0100 0xc4 << 2 | 0b11 */ + {DMA_RS_CANFD_COM_DMA1, 0x313, DMAC_PRV_CHCFG_SET_AM_LEVEL, DMAC_PRV_CHCFG_SET_LVL_EDGE, + DMAC_PRV_CHCFG_REQD_UNDEFINED}, + /* 1001_1110 0x9e << 2 | 0b1 */ + {DMA_RS_SPDIF_RBDMAREQN_TX, 0x279, DMAC_PRV_CHCFG_SET_AM_LEVEL, + DMAC_PRV_CHCFG_SET_LVL_LEVEL, DMAC_PRV_CHCFG_SET_REQD_DST}, + /* 1001_1110 0x9e << 2 | 0b10 */ + {DMA_RS_SPDIF_RBDMAREQN_RX, 0x27a, DMAC_PRV_CHCFG_SET_AM_LEVEL, + DMAC_PRV_CHCFG_SET_LVL_LEVEL, DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1001_1111 0x9f << 2 | 0b11 */ + {DMA_RS_PDM_INT_PDM_DAT0, 0x27f, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_0000 0xa0 << 2 | 0b11 */ + {DMA_RS_PDM_INT_PDM_DAT1, 0x283, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, + /* 1010_0001 0xa1 << 2 | 0b11 */ + {DMA_RS_PDM_INT_PDM_DAT2, 0x287, 0x00000400U, DMAC_PRV_CHCFG_SET_LVL_LEVEL, + DMAC_PRV_CHCFG_SET_REQD_SRC}, +#endif {LAST_RESOURCE_MARKER, 0, 0, 0, 0}, }; @@ -656,6 +1251,83 @@ struct dma_rza2_data { #define DEV_DATA(dev) ((struct dma_rza2_data *)((dev)->data)) #define DEV_CFG(dev) ((struct dma_rza2_config *)((dev)->config)) +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rza2_dma) +#define RZ_DMA_BUS_ADDR(addr) Z_MEM_PHYS_ADDR(addr) + +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3_dma) +#define RZ_DMA_BUS_ADDR(addr) rzg3s_dma_bus_addr(addr) + +struct rzg3s_dma_address_convert_table { + uint32_t cm33_address; /* Base address of CM33 Address space */ + uint32_t bus_address; /* Base address of Bus-master's Address space */ + uint32_t size; /* size of region (byte) */ +}; + +#define BSP_ADDRESS_OFFSET_MASK (0x0FFFFFFF) + +#define CM33_SRAM_CODE_SECURE_BASE (0x00000000) +#define CM33_SRAM_CODE_NONSECURE_BASE (0x10000000) +#define CM33_SRAM_DATA_SECURE_BASE (0x20000000) +#define CM33_SRAM_DATA_NONSECURE_BASE (0x30000000) +#define CM33_SRAM_SIZE (0x10000000) +#define DMA_BUS_SRAM_BASE (0x00000000) +#define CM33_IOREG_SECURE_BASE (0x40000000) +#define CM33_IOREG_NONSECURE_BASE (0x50000000) +#define CM33_IOREG_SIZE (0x10000000) +#define DMA_BUS_IOREG_BASE (0x10000000) +#define CM33_DDR_SECURE_BASE (0x60000000) +#define CM33_DDR_NONSECURE_BASE (0x70000000) +#define CM33_DDR_SIZE (0x10000000) +#define DMA_BUS_DDR_BASE (0x40000000) +#define CM33_SPI_SECURE_BASE (0x80000000) +#define CM33_SPI_NONSECURE_BASE (0x90000000) +#define CM33_SPI_SIZE (0x10000000) +#define DMA_BUS_SPI_BASE (0x20000000) +#define CM33_PCIE_SECURE_BASE (0xA0000000) +#define CM33_PCIE_NONSECURE_BASE (0xB0000000) +#define CM33_PCIE_SIZE (0x10000000) +#define DMA_BUS_PCIE_BASE (0x30000000) + +struct rzg3s_dma_address_convert_table rzg3s_dma_addr_convert_tbl[] = { + {CM33_SRAM_CODE_SECURE_BASE, DMA_BUS_SRAM_BASE, CM33_SRAM_SIZE}, + {CM33_SRAM_CODE_NONSECURE_BASE, DMA_BUS_SRAM_BASE, CM33_SRAM_SIZE}, + {CM33_SRAM_DATA_SECURE_BASE, DMA_BUS_SRAM_BASE, CM33_SRAM_SIZE}, + {CM33_SRAM_DATA_NONSECURE_BASE, DMA_BUS_SRAM_BASE, CM33_SRAM_SIZE}, + {CM33_IOREG_SECURE_BASE, DMA_BUS_IOREG_BASE, CM33_IOREG_SIZE}, + {CM33_IOREG_NONSECURE_BASE, DMA_BUS_IOREG_BASE, CM33_IOREG_SIZE}, + {CM33_DDR_SECURE_BASE, DMA_BUS_DDR_BASE, CM33_DDR_SIZE}, + {CM33_DDR_NONSECURE_BASE, DMA_BUS_DDR_BASE, CM33_DDR_SIZE}, + {CM33_SPI_SECURE_BASE, DMA_BUS_SPI_BASE, CM33_SPI_SIZE}, + {CM33_SPI_NONSECURE_BASE, DMA_BUS_SPI_BASE, CM33_SPI_SIZE}, + {CM33_PCIE_SECURE_BASE, DMA_BUS_PCIE_BASE, CM33_PCIE_SIZE}, + {CM33_PCIE_NONSECURE_BASE, DMA_BUS_PCIE_BASE, CM33_PCIE_SIZE}, +}; + +uint32_t rzg3s_dma_bus_addr(uint32_t original_address) +{ + struct rzg3s_dma_address_convert_table *p_tbl = &rzg3s_dma_addr_convert_tbl[0]; + uint32_t converted_address = original_address; + uint32_t cm33_base; + uint32_t i; + + for (i = 0; i < ARRAY_SIZE(rzg3s_dma_addr_convert_tbl); p_tbl++) { + cm33_base = p_tbl->cm33_address; + + if (cm33_base <= original_address && + (original_address < (cm33_base + p_tbl->size))) { + /* find region: convert address */ + converted_address = + (original_address & BSP_ADDRESS_OFFSET_MASK) | p_tbl->bus_address; + + /* exit loop */ + break; + } + } + + return converted_address; +} +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3_dma) */ + static void rza2_set_n0sa(const struct device *dev, int ch, uint32_t saddr) { sys_write32(saddr, N0SA(dev, ch)); @@ -874,8 +1546,8 @@ static int rza2_construct_link_chain(const struct device *dev, struct dma_config return -EINVAL; } - chan->descrs[i].src_addr = Z_MEM_PHYS_ADDR(block->source_address); - chan->descrs[i].dest_addr = Z_MEM_PHYS_ADDR(block->dest_address); + chan->descrs[i].src_addr = RZ_DMA_BUS_ADDR(block->source_address); + chan->descrs[i].dest_addr = RZ_DMA_BUS_ADDR(block->dest_address); chan->descrs[i].trans_byte = block->block_size; chan->descrs[i].interval = 0; chan->descrs[i].config = ch_cfg; @@ -897,7 +1569,7 @@ static int rza2_construct_link_chain(const struct device *dev, struct dma_config chan->descrs[i].next_link_address = 0; } else { chan->descrs[i].next_link_address = - Z_MEM_PHYS_ADDR((uint32_t)&chan->descrs[i + 1]); + RZ_DMA_BUS_ADDR((uint32_t)&chan->descrs[i + 1]); } total_bytes += block->block_size; @@ -938,11 +1610,13 @@ static int dma_rza2_config(const struct device *dev, uint32_t channel, struct dm int ret; struct dma_rza2_data *data = dev->data; uint32_t channel_cfg = 0; - uint32_t channel_ext; + uint32_t channel_ext = 0; uint32_t dctrl_cfg = 0; struct dma_hw_config hw_config; uint32_t interval = 0; +#ifdef CONFIG_CACHE_MANAGEMENT uint32_t phys_addr; +#endif k_spinlock_key_t key; if (dma_cfg->dma_slot >= LAST_RESOURCE_MARKER) { @@ -1065,7 +1739,7 @@ static int dma_rza2_config(const struct device *dev, uint32_t channel, struct dm }; rza2_set_nxla(dev, channel, - Z_MEM_PHYS_ADDR((uint32_t)&data->channels[channel].descrs[0])); + RZ_DMA_BUS_ADDR((uint32_t)&data->channels[channel].descrs[0])); } else { data->channels[channel].mode = REGISTER_MODE; @@ -1077,8 +1751,8 @@ static int dma_rza2_config(const struct device *dev, uint32_t channel, struct dm goto unlock; } - rza2_set_n0sa(dev, channel, Z_MEM_PHYS_ADDR(dma_cfg->head_block->source_address)); - rza2_set_n0da(dev, channel, Z_MEM_PHYS_ADDR(dma_cfg->head_block->dest_address)); + rza2_set_n0sa(dev, channel, RZ_DMA_BUS_ADDR(dma_cfg->head_block->source_address)); + rza2_set_n0da(dev, channel, RZ_DMA_BUS_ADDR(dma_cfg->head_block->dest_address)); rza2_set_n0tb(dev, channel, dma_cfg->head_block->block_size); channel_cfg &= ~DMAC_PRV_CHCFG_SET_DMS; /* Set register mode */ @@ -1096,7 +1770,8 @@ static int dma_rza2_config(const struct device *dev, uint32_t channel, struct dm } channel_ext = (DMAC_PRV_CHEXT_SET_DPR_NON_SECURE | DMAC_PRV_CHEXT_SET_SPR_NON_SECURE); - phys_addr = Z_MEM_PHYS_ADDR(dma_cfg->head_block->source_address); +#ifdef CONFIG_CACHE_MANAGEMENT + phys_addr = RZ_DMA_BUS_ADDR(dma_cfg->head_block->source_address); /* set bus parameter for source */ if ((phys_addr <= DMAC_PRV_DMA_EXTERNAL_BUS_END) || ((phys_addr >= DMAC_PRV_DMA_EXTERNAL_BUS_MIRROR_START) && @@ -1105,7 +1780,7 @@ static int dma_rza2_config(const struct device *dev, uint32_t channel, struct dm } else { channel_ext |= DMAC_PRV_CHEXT_SET_SCA_STRONG; } - phys_addr = Z_MEM_PHYS_ADDR(dma_cfg->head_block->dest_address); + phys_addr = RZ_DMA_BUS_ADDR(dma_cfg->head_block->dest_address); /* set bus parameter for destination */ if ((phys_addr <= DMAC_PRV_DMA_EXTERNAL_BUS_END) || ((phys_addr >= DMAC_PRV_DMA_EXTERNAL_BUS_MIRROR_START) && @@ -1114,6 +1789,7 @@ static int dma_rza2_config(const struct device *dev, uint32_t channel, struct dm } else { channel_ext |= DMAC_PRV_CHEXT_SET_DCA_STRONG; } +#endif rza2_set_chcfg(dev, channel, channel_cfg); rza2_set_dctrl(dev, channel, dctrl_cfg); @@ -1477,11 +2153,14 @@ static void dma_rza2_err_isr(const struct device *dev) channel_mask = err_0_7 | (err_8_15 << 8); for (ch = 0; ch < config->num_channels; ch++) { - if ((channel_mask & BIT(ch)) && (data->channels[ch].err_callback_en == 0) && - data->channels[ch].dma_callback) { - data->channels[ch].dma_callback(dev, data->channels[ch].user_data, ch, - DMA_STATUS_BLOCK); - dma_rza2_channel_free(dev, ch); + if (channel_mask & BIT(ch)) { + if ((data->channels[ch].err_callback_en == 0) && + data->channels[ch].dma_callback) { + data->channels[ch].dma_callback(dev, data->channels[ch].user_data, + ch, DMA_STATUS_BLOCK); + dma_rza2_channel_free(dev, ch); + } + rza2_set_chctrl(dev, ch, rza2_get_chctrl(dev, ch) | SWRST); } } } @@ -1492,25 +2171,62 @@ static int dma_rza2_init(const struct device *dev) int ret; #ifdef CONFIG_PINCTRL - ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); - if (ret < 0) { - LOG_ERR("unable to configure DMA pins"); - return -EINVAL; + if (cfg->pcfg) { + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_ERR("unable to configure DMA pins"); + return -EINVAL; + } } #endif DEVICE_MMIO_NAMED_MAP(dev, reg_main, K_MEM_CACHE_NONE); DEVICE_MMIO_NAMED_MAP(dev, ext, K_MEM_CACHE_NONE); +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3_dma) + ret = clock_control_on(cfg->clock_dev, (clock_control_subsys_t)&cfg->pclk); + if (ret != 0) { + LOG_ERR("Can't turn on pclk clock for %s\n", dev->name); + return ret; + } + + ret = clock_control_on(cfg->clock_dev, (clock_control_subsys_t)&cfg->aclk); + if (ret != 0) { + LOG_ERR("Can't turn on aclk clock for %s\n", dev->name); + return ret; + } + /* HW and software reset */ + reset_line_deassert_dt(&cfg->aresetn); + reset_line_deassert_dt(&cfg->rst_async); +#endif + cfg->irq_configure(); return 0; } +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rza2_dma) +#define CLOCK_DEFINE(inst) +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3_dma) +#define CLOCK_DEFINE(inst) \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)), \ + .aclk.module = DT_INST_CLOCKS_CELL_BY_NAME(inst, aclk, module), \ + .aclk.domain = DT_INST_CLOCKS_CELL_BY_NAME(inst, aclk, domain), \ + .pclk.module = DT_INST_CLOCKS_CELL_BY_NAME(inst, pclk, module), \ + .pclk.domain = DT_INST_CLOCKS_CELL_BY_NAME(inst, pclk, domain), \ + .aresetn = RESET_DT_SPEC_INST_GET_BY_IDX(inst, 0), \ + .rst_async = RESET_DT_SPEC_INST_GET_BY_IDX(inst, 1), +#endif + +#define DT_IRQ_HAS_CELL_AT_NAME(node_id, name, cell) \ + IS_ENABLED(DT_CAT6(node_id, _IRQ_NAME_, name, _VAL_, cell, _EXISTS)) + #define IRQ_ERR_CONFIGURE(inst, name) \ IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, name, irq), \ DT_INST_IRQ_BY_NAME(inst, name, priority), dma_rza2_err_isr, \ - DEVICE_DT_INST_GET(inst), DT_INST_IRQ_BY_NAME(inst, name, flags)); \ + DEVICE_DT_INST_GET(inst), \ + COND_CODE_1(DT_IRQ_HAS_CELL_AT_NAME(DT_DRV_INST(inst), name, flags), \ + (DT_INST_IRQ_BY_NAME(inst, name, flags)), (0))); \ irq_enable(DT_INST_IRQ_BY_NAME(inst, name, irq)); #define IRQ_DECLARE_ISR(n, inst) \ @@ -1522,7 +2238,8 @@ static int dma_rza2_init(const struct device *dev) #define IRQ_CONFIGURE(n, inst) \ IRQ_CONNECT(DT_INST_IRQ_BY_IDX(inst, n, irq), DT_INST_IRQ_BY_IDX(inst, n, priority), \ dma_rza2_##n##_##inst##_isr, DEVICE_DT_INST_GET(inst), \ - DT_INST_IRQ_BY_IDX(inst, n, flags)); \ + COND_CODE_1(DT_IRQ_HAS_CELL_AT_IDX(DT_DRV_INST(inst), n, flags), \ + (DT_INST_IRQ_BY_IDX(inst, n, flags)), (0))); \ irq_enable(DT_INST_IRQ_BY_IDX(inst, n, irq)); #define CONFIGURE_ALL_IRQS(inst, n) LISTIFY(n, IRQ_CONFIGURE, (), inst) @@ -1561,11 +2278,11 @@ static int dma_rza2_init(const struct device *dev) .irq_configure = dma_rza2_##inst##_irq_configure, \ .pcfg = RZ_PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ .addr_alignment = DMA_BUF_ADDR_ALIGNMENT(DT_DRV_INST(inst)), \ - }; \ + CLOCK_DEFINE(inst)}; \ \ - static __aligned(DMA_BUF_ADDR_ALIGNMENT(DT_DRV_INST(inst))) \ - struct rza2_dma_link_descriptor descr_##inst##_pool[DMA_RZA2_POOL_SIZE] \ - __attribute__((__section__(".nocache.dma"))) = {0}; \ + static __aligned( \ + DMA_BUF_ADDR_ALIGNMENT(DT_DRV_INST(inst))) struct rza2_dma_link_descriptor \ + descr_##inst##_pool[DMA_RZA2_POOL_SIZE] __nocache = {0}; \ \ static struct dma_rza2_channel \ dma_rza2_##inst##_channels[DT_INST_PROP(inst, dma_channels)]; \ diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 3d8872443c5c63..acc8dfd357798a 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -52,6 +52,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_EOS_S3 gpio_eos_s3.c) zephyr_library_sources_ifdef(CONFIG_GPIO_RCAR gpio_rcar.c) zephyr_library_sources_ifdef(CONFIG_GPIO_RZA2 gpio_rza2.c) zephyr_library_sources_ifdef(CONFIG_GPIO_RZA2 gpio_rza2_port.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_RZG3S gpio_rzg3s.c) zephyr_library_sources_ifdef(CONFIG_GPIO_CY8C95XX gpio_cy8c95xx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_SNPS_CREG gpio_creg_gpio.c) zephyr_library_sources_ifdef(CONFIG_GPIO_STMPE1600 gpio_stmpe1600.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 133f336c8d1a27..16697ee42592fe 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -152,6 +152,7 @@ source "drivers/gpio/Kconfig.eos_s3" source "drivers/gpio/Kconfig.rcar" source "drivers/gpio/Kconfig.rza2" +source "drivers/gpio/Kconfig.rzg3s" source "drivers/gpio/Kconfig.cy8c95xx" diff --git a/drivers/gpio/Kconfig.rzg3s b/drivers/gpio/Kconfig.rzg3s new file mode 100644 index 00000000000000..1c87ad29a10e43 --- /dev/null +++ b/drivers/gpio/Kconfig.rzg3s @@ -0,0 +1,28 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_RZG3S + bool "Renesas RZ G3S GPIO controller" + default y + depends on DT_HAS_RENESAS_R9A08G045_GPIO_ENABLED + depends on PINCTRL + help + Enable Renesas RZ G3S GPIO controller driver. + +if GPIO_RZG3S + +config GPIO_RZG3S_INIT_PRIORITY + int "Renesas RZ G3S GPIO controller init priority" + default 40 + help + The RZ G3S GPIO controller driver initialization priority. The priority should be lower + than PINCTRL_RZG3S_INIT_PRIORITY device. + +config GPIO_RZG3S_PORT_INIT_PRIORITY + int "Renesas RZ G3S GPIO controller init priority" + default 41 + help + The RZ G3S GPIO port driver initialization priority. The priority should be lower + than GPIO_RZG3S_INIT_PRIORITY device. + +endif #GPIO_RZG3S diff --git a/drivers/gpio/gpio_rzg3s.c b/drivers/gpio/gpio_rzg3s.c new file mode 100644 index 00000000000000..11de9c95f4722a --- /dev/null +++ b/drivers/gpio/gpio_rzg3s.c @@ -0,0 +1,753 @@ +/* + * Copyright 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_r9a08g045_gpio + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(rzg3s_gpio, CONFIG_GPIO_LOG_LEVEL); + +#define LOG_DEV_ERR(dev, format, ...) LOG_ERR("%s:" #format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_WRN(dev, format, ...) LOG_WRN("%s:" #format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_INF(dev, format, ...) LOG_INF("%s:" #format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_DBG(dev, format, ...) LOG_DBG("%s:" #format, (dev)->name, ##__VA_ARGS__) + +#define R_P(port) (0x0000 + (port)) /* Port Register, Output Data 8-bit */ +#define R_PIN(port) (0x0800 + (port)) /* Port Input Register, Input Data 8-bit */ +#define R_PM(n) (0x0100 + (n) * 2) /* Port Mode 16-bit */ +#define R_ISEL(n) (0x2C00 + (n) * 8) /* Interrupt Enable Control 32-bit */ + +/* R_PM Port Mode Register */ +#define R_PM_MODE_MASK GENMASK(1, 0) +#define R_PM_MODE_VAL(pin, val) (((val) & R_PM_MODE_MASK) << ((pin) << 1)) + +#define R_PM_MODE_HI_Z 0x0 +#define R_PM_MODE_IN BIT(0) +#define R_PM_MODE_OUT BIT(1) +#define R_PM_MODE_OUT_IN (R_PM_MODE_IN | R_PM_MODE_OUT) + +#define R_ISEL_MODE_MASK BIT(1) +#define R_ISEL_MODE_VAL(pin, val) (((val) & R_ISEL_MODE_MASK) << ((pin) * 8)) + +#define RZG3S_PORT_NUM 19 + +#define RZG3S_GPIO_VALID_FLAGS \ + (GPIO_INPUT | GPIO_OUTPUT | GPIO_OUTPUT_INIT_HIGH | GPIO_OUTPUT_INIT_LOW | GPIO_PULL_UP | \ + GPIO_PULL_DOWN) + +/* + * num_pins: indicates number of pins in the port + * reg_ofs: the register index + * irq_ofs: GPIO irq offset within TINT + */ +#define RZG3S_GPIO_PORT_DEF(num_pins, reg_ofs, irq_ofs) \ + (((num_pins) << 16) | (reg_ofs) | ((irq_ofs) << 24)) +#define RZG3S_GPIO_PORT_GET_PINCNT(p) (((p) & GENMASK(23, 16)) >> 16) +#define RZG3S_GPIO_PORT_GET_REG(p) (((p) & GENMASK(15, 0))) +#define RZG3S_GPIO_PORT_GET_IRQ_OFS(p) (((p) & GENMASK(31, 24)) >> 24) + +static const uint32_t rzg3s_gpio_ports[RZG3S_PORT_NUM] = { + RZG3S_GPIO_PORT_DEF(4, 0x20, 0), + RZG3S_GPIO_PORT_DEF(5, 0x30, 4), + RZG3S_GPIO_PORT_DEF(4, 0x31, 9), + RZG3S_GPIO_PORT_DEF(4, 0x32, 13), + RZG3S_GPIO_PORT_DEF(6, 0x33, 17), + RZG3S_GPIO_PORT_DEF(5, 0x21, 23), + RZG3S_GPIO_PORT_DEF(5, 0x22, 28), + RZG3S_GPIO_PORT_DEF(5, 0x34, 33), + RZG3S_GPIO_PORT_DEF(5, 0x35, 38), + RZG3S_GPIO_PORT_DEF(4, 0x36, 43), + RZG3S_GPIO_PORT_DEF(5, 0x37, 47), + RZG3S_GPIO_PORT_DEF(4, 0x23, 52), + RZG3S_GPIO_PORT_DEF(2, 0x24, 56), + RZG3S_GPIO_PORT_DEF(5, 0x25, 58), + RZG3S_GPIO_PORT_DEF(3, 0x26, 63), + RZG3S_GPIO_PORT_DEF(4, 0x27, 66), + RZG3S_GPIO_PORT_DEF(2, 0x28, 70), + RZG3S_GPIO_PORT_DEF(4, 0x29, 72), + RZG3S_GPIO_PORT_DEF(6, 0x2A, 76), +}; + +/* TINT */ +#define R_TINT_TSCR 0x0 +#define R_TINT_TITSR(irq) (0x4 + 0x4 * ((irq) / 16)) +#define R_TINT_TSSR(irq) (0x10 + 0x4 * ((irq) / 4)) + +/* TINT Interrupt Type Selection Register */ +#define R_TITSR_TITSEL_MASK GENMASK(1, 0) +#define R_TITSR_TITSEL_VAL(irq, val) (((val) & R_TITSR_TITSEL_MASK) << (((irq) % 16) * 2)) + +#define R_TITSR_TITSEL_EDGE_RISING 0x0 +#define R_TITSR_TITSEL_EDGE_FALLING 0x1 +#define R_TITSR_TITSEL_LEVEL_HIGH 0x2 +#define R_TITSR_TITSEL_LEVEL_LOW 0x3 + +/* TINT Source Selection Register */ +#define R_TSSR_TSSEL_MASK GENMASK(6, 0) +#define R_TSSR_TSSEL_VAL(irq, val) (((val) & R_TSSR_TSSEL_MASK) << (((irq) % 4) * 8)) +#define R_TSSR_TIEN_MASK BIT(7) +#define R_TSSR_TIEN_VAL(irq, val) (((val) & R_TSSR_TIEN_MASK) << (((irq) % 4) * 8)) + +struct rzg3s_gpio_port_config { + /* gpio_driver_config needs to be first */ + struct gpio_driver_config common; + uint8_t port; + uint8_t ngpios; + const struct device *pinctrl_dev; + const struct device *ctrl_dev; +}; + +struct rzg3s_gpio_port_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; + /* port ISR callback routine address */ + sys_slist_t callbacks; + uint8_t mask_dir_out; + uint8_t mask_dir_in; + uint8_t mask_irq_en; + + struct k_spinlock lock; +}; + +#define TINT_NUM_IRQ 32 + +struct rzg3s_gpio_ctrl_config { + DEVICE_MMIO_NAMED_ROM(tint); + const struct device *pinctrl_dev; + unsigned int parent_irqs[TINT_NUM_IRQ]; + void (*irq_config)(void); +}; + +struct rzg3s_gpio_tint_irq_data { + const struct device *port_dev; + uint8_t pin; /* pin within port */ + uint8_t pin_id; /* global pin number 0..81 */ +}; + +struct rzg3s_gpio_ctrl_data { + DEVICE_MMIO_NAMED_ROM(tint); + mm_reg_t gpio_addr; + struct rzg3s_gpio_tint_irq_data tints[TINT_NUM_IRQ]; + uint32_t free_irqs_mask; + uint32_t edge_irqs_mask; + struct k_spinlock tint_lock; +} rza2_gpio_data; + +#define DEV_DATA(dev) ((struct rzg3s_gpio_ctrl_data *)((dev)->data)) +#define DEV_CFG(dev) ((struct rzg3s_gpio_ctrl_config *)((dev)->config)) + +static int rzg3s_gpio_tint_free(const struct device *dev, const struct device *port_dev, + uint8_t pin); + +static int rzg3s_gpio_tint_allocen(const struct device *dev, const struct device *port_dev, + uint8_t pin, uint8_t pin_id, uint8_t irq_type); + +static uint16_t rzg3s_pinctrl_port_get_reg(uint8_t port) +{ + return RZG3S_GPIO_PORT_GET_REG(rzg3s_gpio_ports[port]); +} + +static uint16_t __maybe_unused rzg3s_pinctrl_port_get_pinnum(uint8_t port) +{ + return RZG3S_GPIO_PORT_GET_PINCNT(rzg3s_gpio_ports[port]); +} + +static uint8_t rzg3s_gpio_in_get(mm_reg_t base, uint8_t port) +{ + uint16_t port_reg = rzg3s_pinctrl_port_get_reg(port); + + return sys_read8(base + R_PIN(port_reg)); +} + +static uint8_t rzg3s_gpio_out_get(mm_reg_t base, uint8_t port) +{ + uint16_t port_reg = rzg3s_pinctrl_port_get_reg(port); + + return sys_read8(base + R_P(port_reg)); +} + +static void rzg3s_gpio_out_set(mm_reg_t base, uint8_t port, uint8_t value) +{ + uint16_t port_reg = rzg3s_pinctrl_port_get_reg(port); + + sys_write8(value, base + R_P(port_reg)); +} + +static int rzg3s_gpio_port_get_raw(const struct device *dev, gpio_port_value_t *value) +{ + const struct rzg3s_gpio_port_config *cfg = dev->config; + mm_reg_t base = DEVICE_MMIO_GET(cfg->pinctrl_dev); + struct rzg3s_gpio_port_data *data = dev->data; + + *value = rzg3s_gpio_in_get(base, cfg->port) & data->mask_dir_in; + + return 0; +} + +static int rzg3s_gpio_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + const struct rzg3s_gpio_port_config *cfg = dev->config; + mm_reg_t base = DEVICE_MMIO_GET(cfg->pinctrl_dev); + struct rzg3s_gpio_port_data *data = dev->data; + k_spinlock_key_t key; + uint8_t reg8; + + key = k_spin_lock(&data->lock); + reg8 = rzg3s_gpio_out_get(base, cfg->port); + reg8 &= ~mask; + reg8 |= ((value & data->mask_dir_out) & mask); + rzg3s_gpio_out_set(base, cfg->port, reg8); + k_spin_unlock(&data->lock, key); + return 0; +} + +static int rzg3s_gpio_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct rzg3s_gpio_port_config *cfg = dev->config; + mm_reg_t base = DEVICE_MMIO_GET(cfg->pinctrl_dev); + struct rzg3s_gpio_port_data *data = dev->data; + k_spinlock_key_t key; + uint8_t reg8; + + key = k_spin_lock(&data->lock); + reg8 = rzg3s_gpio_out_get(base, cfg->port); + reg8 |= pins & data->mask_dir_out; + rzg3s_gpio_out_set(base, cfg->port, reg8); + k_spin_unlock(&data->lock, key); + return 0; +} + +static int rzg3s_gpio_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct rzg3s_gpio_port_config *cfg = dev->config; + mm_reg_t base = DEVICE_MMIO_GET(cfg->pinctrl_dev); + struct rzg3s_gpio_port_data *data = dev->data; + k_spinlock_key_t key; + uint8_t reg8; + + key = k_spin_lock(&data->lock); + reg8 = rzg3s_gpio_out_get(base, cfg->port); + reg8 &= ~(pins & data->mask_dir_out); + rzg3s_gpio_out_set(base, cfg->port, reg8); + k_spin_unlock(&data->lock, key); + return 0; +} + +static int rzg3s_gpio_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +{ + const struct rzg3s_gpio_port_config *cfg = dev->config; + mm_reg_t base = DEVICE_MMIO_GET(cfg->pinctrl_dev); + struct rzg3s_gpio_port_data *data = dev->data; + k_spinlock_key_t key; + uint8_t reg8; + + key = k_spin_lock(&data->lock); + reg8 = rzg3s_gpio_out_get(base, cfg->port); + reg8 ^= (pins & data->mask_dir_out); + rzg3s_gpio_out_set(base, cfg->port, reg8); + k_spin_unlock(&data->lock, key); + return 0; +} + +static void rzg3s_gpio_port_set_dir(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct rzg3s_gpio_port_config *cfg = dev->config; + uint16_t port_reg = rzg3s_pinctrl_port_get_reg(cfg->port); + mm_reg_t base = DEVICE_MMIO_GET(cfg->pinctrl_dev); + uint16_t reg16; + + reg16 = sys_read16(base + R_PM(port_reg)); + + reg16 &= ~R_PM_MODE_VAL(pin, R_PM_MODE_MASK); + if ((flags & (GPIO_INPUT | GPIO_OUTPUT)) == (GPIO_INPUT | GPIO_OUTPUT)) { + reg16 |= R_PM_MODE_VAL(pin, R_PM_MODE_OUT_IN); + } else if (flags & GPIO_INPUT) { + reg16 |= R_PM_MODE_VAL(pin, R_PM_MODE_IN); + } else if (flags & GPIO_OUTPUT) { + reg16 |= R_PM_MODE_VAL(pin, R_PM_MODE_OUT); + } + + sys_write16(reg16, base + R_PM(port_reg)); +} + +static int rzg3s_gpio_port_pin_to_gpio(uint8_t port, gpio_pin_t pin, gpio_flags_t flags) +{ + pinctrl_soc_pin_t pin_cfg = { 0 }; + + pin_cfg.type = PINCTRL_RZG3S_TYPE_PINMUX; + pin_cfg.pinmux.port = port; + pin_cfg.pinmux.pin = pin; + pin_cfg.pinmux.func = PINCTRL_RZG3S_FUNC_GPIO; + + if (flags & GPIO_PULL_DOWN) { + pin_cfg.pinmux.pull_down = 1; + } else if (flags & GPIO_PULL_UP) { + pin_cfg.pinmux.pull_up = 1; + } + + if (flags & RZG3S_GPIO_DRIVE_IOLH_PRESENT) { + pin_cfg.pinmux.drive_strength = 1; + pin_cfg.pinmux.drive_strength_microamp = RZG3S_GPIO_DRIVE_IOLH_GET(flags); + } + + if (flags & RZG3S_GPIO_FILTER_PRESENT) { + pin_cfg.pinmux.filonoff = 1; + pin_cfg.pinmux.filnum = RZG3S_GPIO_FILTER_NUM_GET(flags); + pin_cfg.pinmux.filclksel = RZG3S_GPIO_FILTER_CLK_GET(flags); + } + + return pinctrl_configure_pins(&pin_cfg, 1, PINCTRL_REG_NONE); +} + +static int rzg3s_gpio_port_pin_cfg(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct rzg3s_gpio_port_config *cfg = dev->config; + struct rzg3s_gpio_port_data *data = dev->data; + k_spinlock_key_t key; + int ret = 0; + + if (pin >= cfg->ngpios) { + LOG_DEV_ERR(dev, "port:%u provided pin %d > %d (ngpios)", + cfg->port, pin, cfg->ngpios); + return -EINVAL; + } + + if (!(flags ^ (RZG3S_GPIO_VALID_FLAGS))) { + return -ENOTSUP; + } + + key = k_spin_lock(&data->lock); + data->mask_dir_in &= ~BIT(pin); + data->mask_dir_out &= ~BIT(pin); + if (flags & GPIO_INPUT) { + data->mask_dir_in |= BIT(pin); + } + if (flags & GPIO_OUTPUT) { + data->mask_dir_out = BIT(pin); + } + + ret = rzg3s_gpio_port_pin_to_gpio(cfg->port, pin, flags); + if (ret) { + k_spin_unlock(&data->lock, key); + LOG_DEV_ERR(dev, "port:%u pin %d pincfg failed %d", cfg->port, pin, ret); + return ret; + } + rzg3s_gpio_port_set_dir(dev, pin, flags); + k_spin_unlock(&data->lock, key); + + if (flags & GPIO_OUTPUT_INIT_HIGH) { + ret = rzg3s_gpio_port_set_bits_raw(dev, BIT(pin)); + } else if (flags & GPIO_OUTPUT_INIT_LOW) { + ret = rzg3s_gpio_port_clear_bits_raw(dev, BIT(pin)); + } + + return ret; +} + +static int rzg3s_gpio_port_manage_callback(const struct device *dev, struct gpio_callback *callback, + bool set) +{ + struct rzg3s_gpio_port_data *data = dev->data; + + return gpio_manage_callback(&data->callbacks, callback, set); +} + +static void rzg3s_gpio_isel_set(const struct device *dev, uint8_t pin, bool on) +{ + const struct rzg3s_gpio_port_config *cfg = dev->config; + uint16_t port_reg = rzg3s_pinctrl_port_get_reg(cfg->port); + mm_reg_t base = DEVICE_MMIO_GET(cfg->pinctrl_dev); + uint8_t isel = 0; + uint32_t reg32; + + if (on) { + isel = BIT(1); + } + + /* handle _L/_H for 32-bit register read/write */ + if (pin >= 4) { + pin -= 4; + port_reg += 4; + } + + reg32 = sys_read32(base + R_ISEL(port_reg)); + reg32 &= ~R_ISEL_MODE_VAL(pin, R_ISEL_MODE_MASK); + reg32 |= R_ISEL_MODE_VAL(pin, isel); + sys_write32(reg32, base + R_ISEL(port_reg)); +} + +static int rzg3s_gpio_pin_irq_cfg(const struct device *dev, gpio_pin_t pin, enum gpio_int_mode mode, + enum gpio_int_trig trig) +{ + const struct rzg3s_gpio_port_config *cfg = dev->config; + struct rzg3s_gpio_port_data *data = dev->data; + k_spinlock_key_t key; + uint8_t irq_type; + uint8_t pin_id; + int ret = 0; + + if (pin >= cfg->ngpios) { + LOG_DEV_ERR(dev, "port:%u provided pin %d > %d (ngpios)", + cfg->port, pin, cfg->ngpios); + return -EINVAL; + } + + if (trig == GPIO_INT_TRIG_BOTH) { + return -ENOTSUP; + } + + pin_id = RZG3S_GPIO_PORT_GET_IRQ_OFS(rzg3s_gpio_ports[cfg->port]) + pin; + + key = k_spin_lock(&data->lock); + + if (mode == GPIO_INT_MODE_DISABLED) { + if (!(data->mask_irq_en & BIT(pin))) { + /* not enabled - just exit */ + goto exit_unlock; + } + rzg3s_gpio_isel_set(dev, pin, false); + ret = rzg3s_gpio_tint_free(cfg->ctrl_dev, dev, pin); + data->mask_irq_en &= ~BIT(pin); + goto exit_unlock; + } + + if (!(data->mask_dir_in & BIT(pin))) { + LOG_DEV_ERR(dev, "port:%u pin:%d not cfg as input", cfg->port, pin); + ret = -EINVAL; + goto exit_unlock; + } + + if (mode == GPIO_INT_MODE_EDGE) { + irq_type = R_TITSR_TITSEL_EDGE_RISING; + if (trig == GPIO_INT_TRIG_LOW) { + irq_type = R_TITSR_TITSEL_EDGE_FALLING; + } + } else { + irq_type = R_TITSR_TITSEL_LEVEL_HIGH; + if (trig == GPIO_INT_TRIG_LOW) { + irq_type = R_TITSR_TITSEL_LEVEL_LOW; + } + } + + rzg3s_gpio_isel_set(dev, pin, true); + ret = rzg3s_gpio_tint_allocen(cfg->ctrl_dev, dev, pin, pin_id, irq_type); + if (ret) { + rzg3s_gpio_isel_set(dev, pin, false); + } else { + data->mask_irq_en |= BIT(pin); + } + +exit_unlock: + k_spin_unlock(&data->lock, key); + return ret; +} + +static const struct gpio_driver_api rzg3s_gpio_port_api = { + .port_get_raw = rzg3s_gpio_port_get_raw, + .port_set_masked_raw = rzg3s_gpio_port_set_masked_raw, + .port_set_bits_raw = rzg3s_gpio_port_set_bits_raw, + .port_clear_bits_raw = rzg3s_gpio_port_clear_bits_raw, + .port_toggle_bits = rzg3s_gpio_port_toggle_bits, + .pin_configure = rzg3s_gpio_port_pin_cfg, + .manage_callback = rzg3s_gpio_port_manage_callback, + .pin_interrupt_configure = rzg3s_gpio_pin_irq_cfg, +}; + +static void rzg3s_gpio_port_isr(const struct device *dev, uint8_t pin) +{ + struct rzg3s_gpio_port_data *data = dev->data; + + gpio_fire_callbacks(&data->callbacks, dev, BIT(pin)); +} + +static int rzg3s_gpio_port_init(const struct device *dev) +{ + const struct rzg3s_gpio_port_config *cfg = dev->config; + + ARG_UNUSED(cfg); + __ASSERT(cfg->port < RZG3S_PORT_NUM, "gpio port%u incorrect, check DT", cfg->port); + __ASSERT(cfg->ngpios == rzg3s_pinctrl_port_get_pinnum(cfg->port), + "gpio port%u incorrect ngpios %u, check DT", cfg->port, cfg->ngpios); + + return 0; +} + +static void rzg3s_gpio_tint_free_raw(const struct device *dev, uint8_t tirq) +{ + uint16_t port_reg = R_TINT_TSSR(tirq); + uint32_t reg32; + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); + reg32 &= ~R_TSSR_TSSEL_VAL(tirq, R_TSSR_TSSEL_MASK); + reg32 &= ~R_TSSR_TIEN_VAL(tirq, R_TSSR_TIEN_MASK); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); + + /* clean status */ + port_reg = R_TINT_TSCR; + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); + reg32 &= ~BIT(tirq); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); +} + +static void rzg3s_gpio_tint_allocen_raw(const struct device *dev, uint8_t tirq, uint8_t pin_id) +{ + struct rzg3s_gpio_ctrl_data *data = dev->data; + uint16_t port_reg = R_TINT_TSSR(tirq); + uint32_t reg32; + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); + reg32 &= ~R_TSSR_TSSEL_VAL(tirq, R_TSSR_TSSEL_MASK); + reg32 |= R_TSSR_TSSEL_VAL(tirq, pin_id); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); + + k_busy_wait(100); + + /* clean status for edge */ + if (data->edge_irqs_mask & BIT(tirq)) { + port_reg = R_TINT_TSCR; + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); + if (reg32 & BIT(tirq)) { + reg32 &= ~BIT(tirq); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); + } + } + + port_reg = R_TINT_TSSR(tirq); + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); + reg32 |= R_TSSR_TIEN_VAL(tirq, R_TSSR_TIEN_MASK); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); +} + +static void rzg3s_gpio_tint_set_type_raw(const struct device *dev, uint8_t tirq, uint8_t irq_type) +{ + struct rzg3s_gpio_ctrl_data *data = dev->data; + uint16_t port_reg = R_TINT_TITSR(tirq); + uint32_t reg32; + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); + reg32 &= ~R_TITSR_TITSEL_VAL(tirq, R_TITSR_TITSEL_MASK); + reg32 |= R_TITSR_TITSEL_VAL(tirq, irq_type); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); + + if (irq_type == R_TITSR_TITSEL_EDGE_RISING || + irq_type == R_TITSR_TITSEL_EDGE_FALLING) { + data->edge_irqs_mask |= BIT(tirq); + } +} + +static uint8_t rzg3s_gpio_tint_find(const struct device *dev, const struct device *port_dev, + uint8_t pin) +{ + struct rzg3s_gpio_ctrl_data *data = dev->data; + uint8_t i; + + for (i = 0; i < TINT_NUM_IRQ; i++) { + if (data->tints[i].port_dev == port_dev && data->tints[i].pin == pin) { + break; + } + } + + return i; +} + +static int rzg3s_gpio_tint_free(const struct device *dev, const struct device *port_dev, + uint8_t pin) +{ + const struct rzg3s_gpio_ctrl_config *cfg = dev->config; + struct rzg3s_gpio_ctrl_data *data = dev->data; + k_spinlock_key_t key; + uint8_t tirq; + + key = k_spin_lock(&data->tint_lock); + + tirq = rzg3s_gpio_tint_find(dev, port_dev, pin); + if (tirq == TINT_NUM_IRQ) { + LOG_DEV_DBG(dev, "tint: %s:pin:%u not enabled", port_dev->name, pin); + k_spin_unlock(&data->tint_lock, key); + return -ENOENT; + } + + irq_disable(cfg->parent_irqs[tirq]); + + rzg3s_gpio_tint_free_raw(dev, tirq); + data->tints[tirq].port_dev = NULL; + data->tints[tirq].pin = UINT8_MAX; + data->tints[tirq].pin_id = UINT8_MAX; + data->free_irqs_mask |= BIT(tirq); + data->edge_irqs_mask &= ~BIT(tirq); + + k_spin_unlock(&data->tint_lock, key); + return 0; +} + +static int rzg3s_gpio_tint_allocen(const struct device *dev, const struct device *port_dev, + uint8_t pin, uint8_t pin_id, uint8_t irq_type) +{ + const struct rzg3s_gpio_ctrl_config *cfg = dev->config; + struct rzg3s_gpio_ctrl_data *data = dev->data; + k_spinlock_key_t key; + uint8_t tirq; + int ret = 0; + + key = k_spin_lock(&data->tint_lock); + + tirq = rzg3s_gpio_tint_find(dev, port_dev, pin); + if (tirq != TINT_NUM_IRQ) { + LOG_DEV_DBG(dev, "tint: %s:pin:%u already in use", port_dev->name, pin); + ret = -ENOENT; + goto exit_unlock; + } + + tirq = find_lsb_set(data->free_irqs_mask); + if (!tirq) { + LOG_DEV_DBG(dev, "tint: no free irqs"); + ret = -EBUSY; + goto exit_unlock; + + } + tirq--; + + rzg3s_gpio_tint_set_type_raw(dev, tirq, irq_type); + rzg3s_gpio_tint_allocen_raw(dev, tirq, pin_id); + data->tints[tirq].port_dev = port_dev; + data->tints[tirq].pin = pin; + data->tints[tirq].pin_id = pin_id; + data->free_irqs_mask &= ~BIT(tirq); + irq_enable(cfg->parent_irqs[tirq]); + +exit_unlock: + k_spin_unlock(&data->tint_lock, key); + return ret; +} + +static void rzg3s_gpio_tint_isr(uint32_t p_irq, void *param) +{ + const struct rzg3s_gpio_ctrl_config *cfg; + struct rzg3s_gpio_ctrl_data *data; + const struct device *dev = param; + uint16_t port_reg = R_TINT_TSCR; + uint32_t reg32; + uint8_t tirq; + + cfg = dev->config; + data = dev->data; + tirq = p_irq - cfg->parent_irqs[0]; + __ASSERT_NO_MSG(tirq < TINT_NUM_IRQ); + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); + + if (!(reg32 & BIT(tirq))) { + /* For unknown reasons, the spurious irq generated with TSTATn == 0 + * when TINT IRQ configured and enabled for the first time. + * Same is not seen for further IRQ events. + */ + LOG_DEV_DBG(dev, "tint:%u spurious irq, status 0", tirq); + return; + } + + if (!data->tints[tirq].port_dev) { + k_spinlock_key_t key; + + /* spurious irq disable it */ + key = k_spin_lock(&data->tint_lock); + rzg3s_gpio_tint_free_raw(dev, tirq); + k_spin_unlock(&data->tint_lock, key); + LOG_DEV_ERR(dev, "tint:%u spurious irq, disable it", tirq); + return; + } + + if (data->edge_irqs_mask & BIT(tirq)) { + /* clean status for Edge irq types */ + reg32 &= ~BIT(tirq); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, tint) + port_reg); + } + + rzg3s_gpio_port_isr(data->tints[tirq].port_dev, data->tints[tirq].pin); +} + +static int rzg3s_gpio_ctrl_init(const struct device *dev) +{ + const struct rzg3s_gpio_ctrl_config *cfg = dev->config; + struct rzg3s_gpio_ctrl_data *data = dev->data; + + /* Get IO addr from parent */ + data->gpio_addr = DEVICE_MMIO_GET(cfg->pinctrl_dev); + data->free_irqs_mask = UINT32_MAX; + DEVICE_MMIO_NAMED_MAP(dev, tint, K_MEM_CACHE_NONE); + + cfg->irq_config(); + return 0; +} + +#define GPIO_RZG3S_PORT_DATA_NAME(node_id) _CONCAT(rzg3s_gpio_port_data, DT_DEP_ORD(node_id)) +#define GPIO_RZG3S_PORT_CFG_NAME(node_id) _CONCAT(rzg3s_gpio_port_cfg, DT_DEP_ORD(node_id)) + +#define GPIO_RZG3S_PORT_INIT(p_node) \ + static const struct rzg3s_gpio_port_config GPIO_RZG3S_PORT_CFG_NAME(p_node) = { \ + .common = \ + { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_NODE(p_node), \ + }, \ + .port = DT_REG_ADDR(p_node), \ + .ngpios = DT_PROP(p_node, ngpios), \ + .pinctrl_dev = DEVICE_DT_GET(DT_PARENT(DT_PARENT(p_node))), \ + .ctrl_dev = DEVICE_DT_GET(DT_PARENT(p_node)), \ + }; \ + static struct rzg3s_gpio_port_data GPIO_RZG3S_PORT_DATA_NAME(p_node) = {}; \ + \ + DEVICE_DT_DEFINE(p_node, rzg3s_gpio_port_init, NULL, &GPIO_RZG3S_PORT_DATA_NAME(p_node), \ + &GPIO_RZG3S_PORT_CFG_NAME(p_node), POST_KERNEL, \ + CONFIG_GPIO_RZG3S_PORT_INIT_PRIORITY, &rzg3s_gpio_port_api); + +#define GPIO_RZG3S_IRQ_DECLARE_ISR(n, inst) \ + static void rzg3s_gpio_tint_##n##_isr(void *param) \ + { \ + rzg3s_gpio_tint_isr(DT_INST_IRQ_BY_IDX(inst, n, irq), param); \ + } +#define GPIO_RZG3S_DECLARE_ALL_ISRS(inst, n) LISTIFY(n, GPIO_RZG3S_IRQ_DECLARE_ISR, (), inst) + +#define GPIO_RZG3S_IRQ_CONFIGURE(n, inst) \ + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(inst, n, irq), DT_INST_IRQ_BY_IDX(inst, n, priority), \ + rzg3s_gpio_tint_##n##_isr, DEVICE_DT_INST_GET(inst), 0); + +#define GPIO_RZG3S_IRQ_CONFIG_FUNC(inst) \ + static void rzg3s_gpio_tint_cfg_func_##inst(void) \ + { \ + LISTIFY(DT_NUM_IRQS(DT_DRV_INST(inst)), GPIO_RZG3S_IRQ_CONFIGURE, (), inst) \ + } + +#define GPIO_RZG3S_FILL_ONE_P_IRQ(n, inst) DT_INST_IRQ_BY_IDX(inst, n, irq), +#define GPIO_RZG3S_FILL_ALL_P_IRQS(inst, n) LISTIFY(n, GPIO_RZG3S_FILL_ONE_P_IRQ, (), inst) + +#define GPIO_RZG3S_CTRL_INIT(inst) \ + GPIO_RZG3S_DECLARE_ALL_ISRS(inst, DT_NUM_IRQS(DT_DRV_INST(inst))) \ + GPIO_RZG3S_IRQ_CONFIG_FUNC(inst) \ + static const struct rzg3s_gpio_ctrl_config rzg3s_gpio_ctrl_cfg##inst = { \ + DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(tint, DT_DRV_INST(inst)), \ + .pinctrl_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + .parent_irqs = {GPIO_RZG3S_FILL_ALL_P_IRQS(inst, DT_NUM_IRQS(DT_DRV_INST(inst)))}, \ + .irq_config = rzg3s_gpio_tint_cfg_func_##inst, \ + }; \ + static struct rzg3s_gpio_ctrl_data rzg3s_gpio_ctrl_data##inst = {}; \ + \ + DEVICE_DT_INST_DEFINE(inst, rzg3s_gpio_ctrl_init, NULL, &rzg3s_gpio_ctrl_data##inst, \ + &rzg3s_gpio_ctrl_cfg##inst, POST_KERNEL, \ + CONFIG_GPIO_RZG3S_INIT_PRIORITY, NULL); \ + DT_INST_FOREACH_CHILD_STATUS_OKAY(inst, GPIO_RZG3S_PORT_INIT); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_RZG3S_CTRL_INIT) diff --git a/drivers/i2c/Kconfig.renesas b/drivers/i2c/Kconfig.renesas index 435037d8103fb9..d32ae560182269 100644 --- a/drivers/i2c/Kconfig.renesas +++ b/drivers/i2c/Kconfig.renesas @@ -7,9 +7,9 @@ config I2C_RIIC bool "Renesas I2C Driver for RZ/A2M" default y - depends on DT_HAS_RENESAS_RIIC_ENABLED + depends on DT_HAS_RENESAS_RIIC_ENABLED || DT_HAS_RENESAS_RZG_RIIC_ENABLED help - Enable Renesas I2C Driver (RIIC) for RZ/A2M. + Enable Renesas I2C Driver (RIIC) for RZ/A2M and RZ/G3S. config I2C_RIIC_DMA_DRIVEN bool "DMA support for RIIC I2C devices" diff --git a/drivers/i2c/i2c_riic.c b/drivers/i2c/i2c_riic.c index 28d90274ee9f6f..534517aaead2fa 100644 --- a/drivers/i2c/i2c_riic.c +++ b/drivers/i2c/i2c_riic.c @@ -4,8 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT renesas_riic - #include #include #include @@ -13,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -29,11 +28,23 @@ LOG_MODULE_REGISTER(riic); #define NUM_SLAVES 3 #define NO_ACTIVE_SLAVE (-1) +#define DMA_READ_THRESHOLD 6 +#define DMA_READ_MANUAL 2 + +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_riic) +#define DT_DRV_COMPAT renesas_riic +#else +#define DT_DRV_COMPAT renesas_rzg_riic +#endif + struct riic_config { DEVICE_MMIO_ROM; /* Must be first */ const struct device *clock_dev; struct renesas_cpg_clk mod_clk; struct renesas_cpg_clk bus_clk; +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg_riic) + struct reset_dt_spec reset; +#endif const struct pinctrl_dev_config *pcfg; void (*init_irq_func)(const struct device *dev); uint32_t bitrate; @@ -71,25 +82,6 @@ struct riic_data { #endif }; -/* Registers */ -#define RIIC_CR1 0x00 /* I²C Bus Control Register 1 */ -#define RIIC_CR2 0x04 /* I²C Bus Control Register 2 */ -#define RIIC_MR1 0x08 /* I²C Bus Mode Register 1 */ -#define RIIC_MR2 0x0c /* I²C Bus Mode Register 2 */ -#define RIIC_MR3 0x10 /* I²C Bus Mode Register 3 */ -#define RIIC_FER 0x14 /* I²C Bus Function Enable Register */ -#define RIIC_SER 0x18 /* I²C Bus Status Enable Register */ -#define RIIC_IER 0x1c /* I²C Bus Interrupt Enable Register */ -#define RIIC_SR1 0x20 /* I²C Bus Status Register 1 */ -#define RIIC_SR2 0x24 /* I²C Bus Status Register 2 */ -#define RIIC_SAR0 0x28 /* I²C Slave Address Register 0 */ -#define RIIC_SAR1 0x2c /* I²C Slave Address Register 1 */ -#define RIIC_SAR2 0x30 /* I²C Slave Address Register 2 */ -#define RIIC_BRL 0x34 /* I²C Bus Bit Rate Low-Level Register */ -#define RIIC_BRH 0x38 /* I²C Bus Bit Rate High-Level Register */ -#define RIIC_DRT 0x3c /* I²C Bus Transmit Data Register */ -#define RIIC_DRR 0x40 /* I²C Bus Receive Data Register */ - #define RIIC_CR1_ICE BIT(7) /* Bus Interface Enable */ #define RIIC_CR1_IICRST BIT(6) /* Bus Interface Internal Reset */ #define RIIC_CR1_CLO BIT(5) /* Extra SCL Clock Cycle Output */ @@ -106,8 +98,9 @@ struct riic_data { #define RIIC_CR2_RS BIT(2) /* Restart Condition Issuance Request */ #define RIIC_CR2_ST BIT(1) /* Start Condition Issuance Request */ +#define RIIC_MR1_MTWP BIT(7) /* Write Protect to the MST and TRS bits in ICCR2 */ #define RIIC_MR1_BCWP BIT(3) /* BC Write Protect */ -#define RIIC_MR1_CKS_MASK 0x70 +#define RIIC_MR1_CKS_MASK GENMASK(6, 4) #define RIIC_MR1_CKS(x) ((((x) << 4) & RIIC_MR1_CKS_MASK) | RIIC_MR1_BCWP) #define RIIC_MR2_DLCS BIT(7) /* SDA Output Delay Clock Source Selection */ @@ -178,21 +171,67 @@ struct riic_data { #define TRANSFER_TIMEOUT_MS 10 /* Timeout for @riic_data::transfer_mtx */ -static void riic_write(const struct device *dev, uint32_t offs, uint32_t value) +/* Registers */ +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_riic) +#define RIIC_CR1 0x00 +#define RIIC_CR2 0x04 +#define RIIC_MR1 0x08 +#define RIIC_MR2 0x0c +#define RIIC_MR3 0x10 +#define RIIC_FER 0x14 +#define RIIC_SER 0x18 +#define RIIC_IER 0x1c +#define RIIC_SR1 0x20 +#define RIIC_SR2 0x24 +#define RIIC_SAR0 0x28 +#define RIIC_SAR1 0x2c +#define RIIC_SAR2 0x30 +#define RIIC_BRL 0x34 +#define RIIC_BRH 0x38 +#define RIIC_DRT 0x3c +#define RIIC_DRR 0x40 +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg_riic) +#define RIIC_CR1 0x00 +#define RIIC_CR2 0x01 +#define RIIC_MR1 0x02 +#define RIIC_MR2 0x03 +#define RIIC_MR3 0x04 +#define RIIC_FER 0x05 +#define RIIC_SER 0x06 +#define RIIC_IER 0x07 +#define RIIC_SR1 0x08 +#define RIIC_SR2 0x09 +#define RIIC_SAR0 0x0a +#define RIIC_SAR1 0x0c +#define RIIC_SAR2 0x0e +#define RIIC_BRL 0x10 +#define RIIC_BRH 0x11 +#define RIIC_DRT 0x12 +#define RIIC_DRR 0x13 +#endif + +static void riic_write8(const struct device *dev, uint32_t offs, uint8_t value) { - sys_write32(value, DEVICE_MMIO_GET(dev) + offs); + sys_write8(value, DEVICE_MMIO_GET(dev) + offs); } -static uint32_t riic_read(const struct device *dev, uint32_t offs) +static uint8_t riic_read8(const struct device *dev, uint32_t offs) { - return sys_read32(DEVICE_MMIO_GET(dev) + offs); + return sys_read8(DEVICE_MMIO_GET(dev) + offs); } +#if defined(CONFIG_I2C_TARGET) +static void riic_write16(const struct device *dev, uint32_t offs, uint16_t value) +{ + sys_write16(value, DEVICE_MMIO_GET(dev) + offs); +} +#endif + static int riic_wait_for_clear(const struct device *dev, uint32_t offs, uint16_t mask) { uint32_t timeout = 0; - while ((riic_read(dev, offs) & mask) && (timeout < 10)) { + while ((riic_read8(dev, offs) & mask) && (timeout < 10)) { k_busy_wait(USEC_PER_MSEC); timeout++; } @@ -207,7 +246,7 @@ static int riic_wait_for_set(const struct device *dev, uint32_t offs, uint16_t m { uint32_t timeout = 0; - while (!(riic_read(dev, offs) & mask) && (timeout < 10)) { + while (!(riic_read8(dev, offs) & mask) && (timeout < 10)) { k_busy_wait(USEC_PER_MSEC); timeout++; } @@ -221,7 +260,7 @@ static int riic_wait_for_set(const struct device *dev, uint32_t offs, uint16_t m static inline void riic_clear_set_bit(const struct device *dev, uint32_t offs, uint16_t clear, uint16_t set) { - riic_write(dev, offs, (riic_read(dev, offs) & ~clear) | set); + riic_write8(dev, offs, (riic_read8(dev, offs) & ~clear) | set); } static int riic_wait_for_state(const struct device *dev, uint8_t mask, bool forever) @@ -232,7 +271,7 @@ static int riic_wait_for_state(const struct device *dev, uint8_t mask, bool fore uint16_t timeout = 0; data->interrupt_mask = mask; - data->status_bits = riic_read(dev, RIIC_SR2); + data->status_bits = riic_read8(dev, RIIC_SR2); if (data->status_bits & mask) { data->interrupt_mask = 0; data->status_bits &= mask; @@ -243,17 +282,17 @@ static int riic_wait_for_state(const struct device *dev, uint8_t mask, bool fore k_sem_reset(&data->sem); /* Save previous interrupts before modifying */ - int_backup = riic_read(dev, RIIC_IER); + int_backup = riic_read8(dev, RIIC_IER); /* Enable additionally interrupts */ - riic_write(dev, RIIC_IER, mask | int_backup); + riic_write8(dev, RIIC_IER, mask | int_backup); /* Wait for the interrupts */ ret = k_sem_take(&data->sem, (forever) ? K_FOREVER : K_USEC(MAX_WAIT_US)); /* Restore previous interrupts and wait for the changes to take effect */ - riic_write(dev, RIIC_IER, int_backup); - while ((riic_read(dev, RIIC_IER) != int_backup) && (timeout < 10)) { + riic_write8(dev, RIIC_IER, int_backup); + while ((riic_read8(dev, RIIC_IER) != int_backup) && (timeout < 10)) { k_msleep(1); timeout++; } @@ -261,7 +300,7 @@ static int riic_wait_for_state(const struct device *dev, uint8_t mask, bool fore if (!ret) { return 0; } - data->status_bits = riic_read(dev, RIIC_SR2) & mask; + data->status_bits = riic_read8(dev, RIIC_SR2) & mask; if (data->status_bits) { data->interrupt_mask = 0; return 0; @@ -287,7 +326,7 @@ static int riic_finish(const struct device *dev) { riic_clear_set_bit(dev, RIIC_CR2, 0, RIIC_CR2_SP); riic_wait_for_state(dev, RIIC_IER_SPIE, false); - if (riic_read(dev, RIIC_CR2) & RIIC_SR2_START) { + if (riic_read8(dev, RIIC_CR2) & RIIC_SR2_START) { riic_clear_set_bit(dev, RIIC_SR2, RIIC_SR2_START, 0); } riic_clear_set_bit(dev, RIIC_SR2, RIIC_SR2_NACKF | RIIC_SR2_STOP, 0); @@ -306,17 +345,17 @@ static int riic_set_addr(const struct device *dev, uint16_t chip, uint16_t flags } /* Set slave address & transfer mode */ if (flags & I2C_MSG_ADDR_10_BITS) { - riic_write(dev, RIIC_DRT, 0xf0 | ((chip >> 5) & 0x6) | read); + riic_write8(dev, RIIC_DRT, 0xf0 | ((chip >> 5) & 0x6) | read); riic_wait_for_state(dev, RIIC_IER_TIE, false); - riic_write(dev, RIIC_DRT, chip & 0xff); + riic_write8(dev, RIIC_DRT, chip & 0xff); } else { - riic_write(dev, RIIC_DRT, ((chip & 0x7f) << 1) | read); + riic_write8(dev, RIIC_DRT, ((chip & 0x7f) << 1) | read); } riic_wait_for_state(dev, RIIC_IER_NAKIE, false); if (data->status_bits & RIIC_SR2_NACKF) { return 1; } - if ((riic_read(dev, RIIC_MR3) & RIIC_MR3_ACKBR) == 0) { + if ((riic_read8(dev, RIIC_MR3) & RIIC_MR3_ACKBR) == 0) { return 0; } return 1; @@ -362,6 +401,7 @@ static int riic_dma_read(const struct device *dev, struct i2c_msg *msg) struct dma_block_config dma_blk = { 0 }; bool is_rie_on; int error; + uint32_t start_manual = 0; if (msg->len == 0) { return -EIO; @@ -372,13 +412,13 @@ static int riic_dma_read(const struct device *dev, struct i2c_msg *msg) return -EIO; } - /* TODO: disable RDRFS for whole driver and make the appropriate changes - * to the master and slave API. - */ - /* Disable RDRFS to automatically send ACK/NACK after each byte */ - riic_clear_set_bit(dev, RIIC_MR3, RIIC_MR3_RDRFS, 0); + riic_clear_set_bit(dev, RIIC_MR3, 0, RIIC_MR3_WAIT); - if (msg->len > 1) { + /* Send 2 last bytes in sync mode. It needs to set NACK after receiving last byte */ + if (msg->len > DMA_READ_THRESHOLD) { + /* Disable RDRFS to automatically send ACK/NACK after each byte */ + riic_clear_set_bit(dev, RIIC_MR3, RIIC_MR3_RDRFS, 0); + start_manual = msg->len - DMA_READ_MANUAL; /* Use DMA only for transfers bigger than 1 byte */ dma_cfg.channel_direction = PERIPHERAL_TO_MEMORY; dma_cfg.source_data_size = 1; @@ -390,10 +430,10 @@ static int riic_dma_read(const struct device *dev, struct i2c_msg *msg) dma_cfg.dma_slot = cfg->read_dma_slot; /* Last byte will received below in sync mode */ - dma_blk.block_size = msg->len - 1; + dma_blk.block_size = msg->len - DMA_READ_MANUAL; dma_blk.dest_address = (uint32_t)msg->buf; dma_blk.dest_addr_adj = DMA_ADDR_ADJ_INCREMENT; - dma_blk.source_address = (uint32_t)DEVICE_MMIO_ROM_PTR(dev)->phys_addr + RIIC_DRR; + dma_blk.source_address = *(mm_reg_t *)DEVICE_MMIO_ROM_PTR(dev) + RIIC_DRR; dma_blk.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE; error = dma_config(cfg->dma_dev, cfg->dma_channel, &dma_cfg); @@ -414,7 +454,7 @@ static int riic_dma_read(const struct device *dev, struct i2c_msg *msg) return error; } - is_rie_on = !!(riic_read(dev, RIIC_IER) && RIIC_IER_RIE); + is_rie_on = !!(riic_read8(dev, RIIC_IER) && RIIC_IER_RIE); if (!is_rie_on) { /* Enable Receive Data Full interrupt for DMA operation if needed */ riic_clear_set_bit(dev, RIIC_IER, 0, RIIC_IER_RIE); @@ -422,39 +462,40 @@ static int riic_dma_read(const struct device *dev, struct i2c_msg *msg) } /* Dummy read for clearing RDRF flag. This start data reading transaction */ - riic_read(dev, RIIC_DRR); + riic_read8(dev, RIIC_DRR); /* Waiting for DMA operation to complete */ k_sem_take(&data->sem, K_FOREVER); - /* Stop DMA and restore interrupts */ - dma_stop(cfg->dma_dev, cfg->dma_channel); + /* Restore interrupts */ if (!is_rie_on) { /* Disable Receive Data Full interrupt if needed */ riic_clear_set_bit(dev, RIIC_IER, RIIC_IER_RIE, 0); riic_wait_for_clear(dev, RIIC_IER, RIIC_IER_RIE); } + /* Restore RDRFS */ + riic_clear_set_bit(dev, RIIC_MR3, 0, RIIC_MR3_RDRFS); + riic_wait_for_set(dev, RIIC_MR3, RIIC_MR3_RDRFS); } else { /* Dummy read for clearing RDRF flag. This start data reading transaction */ - riic_read(dev, RIIC_DRR); + riic_read8(dev, RIIC_DRR); } - riic_clear_set_bit(dev, RIIC_MR3, 0, RIIC_MR3_WAIT); - - /* Set NACK transmitting after last byte */ - riic_transmit_nack(dev); + for (int i = start_manual; i < msg->len; i++) { + if (riic_wait_for_state(dev, RIIC_IER_RIE, false)) { + return -EIO; + } + if (msg->len == i + 1) { + riic_clear_set_bit(dev, RIIC_CR2, 0, RIIC_CR2_SP); + /* Set NACK transmitting after last byte */ + riic_transmit_nack(dev); + } else { + riic_transmit_ack(dev); + } - /* Receive last byte */ - if (riic_wait_for_state(dev, RIIC_IER_RIE, false)) { - return -EIO; + /* Receive next byte */ + msg->buf[i] = riic_read8(dev, RIIC_DRR) & 0xff; } - msg->buf[msg->len - 1] = riic_read(dev, RIIC_DRR) & 0xff; - - /* Terminate transaction */ - riic_clear_set_bit(dev, RIIC_CR2, 0, RIIC_CR2_SP); - - /* Restore RDRFS */ - riic_clear_set_bit(dev, RIIC_MR3, 0, RIIC_MR3_RDRFS); return 0; } @@ -499,7 +540,7 @@ static int riic_dma_write(const struct device *dev, struct i2c_msg *msg) dma_blk.block_size = msg->len - 1; dma_blk.source_address = (uint32_t)(msg->buf + 1); dma_blk.source_addr_adj = DMA_ADDR_ADJ_INCREMENT; - dma_blk.dest_address = (uint32_t)DEVICE_MMIO_ROM_PTR(dev)->phys_addr + RIIC_DRT; + dma_blk.dest_address = *(mm_reg_t *)DEVICE_MMIO_ROM_PTR(dev) + RIIC_DRT; dma_blk.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE; error = dma_config(cfg->dma_dev, cfg->dma_channel, &dma_cfg); @@ -517,7 +558,7 @@ static int riic_dma_write(const struct device *dev, struct i2c_msg *msg) return error; } - is_tie_on = !!(riic_read(dev, RIIC_IER) && RIIC_IER_TIE); + is_tie_on = !!(riic_read8(dev, RIIC_IER) && RIIC_IER_TIE); if (!is_tie_on) { /* Enable Transmit Data Empty interrupt for DMA operation if needed */ riic_clear_set_bit(dev, RIIC_IER, 0, RIIC_IER_TIE); @@ -526,7 +567,7 @@ static int riic_dma_write(const struct device *dev, struct i2c_msg *msg) } /* Send first buffer byte (this will trigger DMA if it enabled) */ - riic_write(dev, RIIC_DRT, msg->buf[0]); + riic_write8(dev, RIIC_DRT, msg->buf[0]); /* Wait for transmitting complete */ riic_wait_for_state(dev, RIIC_IER_TEIE, true); @@ -560,7 +601,7 @@ static int riic_transfer_msg(const struct device *dev, struct i2c_msg *msg) } } #else /* CONFIG_I2C_RIIC_DMA_DRIVEN */ - uint32_t i, status; + uint32_t i; if ((msg->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { /* Master read operation in sync mode */ @@ -574,11 +615,10 @@ static int riic_transfer_msg(const struct device *dev, struct i2c_msg *msg) } /* Dummy read for clearing RDRF flag */ - riic_read(dev, RIIC_DRR); + riic_read8(dev, RIIC_DRR); for (i = 0; i < msg->len; i++) { if (riic_wait_for_state(dev, RIIC_IER_RIE, false)) { - status = riic_read(dev, RIIC_SR2); return -EIO; } if (msg->len == i + 2) { @@ -592,7 +632,7 @@ static int riic_transfer_msg(const struct device *dev, struct i2c_msg *msg) } /* Receive next byte */ - msg->buf[i] = riic_read(dev, RIIC_DRR) & 0xff; + msg->buf[i] = riic_read8(dev, RIIC_DRR) & 0xff; } } else { /* Master write operation in sync mode */ @@ -600,7 +640,7 @@ static int riic_transfer_msg(const struct device *dev, struct i2c_msg *msg) if (riic_wait_for_state(dev, RIIC_IER_TIE, false)) { return -EIO; } - riic_write(dev, RIIC_DRT, msg->buf[i]); + riic_write8(dev, RIIC_DRT, msg->buf[i]); } riic_wait_for_state(dev, RIIC_IER_TEIE, false); } @@ -630,7 +670,7 @@ static int riic_transfer(const struct device *dev, } /* Wait for the bus to be available */ - while ((riic_read(dev, RIIC_CR2) & RIIC_CR2_BBSY) && (timeout < 10)) { + while ((riic_read8(dev, RIIC_CR2) & RIIC_CR2_BBSY) && (timeout < 10)) { k_busy_wait(USEC_PER_MSEC); timeout++; } @@ -664,7 +704,7 @@ static int riic_transfer(const struct device *dev, data->master_active = 1; do { if (msgs->flags & I2C_MSG_RESTART) { - if (riic_read(dev, RIIC_SR2) & RIIC_SR2_START) { + if (riic_read8(dev, RIIC_SR2) & RIIC_SR2_START) { /* Generate RESTART condition */ riic_clear_set_bit(dev, RIIC_CR2, 0, RIIC_CR2_RS); } else { @@ -702,6 +742,9 @@ static int riic_transfer(const struct device *dev, } while (num_msgs); data->master_active = 0; + if (riic_read8(dev, RIIC_CR2) & RIIC_CR2_BBSY) { + riic_finish(dev); + } /* Complete without error */ exit: k_mutex_unlock(&data->i2c_lock_mtx); @@ -797,12 +840,12 @@ static int riic_configure(const struct device *dev, uint32_t dev_config) riic_clear_set_bit(dev, RIIC_CR1, 0, RIIC_CR1_IICRST); riic_clear_set_bit(dev, RIIC_CR1, 0, RIIC_CR1_ICE); - riic_write(dev, RIIC_MR1, RIIC_MR1_CKS(cks)); - riic_write(dev, RIIC_BRH, brh | RIIC_BR_RESERVED); - riic_write(dev, RIIC_BRL, brl | RIIC_BR_RESERVED); + riic_write8(dev, RIIC_MR1, RIIC_MR1_CKS(cks)); + riic_write8(dev, RIIC_BRH, brh | RIIC_BR_RESERVED); + riic_write8(dev, RIIC_BRL, brl | RIIC_BR_RESERVED); - riic_write(dev, RIIC_SER, 0); - riic_write(dev, RIIC_MR3, RIIC_MR3_RDRFS); + riic_write8(dev, RIIC_SER, 0); + riic_write8(dev, RIIC_MR3, RIIC_MR3_RDRFS); if (I2C_SPEED_GET(dev_config) == I2C_SPEED_FAST_PLUS) { riic_clear_set_bit(dev, RIIC_FER, 0, RIIC_FER_FMPE); @@ -844,11 +887,13 @@ static int riic_init(const struct device *dev) return -ENODEV; } - /* Configure dt provided device signals when available */ - ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - if (ret < 0) { - LOG_ERR("Can't apply pinctrl state for %s\n", dev->name); - return ret; + if (config->pcfg->state_cnt) { + /* Configure dt provided device signals when available */ + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_ERR("Can't apply pinctrl state for %s\n", dev->name); + return ret; + } } ret = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->mod_clk); @@ -864,6 +909,10 @@ static int riic_init(const struct device *dev) goto err; } +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg_riic) + (void)reset_line_deassert_dt(&config->reset); +#endif + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); bitrate_cfg = i2c_map_dt_bitrate(config->bitrate); @@ -905,11 +954,11 @@ static void riic_slave_event(const struct device *dev) } slave_cb = slave_cfg->callbacks; - status = riic_read(dev, RIIC_SR2); + status = riic_read8(dev, RIIC_SR2); if (status & RIIC_SR2_RDRF) { /* RX data is available, read it and issue write callback */ - val = riic_read(dev, RIIC_DRR); + val = riic_read8(dev, RIIC_DRR); if (slave->first_write) { /* First byte received (device address + W/R) */ slave->first_write = false; @@ -939,13 +988,13 @@ static void riic_slave_event(const struct device *dev) if (slave_cb->read_requested && !slave_cb->read_requested(slave_cfg, &val)) { /* No error, send byte */ - riic_write(dev, RIIC_DRT, val); + riic_write8(dev, RIIC_DRT, val); } } else { if (slave_cb->read_processed && !slave_cb->read_processed(slave_cfg, &val)) { /* No error, send byte */ - riic_write(dev, RIIC_DRT, val); + riic_write8(dev, RIIC_DRT, val); } } return; @@ -967,7 +1016,7 @@ static void riic_slave_event(const struct device *dev) if (status & RIIC_SR2_NACKF) { /* NACK from master. Dummy read DRR to release SCL line */ - riic_read(dev, RIIC_DRR); + riic_read8(dev, RIIC_DRR); /* Temporary disable NACK Reception Interrupt until stop not received */ riic_clear_set_bit(dev, RIIC_IER, RIIC_IER_NAKIE, 0); @@ -993,7 +1042,7 @@ int riic_target_register(const struct device *dev, struct i2c_target_config *con return -EBUSY; } - val = (~riic_read(dev, RIIC_SER)) & RIIC_SER_SLAVE_MASK; + val = (~riic_read8(dev, RIIC_SER)) & RIIC_SER_SLAVE_MASK; slave_num = __builtin_ffs(val) - 1; if (slave_num < 0) { ret = -EBUSY; @@ -1005,7 +1054,7 @@ int riic_target_register(const struct device *dev, struct i2c_target_config *con } else { val = (config->address << RIIC_SAR_SVA_SHIFT) & RIIC_SAR_SVA_MASK; } - riic_write(dev, RIIC_SAR0 + slave_num * 4, val); + riic_write16(dev, RIIC_SAR0 + slave_num * 4, val); riic_clear_set_bit(dev, RIIC_SER, 0, BIT(slave_num)); data->slave[slave_num].slave_cfg = config; data->slave[slave_num].slave_attached = true; @@ -1013,7 +1062,7 @@ int riic_target_register(const struct device *dev, struct i2c_target_config *con data->slave[slave_num].first_write = true; /* Enable interrupts */ - riic_write(dev, RIIC_IER, RIIC_IER_RIE | RIIC_IER_TIE | RIIC_IER_NAKIE | RIIC_IER_SPIE); + riic_write8(dev, RIIC_IER, RIIC_IER_RIE | RIIC_IER_TIE | RIIC_IER_NAKIE | RIIC_IER_SPIE); LOG_DBG("i2c: target registered. Address %x", config->address); @@ -1056,7 +1105,7 @@ int riic_target_unregister(const struct device *dev, struct i2c_target_config *c data->slave[i].slave_cfg = NULL; /* Disable interrupts */ - riic_write(dev, RIIC_IER, 0); + riic_write8(dev, RIIC_IER, 0); LOG_DBG("i2c: slave unregistered"); @@ -1076,7 +1125,7 @@ static void riic_isr(const struct device *dev) if (!data->master_active) { /* Only for slave mode */ - value = riic_read(dev, RIIC_SR1) & RIIC_SR1_AAS_MASK; + value = riic_read8(dev, RIIC_SR1) & RIIC_SR1_AAS_MASK; slave_num = __builtin_ffs(value) - 1; if (slave_num >= 0) { /* Save active slave number because we cannot read it after stop bit */ @@ -1092,7 +1141,7 @@ static void riic_isr(const struct device *dev) } #endif /* Only for master mode */ - value = riic_read(dev, RIIC_SR2); + value = riic_read8(dev, RIIC_SR2); if (value & data->interrupt_mask) { data->status_bits = value & data->interrupt_mask; k_sem_give(&data->sem); @@ -1162,13 +1211,21 @@ static const struct i2c_driver_api riic_driver_api = { #endif }; +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_riic) +#define RIIC_IRQ_FLAGS(n, name) DT_INST_IRQ_BY_NAME(n, name, flags) +#define RIIC_RESET(n) +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg_riic) +#define RIIC_IRQ_FLAGS(n, name) 0 +#define RIIC_RESET(n) .reset = RESET_DT_SPEC_INST_GET(n), +#endif + /* Device Instantiation */ #define RIIC_SET_IRQ(n, name, isr) \ IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, name, irq), \ DT_INST_IRQ_BY_NAME(n, name, priority), \ isr, \ DEVICE_DT_INST_GET(n), \ - DT_INST_IRQ_BY_NAME(n, name, flags)); \ + RIIC_IRQ_FLAGS(n, name)); \ irq_enable(DT_INST_IRQ_BY_NAME(n, name, irq)); #ifdef CONFIG_I2C_RIIC_DMA_DRIVEN @@ -1201,11 +1258,16 @@ static const struct i2c_driver_api riic_driver_api = { .bitrate = DT_INST_PROP(n, clock_frequency), \ .scl_rise_ns = DT_INST_PROP_OR(n, scl_rising_time_ns, 0),\ .scl_fall_ns = DT_INST_PROP_OR(n, scl_falling_time_ns, 0),\ - .mod_clk.module = DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module),\ - .mod_clk.domain = DT_INST_CLOCKS_CELL_BY_IDX(n, 0, domain),\ - .bus_clk.module = DT_INST_CLOCKS_CELL_BY_IDX(n, 1, module),\ - .bus_clk.domain = DT_INST_CLOCKS_CELL_BY_IDX(n, 1, domain),\ + .mod_clk.module = \ + DT_INST_CLOCKS_CELL_BY_NAME(n, fck, module), \ + .mod_clk.domain = \ + DT_INST_CLOCKS_CELL_BY_NAME(n, fck, domain), \ + .bus_clk.module = \ + DT_INST_CLOCKS_CELL_BY_NAME(n, bus, module), \ + .bus_clk.domain = \ + DT_INST_CLOCKS_CELL_BY_NAME(n, bus, domain), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + RIIC_RESET(n) \ RIIC_DMA_CHANNELS(n) \ }; \ \ diff --git a/drivers/input/input_ft5336.c b/drivers/input/input_ft5336.c index 65aa3f1a9180d9..8c8ce9a606e5c2 100644 --- a/drivers/input/input_ft5336.c +++ b/drivers/input/input_ft5336.c @@ -75,7 +75,7 @@ struct ft5336_config { struct gpio_dt_spec reset_gpio; int tag; #ifdef CONFIG_INPUT_FT5336_INTERRUPT -#ifdef CONFIG_FT5335_GPIO_INTERRUPT +#ifdef CONFIG_INPUT_FT5335_GPIO_INTERRUPT /** Interrupt GPIO information. */ struct gpio_dt_spec int_gpio; #else diff --git a/drivers/interrupt_controller/CMakeLists.txt b/drivers/interrupt_controller/CMakeLists.txt index c32a938330c180..fada5d2f10b0c9 100644 --- a/drivers/interrupt_controller/CMakeLists.txt +++ b/drivers/interrupt_controller/CMakeLists.txt @@ -23,7 +23,8 @@ zephyr_library_sources_ifdef(CONFIG_LOAPIC_SPURIOUS_VECTOR intc_loapic_spurious zephyr_library_sources_ifdef(CONFIG_MCHP_ECIA_XEC intc_mchp_ecia_xec.c) zephyr_library_sources_ifdef(CONFIG_NPCX_MIWU intc_miwu.c) zephyr_library_sources_ifdef(CONFIG_PLIC intc_plic.c) -zephyr_library_sources_ifdef(CONFIG_INTC_R7S9210 intc_r7s9210.c) +zephyr_library_sources_ifdef(CONFIG_INTC_R7S9210 intc_r7s9210.c intc_rz_common.c) +zephyr_library_sources_ifdef(CONFIG_INTC_R9A08G045 intc_r9a08g045.c intc_rz_common.c) zephyr_library_sources_ifdef(CONFIG_RV32M1_INTMUX intc_rv32m1_intmux.c) zephyr_library_sources_ifdef(CONFIG_SAM0_EIC intc_sam0_eic.c) zephyr_library_sources_ifdef(CONFIG_SHARED_IRQ intc_shared_irq.c) diff --git a/drivers/interrupt_controller/Kconfig b/drivers/interrupt_controller/Kconfig index e7323ab687a9af..094db0401e4b42 100644 --- a/drivers/interrupt_controller/Kconfig +++ b/drivers/interrupt_controller/Kconfig @@ -72,7 +72,7 @@ source "drivers/interrupt_controller/Kconfig.stm32" source "drivers/interrupt_controller/Kconfig.cavs" -source "drivers/interrupt_controller/Kconfig.r7s9210" +source "drivers/interrupt_controller/Kconfig.renesas" source "drivers/interrupt_controller/Kconfig.rv32m1" diff --git a/drivers/interrupt_controller/Kconfig.r7s9210 b/drivers/interrupt_controller/Kconfig.r7s9210 deleted file mode 100644 index 4035e10170636c..00000000000000 --- a/drivers/interrupt_controller/Kconfig.r7s9210 +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2023 EPAM Systems -# SPDX-License-Identifier: Apache-2.0 - -config INTC_R7S9210 - bool "Renesas r7s9210 interrupt controller support" - default y - depends on DT_HAS_RENESAS_R7S9210_INTC_ENABLED - depends on MULTI_LEVEL_INTERRUPTS - select ARM_CUSTOM_INTERRUPT_CONTROLLER - help - Select this option to enable support for the Renesas r7s9210 interrupt - controller driver. This provides a level 2 interrupt controller for - the SoC. The INTMUX peripheral combines level 2 interrupts into eight - channels; each channel has its own level 1 interrupt to the core. - -if INTC_R7S9210 - -config INTC_R7S9210_INIT_PRIORITY - int "r7s9210 intc driver initialization priority" - default 40 - help - Boot time initialization priority for r7s9210 intc driver. - -endif # INTC_R7S9210 diff --git a/drivers/interrupt_controller/Kconfig.renesas b/drivers/interrupt_controller/Kconfig.renesas new file mode 100644 index 00000000000000..8d4bdbea478807 --- /dev/null +++ b/drivers/interrupt_controller/Kconfig.renesas @@ -0,0 +1,46 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +config INTC_R7S9210 + bool "Renesas r7s9210 interrupt controller support" + default y + depends on DT_HAS_RENESAS_R7S9210_INTC_ENABLED + depends on MULTI_LEVEL_INTERRUPTS + select ARM_CUSTOM_INTERRUPT_CONTROLLER + help + Select this option to enable support for the Renesas r7s9210 interrupt + controller driver. This provides a level 2 interrupt controller for + the SoC. The INTMUX peripheral combines level 2 interrupts into eight + channels; each channel has its own level 1 interrupt to the core. + +if INTC_R7S9210 + +config INTC_R7S9210_INIT_PRIORITY + int "r7s9210 intc driver initialization priority" + default 40 + help + Boot time initialization priority for r7s9210 intc driver. + +endif # INTC_R7S9210 + +config INTC_R9A08G045 + bool "Renesas r9a08g045 interrupt controller support" + default y + depends on DT_HAS_RENESAS_R9A08G045_INTC_ENABLED + depends on MULTI_LEVEL_INTERRUPTS + select ARM_CUSTOM_INTERRUPT_CONTROLLER + help + Select this option to enable support for the Renesas r9a08g045 interrupt + controller driver for 8 pin IRQs. This provides a level 2 interrupt controller for + the SoC. The IM33 peripheral combines level 2 interrupts into eight + channels; each channel has its own level 1 interrupt to the core. + +if INTC_R9A08G045 + +config INTC_R9A08G045_INIT_PRIORITY + int "r9a08g045 intc driver initialization priority" + default 40 + help + Boot time initialization priority for r9a08g045 intc driver. + +endif # INTC_R9A08G045 diff --git a/drivers/interrupt_controller/intc_gic.c b/drivers/interrupt_controller/intc_gic.c index 82eda22da274fe..7089f39de137e9 100644 --- a/drivers/interrupt_controller/intc_gic.c +++ b/drivers/interrupt_controller/intc_gic.c @@ -89,6 +89,16 @@ void arm_gic_irq_clear_pending(unsigned int irq) sys_write32((1 << int_off), (GICD_ICPENDRn + int_grp * 4)); } +void arm_gic_irq_set_pending(unsigned int irq) +{ + int int_grp, int_off; + + int_grp = irq / 32; + int_off = irq % 32; + + sys_write32((1 << int_off), (GICD_ISPENDRn + int_grp * 4)); +} + void arm_gic_irq_set_priority( unsigned int irq, unsigned int prio, uint32_t flags) { diff --git a/drivers/interrupt_controller/intc_r7s9210.c b/drivers/interrupt_controller/intc_r7s9210.c index aa25f7766a400c..3d8f93fd78e914 100644 --- a/drivers/interrupt_controller/intc_r7s9210.c +++ b/drivers/interrupt_controller/intc_r7s9210.c @@ -25,6 +25,8 @@ #include #include +#include "intc_rz_common.h" + /** * CR0 is a 16-bit register that sets the input signal detection mode for the * external interrupt input pin NMI, and indicates the input level at the NMI pin. @@ -61,26 +63,10 @@ */ #define R7S9210_INTC_RR_MSK BIT(15) -struct r7s9210_intc_line_cfg { - unsigned int line; - unsigned int parent_line; -}; - -struct r7s9210_intc_cfg { - DEVICE_MMIO_ROM; /* Must be first */ - struct r7s9210_intc_line_cfg *line_map; - unsigned int num_lines; -}; - -struct r7s9210_intc_data { - DEVICE_MMIO_RAM; /* Must be first */ - struct k_spinlock lock; -}; - static void r7s9210_isr(const void *arg) { const struct device *const dev = DEVICE_DT_INST_GET(0); - struct r7s9210_intc_data *data = (struct r7s9210_intc_data *)dev->data; + struct intc_rz_data *data = (struct intc_rz_data *)dev->data; k_spinlock_key_t key; const uint32_t line = POINTER_TO_UINT(arg); const struct _isr_table_entry *entry = &_sw_isr_table[CONFIG_2ND_LVL_ISR_TBL_OFFSET + line]; @@ -99,78 +85,16 @@ static void r7s9210_isr(const void *arg) k_spin_unlock(&data->lock, key); } -/* is this irq belongs to this intc if yes - return parent irq */ -static unsigned int r7s9210_intr_get_parent_irq(const struct device *dev, unsigned int irq) -{ - const struct r7s9210_intc_cfg *cfg = (const struct r7s9210_intc_cfg *)dev->config; - unsigned int parent_line = irq_parent_level_2(irq) + 32; - - irq = irq_from_level_2(irq); - parent_line += irq; - - for (unsigned int line = 0; line < cfg->num_lines; line++) { - if (cfg->line_map[line].line != irq) { - continue; - } - - if (cfg->line_map[line].parent_line == parent_line) { - return parent_line; - } - } - - return 0; -} - -/* The driver can't enable IRQ by this driver, so lets request it from the parent driver. */ -static void r7s9210_intr_enable(const struct device *dev, unsigned int irq) -{ - unsigned int parent_irq = r7s9210_intr_get_parent_irq(dev, irq); - - if (!parent_irq) { - return; - } - - irq_enable(parent_irq); -} - -/* The driver can't disable IRQ by this driver, so lets request it from the parent driver. */ -static void r7s9210_intr_disable(const struct device *dev, unsigned int irq) -{ - unsigned int parent_irq = r7s9210_intr_get_parent_irq(dev, irq); - - if (!parent_irq) { - return; - } - - irq_disable(parent_irq); -} - -/** - * The driver can't determine the status of whether the IRQs on lines are enabled or not. - * So, let's request information from the parent driver. - */ -static unsigned int r7s9210_intr_get_state(const struct device *dev) -{ - const struct r7s9210_intc_cfg *cfg = (const struct r7s9210_intc_cfg *)dev->config; - - for (unsigned int line = 0; line < cfg->num_lines; line++) { - if (irq_is_enabled(cfg->line_map[line].parent_line)) { - return 1; - } - } - - return 0; -} - static void r7s9210_intr_set_priority(const struct device *dev, unsigned int irq, unsigned int prio, uint32_t flags) { uint16_t cr1; - struct r7s9210_intc_data *data = (struct r7s9210_intc_data *)dev->data; + const struct intc_rz_cfg *cfg = (const struct intc_rz_cfg *)dev->config; + struct intc_rz_data *data = (struct intc_rz_data *)dev->data; k_spinlock_key_t key; - unsigned int parent_irq = r7s9210_intr_get_parent_irq(dev, irq); + unsigned int parent_irq = intc_rz_intr_get_parent_irq(dev, irq); - if (!parent_irq) { + if (parent_irq >= cfg->num_lines) { return; } @@ -200,55 +124,22 @@ static void r7s9210_intr_set_priority(const struct device *dev, unsigned int irq k_spin_unlock(&data->lock, key); } -/** - * The driver can't determine the status of whether the IRQ on this line is enabled or not. - * Therefore, let's request this information from the parent driver. - */ -static int r7s9210_intr_get_line_state(const struct device *dev, unsigned int irq) -{ - unsigned int parent_irq = r7s9210_intr_get_parent_irq(dev, irq); - - if (!parent_irq) { - return 0; - } - - return irq_is_enabled(parent_irq); -} - static const struct irq_next_level_api r7s9210_intc_next_lvl = { - .intr_enable = r7s9210_intr_enable, - .intr_disable = r7s9210_intr_disable, - .intr_get_state = r7s9210_intr_get_state, + .intr_enable = intc_rz_intr_enable, + .intr_disable = intc_rz_intr_disable, + .intr_get_state = intc_rz_intr_get_state, .intr_set_priority = r7s9210_intr_set_priority, - .intr_get_line_state = r7s9210_intr_get_line_state, + .intr_get_line_state = intc_rz_intr_get_line_state, }; BUILD_ASSERT(DT_NUM_IRQS(DT_DRV_INST(0)) == DT_INST_PROP_LEN(0, map), "Number of items in interrupts and map should be the same"); -#define IRQ_CONFIGURE(n, inst) \ - IRQ_CONNECT(DT_INST_IRQ_BY_IDX(inst, n, irq), \ - DT_INST_IRQ_BY_IDX(inst, n, priority), r7s9210_isr, \ - DT_INST_PROP_BY_IDX(inst, map, n), \ - DT_INST_IRQ_BY_IDX(inst, n, flags)); \ - BUILD_ASSERT(DT_INST_IRQ_BY_IDX(inst, n, type) == GIC_SPI, \ - "Driver can work only with SPI parent interrupts"); - -#define CONFIGURE_ALL_IRQS(inst, n) LISTIFY(n, IRQ_CONFIGURE, (), inst) - -#define FILL_ONE_LINE_MAP(n, inst) \ - { \ - DT_INST_PROP_BY_IDX(inst, map, n), \ - DT_INST_IRQ_BY_IDX(inst, n, irq), \ - } -#define FILL_LINE_MAP_CONFIG(inst, n) \ - (struct r7s9210_intc_line_cfg []){LISTIFY(n, FILL_ONE_LINE_MAP, (,), inst)} - static inline void r7s9210_intc_setup_nmi_edge(const struct device *dev) { k_spinlock_key_t key; uint16_t cr0; - struct r7s9210_intc_data *data = (struct r7s9210_intc_data *)dev->data; + struct intc_rz_data *data = (struct intc_rz_data *)dev->data; uint16_t nmi_edge = DT_INST_PROP_OR(0, nmi_edge, IRQ_TYPE_EDGE_FALLING) >> 2; nmi_edge <<= R7S9210_INTC_CR0_NMIE_OFFSET; @@ -278,23 +169,29 @@ void z_arm_nmi_eoi(void) sys_write16(cr0, DEVICE_MMIO_GET(dev) + R7S9210_INTC_CR0); } +#define IRQ_CONFIGURE(n, inst, _isr) \ + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(inst, n, irq), DT_INST_IRQ_BY_IDX(inst, n, priority), _isr, \ + DT_INST_PROP_BY_IDX(inst, map, n), DT_INST_IRQ_BY_IDX(inst, n, flags)); + +#define CONFIGURE_ALL_IRQS(inst, n, _isr) LISTIFY(n, IRQ_CONFIGURE, (), inst, _isr) + static int r7s9210_intc_init(const struct device *dev) { DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); - CONFIGURE_ALL_IRQS(0, DT_NUM_IRQS(DT_DRV_INST(0))); + CONFIGURE_ALL_IRQS(0, DT_NUM_IRQS(DT_DRV_INST(0)), r7s9210_isr); r7s9210_intc_setup_nmi_edge(dev); return 0; } -static const struct r7s9210_intc_cfg drv_cfg = { +static const struct intc_rz_cfg drv_cfg = { DEVICE_MMIO_ROM_INIT(DT_DRV_INST(0)), .num_lines = DT_NUM_IRQS(DT_DRV_INST(0)), .line_map = FILL_LINE_MAP_CONFIG(0, DT_NUM_IRQS(DT_DRV_INST(0))), }; -static struct r7s9210_intc_cfg drv_data; +static struct intc_rz_data drv_data; DEVICE_DT_INST_DEFINE(0, &r7s9210_intc_init, NULL, &drv_data, &drv_cfg, PRE_KERNEL_1, diff --git a/drivers/interrupt_controller/intc_r9a08g045.c b/drivers/interrupt_controller/intc_r9a08g045.c new file mode 100644 index 00000000000000..714baeebacaa0d --- /dev/null +++ b/drivers/interrupt_controller/intc_r9a08g045.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2024 EPAM Systemss + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_r9a08g045_intc + +/** + * @file + * @brief r9a08g045 interrupt controller driver + * + * This driver provides support for level 2 interrupts on the r9a08g045 + * SoC. The r9a08g045 interrupt controller is a front-end for the NVIC found + * on Renesas RZ/G3S SoCs: IRQ sense select for 8 external pin interrupts, + * 1:1-mapped to 8 NVIC interrupts and NMI edge select. + */ + +#include +#include +#include +#include +#include +#include +#include +LOG_MODULE_REGISTER(r9a08g045_intc, CONFIG_INTC_LOG_LEVEL); + +#include "intc_rz_common.h" + +#define R9A08G045_NMI_NSCR 0x00 +#define R9A08G045_NMI_NITSR 0x04 + +#define R9A08G045_INTC_ISCR 0x10 +#define R9A08G045_INTC_IITSR 0x14 + +/* NSCR NMI Status Control Register */ +#define R9A08G045_NMI_NSCR_NSTAT BIT(0) +#define R9A08G045_NMI_NSCR_NSMON BIT(16) + +/* NITSR NMI Interrupt Type Selection Register + * 0: Falling-edge detection. + * 1: Rising-edge detection. + */ +#define R9A08G045_NMI_NITSR_NTSEL BIT(0) + +/* ISCR IRQ Status Control Register */ +#define R9A08G045_INTC_ISCR_ISTAT(n) BIT(n) + +/* IITSR IRQ Interrupt Type Selection Register */ +#define R9A08G045_INTC_IITSR_IITSEL(n, t) (((t) & 0x3) << ((n) << 1)) +#define R9A08G045_INTC_IITSR_IITSEL_LOW_LEVEL 0x0 +#define R9A08G045_INTC_IITSR_IITSEL_EDGE_FALLING 0x1 +#define R9A08G045_INTC_IITSR_IITSEL_EDGE_RISING 0x2 +#define R9A08G045_INTC_IITSR_IITSEL_EDGE_BOTH 0x3 + +struct r9a08g045_intc_data { + struct intc_rz_data rz_data; + uint8_t f_irq_lvl; +}; + +static void r9a08g045_intr_nmi_eoi(const struct device *dev) +{ + uint32_t reg_val; + + /* cancel current NMI, this function is called after nmi handler */ + reg_val = sys_read32(DEVICE_MMIO_GET(dev) + R9A08G045_NMI_NSCR); + reg_val &= ~R9A08G045_NMI_NSCR_NSTAT; + sys_write32(reg_val, DEVICE_MMIO_GET(dev) + R9A08G045_NMI_NSCR); +} + +static void r9a08g045_intr_nmi_set_type(const struct device *dev, unsigned int irq, + uint32_t flags) +{ + struct r9a08g045_intc_data *data = (struct r9a08g045_intc_data *)dev->data; + k_spinlock_key_t key; + + irq = irq_from_level_2(irq); + + switch (flags) { + case IRQ_TYPE_EDGE_FALLING: + flags = 0; + break; + case IRQ_TYPE_EDGE_RISING: + flags = R9A08G045_NMI_NITSR_NTSEL; + break; + default: + return; + } + + key = k_spin_lock(&data->rz_data.lock); + sys_write32(flags, DEVICE_MMIO_GET(dev) + R9A08G045_NMI_NITSR); + k_spin_unlock(&data->rz_data.lock, key); +} + +static void r9a08g045_nmi_isr(const void *arg) +{ + const struct device *const dev = DEVICE_DT_INST_GET(0); + const uint32_t line = POINTER_TO_UINT(arg); + const struct _isr_table_entry *entry; + uint32_t reg_val; + + reg_val = sys_read32(DEVICE_MMIO_GET(dev) + R9A08G045_NMI_NSCR); + if (!(reg_val & R9A08G045_NMI_NSCR_NSTAT)) { + LOG_DBG("intc_nmi: spurious irq %u", line); + return; + } + + entry = &_sw_isr_table[CONFIG_2ND_LVL_ISR_TBL_OFFSET + line]; + entry->isr(entry->arg); + + r9a08g045_intr_nmi_eoi(dev); +} + +static void r9a08g045_intr_eoi(const struct device *dev, uint32_t line) +{ + struct r9a08g045_intc_data *data = dev->data; + k_spinlock_key_t key; + uint32_t reg_val; + + if (data->f_irq_lvl & BIT(line)) { + return; + } + + /* clear non-level irq status only - invalid to clear for lvl */ + key = k_spin_lock(&data->rz_data.lock); + reg_val = sys_read32(DEVICE_MMIO_GET(dev) + R9A08G045_INTC_ISCR); + if (reg_val & BIT(line)) { + reg_val &= ~R9A08G045_INTC_ISCR_ISTAT(line); + sys_write32(reg_val, DEVICE_MMIO_GET(dev) + R9A08G045_INTC_ISCR); + reg_val = sys_read32(DEVICE_MMIO_GET(dev) + R9A08G045_INTC_ISCR); + } + k_spin_unlock(&data->rz_data.lock, key); +} + +static void r9a08g045_isr(const void *arg) +{ + const struct device *const dev = DEVICE_DT_INST_GET(0); + const uint32_t irq_idx = POINTER_TO_UINT(arg); + const struct _isr_table_entry *entry; + uint32_t reg_val; + uint32_t line; + + line = irq_idx - 1; + reg_val = sys_read32(DEVICE_MMIO_GET(dev) + R9A08G045_INTC_ISCR); + if (!(reg_val & BIT(line))) { + LOG_DBG("intc: spurious irq %u", line); + return; + } + + entry = &_sw_isr_table[CONFIG_2ND_LVL_ISR_TBL_OFFSET + irq_idx]; + entry->isr(entry->arg); + + r9a08g045_intr_eoi(dev, line); +} + +static void r9a08g045_intr_set_priority(const struct device *dev, unsigned int irq, + unsigned int prio, uint32_t flags) +{ + struct r9a08g045_intc_data *data = (struct r9a08g045_intc_data *)dev->data; + const struct intc_rz_cfg *cfg = (const struct intc_rz_cfg *)dev->config; + unsigned int parent_irq = intc_rz_intr_get_parent_irq(dev, irq); + k_spinlock_key_t key; + uint32_t reg_val; + uint32_t line; + + if (parent_irq >= cfg->num_lines) { + return; + } + + line = irq_from_level_2(irq); + + if (!line) { + r9a08g045_intr_nmi_set_type(dev, irq, flags); + return; + } + + /* adjust line - started from 1 in DT */ + line--; + data->f_irq_lvl &= ~BIT(line); + switch (flags) { + case IRQ_TYPE_LOW_LEVEL: + flags = R9A08G045_INTC_IITSR_IITSEL_LOW_LEVEL; + data->f_irq_lvl |= BIT(line); + break; + case IRQ_TYPE_EDGE_FALLING: + flags = R9A08G045_INTC_IITSR_IITSEL_EDGE_FALLING; + break; + case IRQ_TYPE_EDGE_RISING: + flags = R9A08G045_INTC_IITSR_IITSEL_EDGE_RISING; + break; + case IRQ_TYPE_EDGE_BOTH: + flags = R9A08G045_INTC_IITSR_IITSEL_EDGE_BOTH; + break; + default: + return; + } + + key = k_spin_lock(&data->rz_data.lock); + reg_val = sys_read32(DEVICE_MMIO_GET(dev) + R9A08G045_INTC_IITSR); + reg_val &= ~R9A08G045_INTC_IITSR_IITSEL(line, 0x3); + reg_val |= R9A08G045_INTC_IITSR_IITSEL(line, flags); + sys_write32(reg_val, DEVICE_MMIO_GET(dev) + R9A08G045_INTC_IITSR); + k_spin_unlock(&data->rz_data.lock, key); + + r9a08g045_intr_eoi(dev, line); +} + +static const struct irq_next_level_api r9a08g045_intc_next_lvl = { + .intr_enable = intc_rz_intr_enable, + .intr_disable = intc_rz_intr_disable, + .intr_get_state = intc_rz_intr_get_state, + .intr_set_priority = r9a08g045_intr_set_priority, + .intr_get_line_state = intc_rz_intr_get_line_state, +}; + +#define IRQ_CONFIGURE(n, inst, _isr, _isr_nmi) \ + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(inst, n, irq), DT_INST_IRQ_BY_IDX(inst, n, priority), \ + COND_CODE_0(n, (_isr_nmi), (_isr)), DT_INST_PROP_BY_IDX(inst, map, n), 0); + +#define CONFIGURE_ALL_IRQS(inst, n, _isr, _isr_nmi) \ + LISTIFY(n, IRQ_CONFIGURE, (), inst, _isr, _isr_nmi) + +static int r9a08g045_intc_init(const struct device *dev) +{ + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + CONFIGURE_ALL_IRQS(0, DT_NUM_IRQS(DT_DRV_INST(0)), r9a08g045_isr, r9a08g045_nmi_isr); + + return 0; +} + +BUILD_ASSERT(DT_NUM_IRQS(DT_DRV_INST(0)) == DT_INST_PROP_LEN(0, map), + "Number of items in interrupts and map should be the same"); + +static const struct intc_rz_cfg drv_cfg = { + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(0)), + + .num_lines = DT_NUM_IRQS(DT_DRV_INST(0)), + .line_map = FILL_LINE_MAP_CONFIG(0, DT_NUM_IRQS(DT_DRV_INST(0))), +}; + +static struct r9a08g045_intc_data drv_data; + +DEVICE_DT_INST_DEFINE(0, &r9a08g045_intc_init, NULL, + &drv_data, &drv_cfg, PRE_KERNEL_1, + CONFIG_INTC_R9A08G045_INIT_PRIORITY, &r9a08g045_intc_next_lvl); diff --git a/drivers/interrupt_controller/intc_rz_common.c b/drivers/interrupt_controller/intc_rz_common.c new file mode 100644 index 00000000000000..02914841ac33cc --- /dev/null +++ b/drivers/interrupt_controller/intc_rz_common.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2024 EPAM Systemss + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "intc_rz_common.h" + +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_r7s9210_intc) +#include + +#define INTC_RZ_INT_BASE (GIC_SPI_INT_BASE) +#else +#define INTC_RZ_INT_BASE (0) +#endif + +/* is this irq belongs to this intc if yes - return parent irq */ +unsigned int intc_rz_intr_get_parent_irq(const struct device *dev, unsigned int irq) +{ + const struct intc_rz_cfg *cfg = (const struct intc_rz_cfg *)dev->config; + unsigned int parent_line = irq_parent_level_2(irq) + INTC_RZ_INT_BASE; + unsigned int line; + + irq = irq_from_level_2(irq); + parent_line += irq; + + for (line = 0; line < cfg->num_lines; line++) { + if (cfg->line_map[line].line != irq) { + continue; + } + + if (cfg->line_map[line].parent_line == parent_line) { + return parent_line; + } + } + + return line; +} + +/* The driver can't enable IRQ by this driver, so lets request it from the parent driver. */ +void intc_rz_intr_enable(const struct device *dev, unsigned int irq) +{ + const struct intc_rz_cfg *cfg = (const struct intc_rz_cfg *)dev->config; + unsigned int parent_irq = intc_rz_intr_get_parent_irq(dev, irq); + + if (parent_irq >= cfg->num_lines) { + return; + } + + irq_enable(parent_irq); +} + +/* The driver can't disable IRQ by this driver, so lets request it from the parent driver. */ +void intc_rz_intr_disable(const struct device *dev, unsigned int irq) +{ + const struct intc_rz_cfg *cfg = (const struct intc_rz_cfg *)dev->config; + unsigned int parent_irq = intc_rz_intr_get_parent_irq(dev, irq); + + if (parent_irq >= cfg->num_lines) { + return; + } + + irq_disable(parent_irq); +} + +/** + * The driver can't determine the status of whether the IRQs on lines are enabled or not. + * So, let's request information from the parent driver. + */ +unsigned int intc_rz_intr_get_state(const struct device *dev) +{ + const struct intc_rz_cfg *cfg = (const struct intc_rz_cfg *)dev->config; + + for (unsigned int line = 0; line < cfg->num_lines; line++) { + if (irq_is_enabled(cfg->line_map[line].parent_line)) { + return 1; + } + } + + return 0; +} + +/** + * The driver can't determine the status of whether the IRQ on this line is enabled or not. + * Therefore, let's request this information from the parent driver. + */ +int intc_rz_intr_get_line_state(const struct device *dev, unsigned int irq) +{ + const struct intc_rz_cfg *cfg = (const struct intc_rz_cfg *)dev->config; + unsigned int parent_irq = intc_rz_intr_get_parent_irq(dev, irq); + + if (parent_irq >= cfg->num_lines) { + return 0; + } + + return irq_is_enabled(parent_irq); +} diff --git a/drivers/interrupt_controller/intc_rz_common.h b/drivers/interrupt_controller/intc_rz_common.h new file mode 100644 index 00000000000000..c2219e44d541e1 --- /dev/null +++ b/drivers/interrupt_controller/intc_rz_common.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 EPAM Systemss + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_RZ_COMMON_H_ +#define ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_RZ_COMMON_H_ + +struct intc_rz_line_cfg { + unsigned int line; + unsigned int parent_line; +}; + +struct intc_rz_cfg { + DEVICE_MMIO_ROM; /* Must be first */ + struct intc_rz_line_cfg *line_map; + unsigned int num_lines; +}; + +struct intc_rz_data { + DEVICE_MMIO_RAM; /* Must be first */ + struct k_spinlock lock; +}; + +#define FILL_ONE_LINE_MAP(n, inst) \ + { \ + DT_INST_PROP_BY_IDX(inst, map, n), \ + DT_INST_IRQ_BY_IDX(inst, n, irq), \ + } +#define FILL_LINE_MAP_CONFIG(inst, n) \ + (struct intc_rz_line_cfg []){LISTIFY(n, FILL_ONE_LINE_MAP, (,), inst)} + +unsigned int intc_rz_intr_get_parent_irq(const struct device *dev, unsigned int irq); +void intc_rz_intr_enable(const struct device *dev, unsigned int irq); +void intc_rz_intr_disable(const struct device *dev, unsigned int irq); +unsigned int intc_rz_intr_get_state(const struct device *dev); +int intc_rz_intr_get_line_state(const struct device *dev, unsigned int irq); + +#endif /* ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_RZ_COMMON_H_ */ diff --git a/drivers/ipm/CMakeLists.txt b/drivers/ipm/CMakeLists.txt index a6c41f845e43ef..1209f9d22c116b 100644 --- a/drivers/ipm/CMakeLists.txt +++ b/drivers/ipm/CMakeLists.txt @@ -8,6 +8,7 @@ zephyr_library_sources_ifdef(CONFIG_IPM_MCUX ipm_mcux.c) zephyr_library_sources_ifdef(CONFIG_IPM_IMX ipm_imx.c) zephyr_library_sources_ifdef(CONFIG_IPM_IMX_REV2 ipm_imx.c) zephyr_library_sources_ifdef(CONFIG_IPM_MHU ipm_mhu.c) +zephyr_library_sources_ifdef(CONFIG_IPM_RENESAS_MHU ipm_renesas_mhu.c) zephyr_library_sources_ifdef(CONFIG_IPM_STM32_IPCC ipm_stm32_ipcc.c) zephyr_library_sources_ifdef(CONFIG_IPM_NRFX ipm_nrfx_ipc.c) zephyr_library_sources_ifdef(CONFIG_IPM_STM32_HSEM ipm_stm32_hsem.c) diff --git a/drivers/ipm/Kconfig b/drivers/ipm/Kconfig index 81c64202427b57..2f6dfcecb3e534 100644 --- a/drivers/ipm/Kconfig +++ b/drivers/ipm/Kconfig @@ -15,6 +15,14 @@ config IPM_MHU help Driver for SSE 200 MHU (Message Handling Unit) +config IPM_RENESAS_MHU + bool "IPM Renesas MHU driver" + default y + depends on DT_HAS_RENESAS_MHU_ENABLED + help + Driver for Renesas messaging unit, + based on Renesas RZ series HW. + config IPM_NRFX bool "IPM NRF driver" default y diff --git a/drivers/ipm/ipm_renesas_mhu.c b/drivers/ipm/ipm_renesas_mhu.c new file mode 100644 index 00000000000000..3af1dad40b852b --- /dev/null +++ b/drivers/ipm/ipm_renesas_mhu.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(ipm_renesas_mhu, CONFIG_IPM_LOG_LEVEL); + +#define DT_DRV_COMPAT renesas_mhu + +enum msg_type { + MHU_SEND, + MHU_RSP +}; + +#define MHU_MAX_ID_VAL 0 + +#define INT_STS_OFF (0x0) +#define INT_SET_OFF (0x4) +#define INT_CLR_OFF (0x8) + +#define RSP_OFF (0x10) + +#define MSG_REG(dev, off) (DEVICE_MMIO_GET(dev) + off) +#define RSP_REG(dev, off) (DEVICE_MMIO_GET(dev) + RSP_OFF + off) + +struct mhu_config { + DEVICE_MMIO_ROM; /* Must be first */ + const struct device *clk_dev; + struct renesas_cpg_clk clk_mod; + const struct reset_dt_spec reset; + void (*irq_configure)(void); + enum msg_type type; + uint32_t shm_addr; + uint32_t shm_size; + uint16_t mhu_ch_size; +}; + +struct mhu_data { + DEVICE_MMIO_RAM; /* Must be first */ + ipm_callback_t cb; + void *user_data; + void *shm_tx; + void *shm_rx; + uint32_t shm_ch_size; + char *mhu_msg_buf; +}; + +#define DEV_CFG(_dev) ((const struct mhu_config *)(_dev)->config) +#define DEV_DATA(_dev) ((struct mhu_data *const)(_dev)->data) + +static void mhu_irq_handler(const struct device *dev) +{ + const struct mhu_config *cfg = DEV_CFG(dev); + struct mhu_data *data = DEV_DATA(dev); + mm_reg_t sts_off, clr_off; + + if (cfg->type == MHU_RSP) { + sts_off = MSG_REG(dev, INT_STS_OFF); + clr_off = MSG_REG(dev, INT_CLR_OFF); + } else { + sts_off = RSP_REG(dev, INT_STS_OFF); + clr_off = RSP_REG(dev, INT_CLR_OFF); + } + + if (sys_read32(sts_off) == 0) { + LOG_ERR("ERROR: Unexpected status\n"); + return; + }; + + /* Copy buffer only if cb was provided */ + if (data->cb && cfg->shm_addr) { + memcpy(data->mhu_msg_buf, data->shm_rx, cfg->mhu_ch_size); + } + + sys_write32(1, clr_off); + + if (data->cb) { + data->cb(dev, data->user_data, 0, data->mhu_msg_buf); + } +} + +static int mhu_send(const struct device *dev, int wait, uint32_t cpu_id, const void *buf, int size) +{ + const struct mhu_config *cfg = DEV_CFG(dev); + struct mhu_data *data = DEV_DATA(dev); + mm_reg_t sts_off, set_off; + + if (size > cfg->mhu_ch_size) { + return -EINVAL; + } + + if (cfg->type == MHU_SEND) { + sts_off = MSG_REG(dev, INT_STS_OFF); + set_off = MSG_REG(dev, INT_SET_OFF); + } else { + sts_off = RSP_REG(dev, INT_STS_OFF); + set_off = RSP_REG(dev, INT_SET_OFF); + } + + while (sys_read32(sts_off)) { + k_busy_wait(1); + }; + + if (cfg->shm_addr) { + if (buf && size) { + /* Put message to the shared memory */ + memcpy(data->shm_tx, buf, size); + } else { + /* cleanup memory if buffer was not set */ + memset(data->shm_tx, 0, cfg->mhu_ch_size); + } + } + + sys_write32(1, set_off); + + return 0; +} + +static void mhu_reg_callback(const struct device *dev, ipm_callback_t cb, void *user_data) +{ + struct mhu_data *data = DEV_DATA(dev); + + data->cb = cb; + data->user_data = user_data; +} + +static int mhu_init(const struct device *dev) +{ + int ret; + struct mhu_data *data = DEV_DATA(dev); + const struct mhu_config *cfg = DEV_CFG(dev); + + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + + if (device_is_ready(cfg->clk_dev)) { + ret = clock_control_on(cfg->clk_dev, (clock_control_subsys_t)&cfg->clk_mod); + if (ret < 0) { + LOG_ERR("Failed to configure clk"); + return ret; + } + } + + if (device_is_ready(cfg->reset.dev)) { + (void)reset_line_deassert_dt(&cfg->reset); + } + + if (cfg->shm_addr) { + data->shm_tx = (void *)(cfg->shm_addr); + data->shm_rx = (void *)(cfg->shm_addr + cfg->mhu_ch_size); + } + + cfg->irq_configure(); + return 0; +} + +static int mhu_set_enabled(const struct device *dev, int enable) +{ + ARG_UNUSED(dev); + ARG_UNUSED(enable); + return 0; +} + +static int mhu_max_data_size_get(const struct device *dev) +{ + const struct mhu_config *cfg = DEV_CFG(dev); + + ARG_UNUSED(dev); + + return cfg->mhu_ch_size; +} + +static uint32_t mhu_max_id_val_get(const struct device *dev) +{ + ARG_UNUSED(dev); + + return MHU_MAX_ID_VAL; +} + +static const struct ipm_driver_api mhu_driver_api = { + .send = mhu_send, + .register_callback = mhu_reg_callback, + .max_data_size_get = mhu_max_data_size_get, + .max_id_val_get = mhu_max_id_val_get, + .set_enabled = mhu_set_enabled, +}; + +#define MHU_SHM_SIZE(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, memory_region), \ + (DT_REG_SIZE(DT_INST_PHANDLE(n, memory_region))), (0)) + +#define MHU_SET_CLOCK(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, clocks), \ + (.clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_IDX(n, 0)), \ + .clk_mod.module = DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module), \ + .clk_mod.domain = DT_INST_CLOCKS_CELL_BY_IDX(n, 0, domain),), \ + ()) + +#define MHU_SET_RESET(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, resets), (.reset = RESET_DT_SPEC_INST_GET(n),), ()) + +#define RENESAS_MHU_INIT(n) \ + \ + static char mhu_buf_##n[(MHU_SHM_SIZE(n) >> 1) + 1] = {}; \ + \ + static void mhu_irq_##n##_config(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, 0, irq), DT_INST_IRQ_BY_IDX(n, 0, priority), \ + mhu_irq_handler, DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQ_BY_IDX(n, 0, irq)); \ + } \ + \ + static const struct mhu_config mhu_##n##_conf = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ + MHU_SET_CLOCK(n) MHU_SET_RESET(n).irq_configure = mhu_irq_##n##_config, \ + .type = DT_INST_PROP(n, renesas_mhu_type), \ + .shm_addr = COND_CODE_1(DT_INST_NODE_HAS_PROP(n, memory_region), \ + (DT_REG_ADDR(DT_INST_PHANDLE(n, memory_region))), (0)), \ + .shm_size = MHU_SHM_SIZE(n), \ + .mhu_ch_size = MHU_SHM_SIZE(n) >> 1, \ + }; \ + \ + static struct mhu_data mhu_##n##_data = { \ + .mhu_msg_buf = mhu_buf_##n, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, &mhu_init, NULL, &mhu_##n##_data, &mhu_##n##_conf, PRE_KERNEL_1, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &mhu_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(RENESAS_MHU_INIT); diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index 9bb20cb72436c8..508c98050a3797 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -36,3 +36,4 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_EMSDP pinctrl_emsdp.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_TI_CC32XX pinctrl_ti_cc32xx.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_NUMAKER pinctrl_numaker.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_QUICKLOGIC_EOS_S3 pinctrl_eos_s3.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_RZG3S pinctrl_rzg3s.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index c39a36bda8dec8..7f00c1d9267505 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -43,6 +43,7 @@ source "drivers/pinctrl/Kconfig.nrf" source "drivers/pinctrl/Kconfig.rcar" source "drivers/pinctrl/Kconfig.rpi_pico" source "drivers/pinctrl/Kconfig.rza2" +source "drivers/pinctrl/Kconfig.rzg3s" source "drivers/pinctrl/Kconfig.sam" source "drivers/pinctrl/Kconfig.sam0" source "drivers/pinctrl/Kconfig.stm32" diff --git a/drivers/pinctrl/Kconfig.rzg3s b/drivers/pinctrl/Kconfig.rzg3s new file mode 100644 index 00000000000000..7a14f75cd0e7b5 --- /dev/null +++ b/drivers/pinctrl/Kconfig.rzg3s @@ -0,0 +1,19 @@ +# opyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_RZG3S + bool "Pin controller driver for Renesas RZ G3S series" + default y + depends on DT_HAS_RENESAS_R9A08G045_CPG_MSSR_ENABLED + help + Enable pin controller driver for Renesas RZ G3S series + +if PINCTRL_RZG3S + +config PINCTRL_RZG3S_INIT_PRIORITY + int "RZ G3S pinctrl init priority" + default 35 + help + Device driver initialization priority. + +endif #PINCTRL_RZG3S diff --git a/drivers/pinctrl/pinctrl_rzg3s.c b/drivers/pinctrl/pinctrl_rzg3s.c new file mode 100644 index 00000000000000..8edd162a92185b --- /dev/null +++ b/drivers/pinctrl/pinctrl_rzg3s.c @@ -0,0 +1,797 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_r9a08g045_pinctrl + +#include +#include + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(pinctrl_rzg3s, CONFIG_PINCTRL_LOG_LEVEL); + +#define LOG_DEV_ERR(dev, format, ...) LOG_ERR("%s:"#format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_WRN(dev, format, ...) LOG_WRN("%s:"#format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_INF(dev, format, ...) LOG_INF("%s:"#format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_DBG(dev, format, ...) LOG_DBG("%s:"#format, (dev)->name, ##__VA_ARGS__) + +#define RZG3S_PORT0 0x20 +#define RZG3S_PORT5 0x21 +#define RZG3S_PORT6 0x22 +#define RZG3S_PORT11 0x23 +#define RZG3S_PORT12 0x24 +#define RZG3S_PORT13 0x25 +#define RZG3S_PORT14 0x26 +#define RZG3S_PORT15 0x27 +#define RZG3S_PORT16 0x28 +#define RZG3S_PORT17 0x29 +#define RZG3S_PORT18 0x2A +#define RZG3S_PORT1 0x30 +#define RZG3S_PORT2 0x31 +#define RZG3S_PORT3 0x32 +#define RZG3S_PORT4 0x33 +#define RZG3S_PORT7 0x34 +#define RZG3S_PORT8 0x35 +#define RZG3S_PORT9 0x36 +#define RZG3S_PORT10 0x37 + +#define RZG3S_PORT_NUM 19 + +/* + * n indicates number of pins in the port, a is the register index + * and f is pin configuration capabilities supported. + */ +#define RZG3S_GPIO_PORT_DEF(num_pins, reg_ofs) (((num_pins) << 16) | (reg_ofs)) +#define RZG3S_GPIO_PORT_GET_PINCNT(p) (((p) & GENMASK(31, 16)) >> 16) +#define RZG3S_GPIO_PORT_GET_REG(x) (((x) & GENMASK(15, 0))) + +static const uint32_t rzg3s_pinctrl_ports[RZG3S_PORT_NUM] = { + RZG3S_GPIO_PORT_DEF(4, RZG3S_PORT0), + RZG3S_GPIO_PORT_DEF(5, RZG3S_PORT1), + RZG3S_GPIO_PORT_DEF(4, RZG3S_PORT2), + RZG3S_GPIO_PORT_DEF(4, RZG3S_PORT3), + RZG3S_GPIO_PORT_DEF(6, RZG3S_PORT4), + RZG3S_GPIO_PORT_DEF(5, RZG3S_PORT5), + RZG3S_GPIO_PORT_DEF(5, RZG3S_PORT6), + RZG3S_GPIO_PORT_DEF(5, RZG3S_PORT7), + RZG3S_GPIO_PORT_DEF(5, RZG3S_PORT8), + RZG3S_GPIO_PORT_DEF(4, RZG3S_PORT9), + RZG3S_GPIO_PORT_DEF(5, RZG3S_PORT10), + RZG3S_GPIO_PORT_DEF(4, RZG3S_PORT11), + RZG3S_GPIO_PORT_DEF(2, RZG3S_PORT12), + RZG3S_GPIO_PORT_DEF(5, RZG3S_PORT13), + RZG3S_GPIO_PORT_DEF(3, RZG3S_PORT14), + RZG3S_GPIO_PORT_DEF(4, RZG3S_PORT15), + RZG3S_GPIO_PORT_DEF(2, RZG3S_PORT16), + RZG3S_GPIO_PORT_DEF(4, RZG3S_PORT17), + RZG3S_GPIO_PORT_DEF(6, RZG3S_PORT18), +}; + +#define R_PM(n) (0x0100 + (n) * 2) +#define R_PMC(n) (0x0200 + (n)) +#define R_PFC(n) (0x0400 + (n) * 4) +#define R_IOLH(n) (0x1000 + (n) * 8) +#define R_IEN(n) (0x1800 + (n) * 8) +#define R_PUPD(n) (0x1C00 + (n) * 8) +#define R_PWPR (0x3000) + +#define R_FILONOFF(n) (0x2000 + (n) * 8) +#define R_FILNUM(n) (0x2400 + (n) * 8) +#define R_FILCLKSEL(n) (0x2800 + (n) * 8) + +/* R_PWPR */ +#define R_PWPR_PFSWE BIT(6) /* PFSWE Bit Enable */ +#define R_PWPR_B0WI BIT(7) /* PFSWE Bit Disable */ + +/* R_PM Port Mode Register */ +#define R_PM_MODE_MASK GENMASK(1, 0) +#define R_PM_MODE_VAL(pin, val) (((val) & R_PM_MODE_MASK) << ((pin) << 1)) + +#define R_PM_MODE_HI_Z 0x0 +#define R_PM_MODE_IN BIT(0) +#define R_PM_MODE_OUT BIT(1) +#define R_PM_MODE_OUT_IN (R_PM_MODE_IN | R_PM_MODE_OUT) + +/* R_PFC Port Function Control Register */ +#define R_PFC_FUNC_MASK GENMASK(2, 0) +#define R_PFC_FUNC_VAL(pin, val) (((val) & R_PFC_FUNC_MASK) << ((pin) << 2)) + +/* R_PUPD Pull-Up/Pull-Down Switching Register */ +#define R_PUPD_MASK GENMASK(1, 0) +#define R_PUPD_VAL(pin, val) (((val) & R_PUPD_MASK) << ((pin) << 3)) +#define R_PUPD_NONE 0x0 +#define R_PUPD_UP BIT(0) +#define R_PUPD_DOWN BIT(1) + +/* R_IOLH Driving Ability Control Register */ +#define R_IOLH_MASK GENMASK(1, 0) +#define R_IOLH_VAL(pin, val) (((val) & R_IOLH_MASK) << ((pin) << 3)) + +/* R_IEN Input Enable Control Register */ +#define R_IEN_MASK BIT(0) +#define R_IEN_VAL(pin, val) (((val) & R_IEN_MASK) << ((pin) << 3)) + +/* R_FILONOFF Digital Noise Filter Switching Register */ +#define R_FILONOFF_MASK BIT(0) +#define R_FILONOFF_VAL(pin, val) (((val) & R_IEN_MASK) << ((pin) * 8)) + +/* R_FILNUM Digital Noise Filter Number Register */ +#define R_FILNUM_MASK GENMASK(1, 0) +#define R_FILNUM_VAL(pin, val) (((val) & R_FILNUM_MASK) << ((pin) * 8)) + +/* R_FILCLKSEL Digital Noise Filter Clock Selection Register */ +#define R_FILCLKSEL_MASK GENMASK(1, 0) +#define R_FILCLKSEL_VAL(pin, val) (((val) & R_FILCLKSEL_MASK) << ((pin) * 8)) + +#define R_SD_CH0_POC (0x3004) +#define R_SD_CH1_POC (0x3008) +#define R_XSPI_POC (0x300C) +#define R_ETH0_POC (0x3010) +#define R_ETH1_POC (0x3014) +#define R_ETH_MODE (0x3018) +#define R_I3C_SET (0x301C) +#define R_XSPI_HI_Z (0x3020) + +typedef int (*rzg3s_pinctrl_grp_handler)(const struct device *dev, + const struct pinctrl_soc_rzg3s_grp *grp); + +#define SPIN_CFG_IOLH BIT(0) +#define SPIN_CFG_IEN BIT(1) +#define SPIN_CFG_FILONOFF BIT(2) +#define SPIN_CFG_ETH_OEN BIT(3) + +struct rzg3s_pinctrl_spin_cfg { + uint16_t reg_idx; /* IEN/IOLH/FILxx registers index */ + uint8_t reg_pin; /* IEN/IOLH/FILxx registers pin (p * 8) */ + uint8_t cfg; /* pin configuration capabilities supported */ +}; + +#define SPIN_DEF(_id, _reg_idx, _reg_pin, _cfg) \ + [_id] = {.reg_idx = _reg_idx, .reg_pin = _reg_pin, .cfg = _cfg} + +static const struct rzg3s_pinctrl_spin_cfg rzg3s_pinctrl_spins[PINCTRL_RZG3S_SPIN_LAST] = { + SPIN_DEF(PINCTRL_RZG3S_NMI_SPIN, 0x0, 0, (SPIN_CFG_FILONOFF)), + SPIN_DEF(PINCTRL_RZG3S_TMS_SWDIO_SPIN, 0x1, 0, (SPIN_CFG_IEN | SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_TDO_SPIN, 0x1, 1, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_SPCLK_SPIN, 0x4, 0, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_RESET_SPIN, 0x4, 1, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_WP_SPIN, 0x4, 2, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_DS_SPIN, 0x4, 3, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_CS0_SPIN, 0x4, 4, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_CS1_SPIN, 0x4, 5, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_IO0_SPIN, 0x5, 0, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_IO1_SPIN, 0x5, 1, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_IO2_SPIN, 0x5, 2, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_IO3_SPIN, 0x5, 3, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_IO4_SPIN, 0x5, 4, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_IO5_SPIN, 0x5, 5, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_IO6_SPIN, 0x5, 6, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_XSPI_IO7_SPIN, 0x5, 7, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_WDTOVF_PERROUT_SPIN, 0x6, 0, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_SD0_CLK_SPIN, 0x10, 0, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_SD0_CMD_SPIN, 0x10, 1, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD0_RST_SPIN, 0x10, 2, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_SD0_DATA0_SPIN, 0x11, 0, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD0_DATA1_SPIN, 0x11, 1, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD0_DATA2_SPIN, 0x11, 2, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD0_DATA3_SPIN, 0x11, 3, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD0_DATA4_SPIN, 0x11, 4, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD0_DATA5_SPIN, 0x11, 5, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD0_DATA6_SPIN, 0x11, 6, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD0_DATA7_SPIN, 0x11, 7, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD1_CLK_SPIN, 0x12, 0, (SPIN_CFG_IOLH)), + SPIN_DEF(PINCTRL_RZG3S_SD1_CMD_SPIN, 0x12, 1, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD1_DATA0_SPIN, 0x13, 0, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD1_DATA1_SPIN, 0x13, 1, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD1_DATA2_SPIN, 0x13, 2, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD1_DATA3_SPIN, 0x13, 3, (SPIN_CFG_IOLH | SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_AUDIO_CLK1_SPIN, 0x2, 0, (SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_AUDIO_CLK2_SPIN, 0x2, 1, (SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_I3C_SDA_SPIN, 0x9, 0, (SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_I3C_SCL_SPIN, 0x9, 1, (SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD2_CMD_SPIN, 0x23, 1, (SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD2_DATA0_SPIN, 0x23, 2, (SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD2_DATA1_SPIN, 0x23, 3, (SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD2_DATA2_SPIN, 0x24, 0, (SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_SD2_DATA3_SPIN, 0x24, 1, (SPIN_CFG_IEN)), + SPIN_DEF(PINCTRL_RZG3S_ET0_TXC_TX_CLK_SPIN, 0x30, 0, (SPIN_CFG_IEN | SPIN_CFG_ETH_OEN)), + SPIN_DEF(PINCTRL_RZG3S_ET1_TXC_TX_CLK_SPIN, 0x34, 0, (SPIN_CFG_IEN | SPIN_CFG_ETH_OEN)), + SPIN_DEF(PINCTRL_RZG3S_ET0_TX_CTL_TX_EN_SPIN, 0, 0, (SPIN_CFG_ETH_OEN)), + SPIN_DEF(PINCTRL_RZG3S_ET1_TX_CTL_TX_EN_SPIN, 0, 0, (SPIN_CFG_ETH_OEN)), +}; + +struct rzg3s_pinctrl_cfg { + DEVICE_MMIO_NAMED_ROM(pinctrl); +}; + +struct rzg3s_pinctrl_data { + DEVICE_MMIO_NAMED_ROM(pinctrl); + + struct k_spinlock lock; +}; + +#define DEV_DATA(dev) ((struct rzg3s_pinctrl_data *)((dev)->data)) +#define DEV_CFG(dev) ((struct rzg3s_pinctrl_cfg *)((dev)->config)) + +static uint16_t rzg3s_pinctrl_port_get_reg(uint8_t port) +{ + return RZG3S_GPIO_PORT_GET_REG(rzg3s_pinctrl_ports[port]); +} + +static uint16_t rzg3s_pinctrl_port_get_pinnum(uint8_t port) +{ + return RZG3S_GPIO_PORT_GET_PINCNT(rzg3s_pinctrl_ports[port]); +} + +static void rzg3s_pinctrl_pfc_we(const struct device *dev) +{ + /* PFS Register Write Enable B0WI=0 R_PFSWE=1*/ + sys_write8(0x00, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PWPR); + sys_write8(R_PWPR_PFSWE, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PWPR); +} + +static void rzg3s_pinctrl_pfc_wd(const struct device *dev) +{ + /* PFS Register Write Protect B0WI=1 R_PFSWE=0 */ + sys_write8(0x00, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PWPR); + sys_write8(R_PWPR_B0WI, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PWPR); +} + +static void rzg3s_pinctrl_pfc_set(const struct device *dev, + const struct pinctrl_soc_rzg3s_pinmux *pinmux) +{ + uint16_t port_reg = rzg3s_pinctrl_port_get_reg(pinmux->port); + uint32_t reg32; + uint16_t reg16; + uint8_t reg8; + + /* Set pin to 'Non-use (Hi-z input protection)' */ + reg16 = sys_read16(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PM(port_reg)); + reg16 &= ~R_PM_MODE_VAL(pinmux->pin, R_PM_MODE_MASK); + sys_write16(reg16, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PM(port_reg)); + + /* switch to GPIO (temp) */ + reg8 = sys_read8(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PMC(port_reg)); + reg8 &= ~BIT(pinmux->pin); + sys_write8(reg8, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PMC(port_reg)); + + if (pinmux->func == PINCTRL_RZG3S_FUNC_GPIO) { + return; + } + + rzg3s_pinctrl_pfc_we(dev); + + /* Set Pin function */ + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PFC(port_reg)); + reg32 &= ~R_PFC_FUNC_VAL(pinmux->pin, R_PFC_FUNC_MASK); + reg32 |= R_PFC_FUNC_VAL(pinmux->pin, (pinmux->func - 1)); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PFC(port_reg)); + + rzg3s_pinctrl_pfc_wd(dev); + + /* Port Mode : Peripheral module pin functions */ + reg8 = sys_read8(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PMC(port_reg)); + reg8 |= BIT(pinmux->pin); + sys_write8(reg8, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PMC(port_reg)); +} + +static void rzg3s_pinctrl_pupd_set(const struct device *dev, + const struct pinctrl_soc_rzg3s_pinmux *pinmux) +{ + uint16_t port_reg = rzg3s_pinctrl_port_get_reg(pinmux->port); + uint8_t pin = pinmux->pin; + uint8_t pull = R_PUPD_NONE; + uint32_t reg32; + + if (pinmux->pull_pin_default) { + return; + } + + if (pinmux->pull_up) { + pull = R_PUPD_UP; + } else if (pinmux->pull_down) { + pull = R_PUPD_DOWN; + } + + /* handle _L/_H for 32-bit register read/write */ + if (pin >= 4) { + pin -= 4; + port_reg += 4; + } + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PUPD(port_reg)); + reg32 &= ~R_PUPD_VAL(pin, R_PUPD_MASK); + reg32 |= R_PUPD_VAL(pin, pull); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_PUPD(port_reg)); +} + +static void rzg3s_pinctrl_pinmux_iolh_set(const struct device *dev, + const struct pinctrl_soc_rzg3s_pinmux *pinmux) +{ + uint16_t port_reg = rzg3s_pinctrl_port_get_reg(pinmux->port); + uint8_t pin = pinmux->pin; + uint8_t iolh = pinmux->drive_strength_microamp; + uint32_t reg32; + + if (!pinmux->drive_strength) { + return; + } + + /* handle _L/_H for 32-bit register read/write */ + if (pin >= 4) { + pin -= 4; + port_reg += 4; + } + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_IOLH(port_reg)); + reg32 &= ~R_IOLH_VAL(pin, R_IOLH_MASK); + reg32 |= R_IOLH_VAL(pin, iolh); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_IOLH(port_reg)); +} + +static void rzg3s_pinctrl_filter_set(const struct device *dev, uint16_t port_reg, uint8_t pin, + uint8_t filnum, uint8_t filclksel) +{ + uint32_t reg32; + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_FILNUM(port_reg)); + reg32 &= ~R_FILNUM_VAL(pin, R_IOLH_MASK); + reg32 |= R_FILNUM_VAL(pin, filnum); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_FILNUM(port_reg)); + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_FILCLKSEL(port_reg)); + reg32 &= ~R_FILCLKSEL_VAL(pin, R_IOLH_MASK); + reg32 |= R_FILCLKSEL_VAL(pin, filclksel); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_FILCLKSEL(port_reg)); + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_FILONOFF(port_reg)); + reg32 &= ~R_FILONOFF_VAL(pin, R_IOLH_MASK); + reg32 |= R_FILONOFF_VAL(pin, 0x1); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_FILONOFF(port_reg)); +} + +static void rzg3s_pinctrl_pinmux_filter_set(const struct device *dev, + const struct pinctrl_soc_rzg3s_pinmux *pinmux) +{ + uint16_t port_reg = rzg3s_pinctrl_port_get_reg(pinmux->port); + uint8_t pin = pinmux->pin; + + if (!pinmux->filonoff) { + return; + } + + /* handle _L/_H for 32-bit register read/write */ + if (pin >= 4) { + pin -= 4; + port_reg += 4; + } + + rzg3s_pinctrl_filter_set(dev, port_reg, pin, pinmux->filnum, pinmux->filclksel); +} + +static int rzg3s_pinctrl_pinmux(const struct device *dev, + const struct pinctrl_soc_rzg3s_pinmux *pinmux) +{ + int ret = 0; + + if (pinmux->port >= RZG3S_PORT_NUM) { + LOG_DEV_ERR(dev, "port:%u:%u func:%u invalid port", + pinmux->port, pinmux->pin, pinmux->func); + return -EINVAL; + } + if (pinmux->pin >= rzg3s_pinctrl_port_get_pinnum(pinmux->port)) { + LOG_DEV_ERR(dev, "port:%u:%u func:%u invalid pin", + pinmux->port, pinmux->pin, pinmux->func); + return -EINVAL; + } + if (pinmux->func > (R_PFC_FUNC_MASK + 1)) { + LOG_DEV_ERR(dev, "port:%u:%u invalid func:%u", + pinmux->port, pinmux->pin, pinmux->func); + return -EINVAL; + } + if (pinmux->pull_up && pinmux->pull_down) { + LOG_DEV_ERR(dev, "port:%u:%u func:%u pull up/down err", + pinmux->port, pinmux->pin, pinmux->func); + return -EINVAL; + } + if (pinmux->drive_strength && pinmux->drive_strength_microamp > R_IOLH_MASK) { + LOG_DEV_ERR(dev, "port:%u:%u func:%u drive-strength invalid", + pinmux->port, pinmux->pin, pinmux->func); + return -EINVAL; + } + + rzg3s_pinctrl_pfc_set(dev, pinmux); + rzg3s_pinctrl_pupd_set(dev, pinmux); + rzg3s_pinctrl_pinmux_iolh_set(dev, pinmux); + rzg3s_pinctrl_pinmux_filter_set(dev, pinmux); + return ret; +} + +static int rzg3s_pinctrl_grp_poc_raw(const struct device *dev, + const struct pinctrl_soc_rzg3s_grp *grp) +{ + uint32_t reg_shift = 0; + uint32_t reg_ofs; + uint32_t reg_msk; + uint32_t reg32; + + if (!grp->f_power_source) { + return 0; + } + + switch (grp->grp) { + case PINCTRL_RZG3S_ETH0_GRP: + reg_ofs = R_ETH0_POC; + reg_msk = 0x3; + break; + case PINCTRL_RZG3S_ETH1_GRP: + reg_ofs = R_ETH1_POC; + reg_msk = 0x3; + break; + case PINCTRL_RZG3S_SD_CH0_GRP: + reg_ofs = R_SD_CH0_POC; + reg_msk = 0x1; + break; + case PINCTRL_RZG3S_SD_CH1_GRP: + reg_ofs = R_SD_CH1_POC; + reg_msk = 0x1; + break; + case PINCTRL_RZG3S_XSPI_GRP: + reg_ofs = R_XSPI_POC; + reg_msk = 0x3; + break; + case PINCTRL_RZG3S_I3C_GRP: + reg_ofs = R_I3C_SET; + reg_msk = 0x1; + reg_shift = 0x1; + break; + default: + return -EINVAL; + } + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + reg_ofs); + reg32 &= ~reg_msk << reg_shift; + reg32 |= grp->power_source << reg_shift; + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + reg_ofs); + + return 0; +} + +static int rzg3s_pinctrl_grp_poc(const struct device *dev, const struct pinctrl_soc_rzg3s_grp *grp) +{ + if (grp->bias_disable || + grp->bias_high_impedance || + grp->low_power_disable || + grp->low_power_enable) { + LOG_DEV_ERR(dev, "grp:%u: invalid cfg", grp->grp); + return -EINVAL; + } + + return rzg3s_pinctrl_grp_poc_raw(dev, grp); +} + +static int rzg3s_pinctrl_grp_xspi(const struct device *dev, + const struct pinctrl_soc_rzg3s_grp *grp) +{ + uint32_t reg_ofs = R_XSPI_HI_Z; + uint32_t reg32; + int ret; + + if (grp->low_power_disable || grp->low_power_enable) { + LOG_DEV_ERR(dev, "grp:%u: invalid cfg", grp->grp); + return -EINVAL; + } + + if (grp->bias_disable && grp->bias_high_impedance) { + LOG_DEV_ERR(dev, "grp:%u: invalid Hi-Z cfg", grp->grp); + return -EINVAL; + } + + ret = rzg3s_pinctrl_grp_poc_raw(dev, grp); + if (ret) { + return ret; + } + + if (!grp->bias_disable && !grp->bias_high_impedance) { + return 0; + } + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + reg_ofs); + reg32 &= ~BIT(0); + if (grp->bias_disable) { + reg32 |= BIT(0); + } + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + reg_ofs); + + return 0; +} + +static int rzg3s_pinctrl_grp_i3c(const struct device *dev, const struct pinctrl_soc_rzg3s_grp *grp) +{ + uint32_t reg_ofs = R_I3C_SET; + uint32_t reg32; + int ret; + + if (grp->bias_disable || grp->bias_high_impedance) { + LOG_DEV_ERR(dev, "grp:%u: invalid cfg", grp->grp); + return -EINVAL; + } + + if (grp->low_power_disable && grp->low_power_enable) { + LOG_DEV_ERR(dev, "grp:%u: invalid low_power cfg", grp->grp); + return -EINVAL; + } + + ret = rzg3s_pinctrl_grp_poc_raw(dev, grp); + if (ret) { + return ret; + } + + if (!grp->low_power_disable && !grp->low_power_enable) { + return 0; + } + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + reg_ofs); + reg32 &= ~BIT(0); + if (grp->low_power_disable) { + reg32 |= BIT(0); + } + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + reg_ofs); + + return 0; +} + +static const rzg3s_pinctrl_grp_handler rzg3s_pinctrl_grps[PINCTRL_RZG3S_GRP_LAST] = { + [PINCTRL_RZG3S_ETH0_GRP] = rzg3s_pinctrl_grp_poc, + [PINCTRL_RZG3S_ETH1_GRP] = rzg3s_pinctrl_grp_poc, + [PINCTRL_RZG3S_SD_CH0_GRP] = rzg3s_pinctrl_grp_poc, + [PINCTRL_RZG3S_SD_CH1_GRP] = rzg3s_pinctrl_grp_poc, + [PINCTRL_RZG3S_SD_CH1_GRP] = rzg3s_pinctrl_grp_poc, + [PINCTRL_RZG3S_XSPI_GRP] = rzg3s_pinctrl_grp_xspi, + [PINCTRL_RZG3S_I3C_GRP] = rzg3s_pinctrl_grp_i3c, +}; + +static int rzg3s_pinctrl_pingrp(const struct device *dev, const struct pinctrl_soc_rzg3s_grp *grp) +{ + if (grp->grp >= PINCTRL_RZG3S_GRP_LAST) { + LOG_DEV_ERR(dev, "grp:%u: invalid group", grp->grp); + return -EINVAL; + } + + return rzg3s_pinctrl_grps[grp->grp](dev, grp); +} + +static int rzg3s_pinctrl_spin_iolh_set(const struct device *dev, + const struct pinctrl_soc_rzg3s_spin *spin) +{ + const struct rzg3s_pinctrl_spin_cfg *spin_cfg = &rzg3s_pinctrl_spins[spin->spin]; + uint8_t iolh = spin->drive_strength_microamp; + uint16_t port_reg = spin_cfg->reg_idx; + uint8_t pin = spin_cfg->reg_pin; + uint32_t reg32; + + if (!spin->drive_strength) { + return 0; + } + + if (spin->drive_strength && !(spin_cfg->cfg & SPIN_CFG_IOLH)) { + LOG_DEV_ERR(dev, "spin:%u: invalid drive-strength cfg", spin->spin); + return -EINVAL; + } + + /* handle _L/_H for 32-bit register read/write */ + if (pin >= 4) { + pin -= 4; + port_reg += 4; + } + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_IOLH(port_reg)); + reg32 &= ~R_IOLH_VAL(pin, R_IOLH_MASK); + reg32 |= R_IOLH_VAL(pin, iolh); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_IOLH(port_reg)); + return 0; +} + +static int rzg3s_pinctrl_spin_ien_set(const struct device *dev, + const struct pinctrl_soc_rzg3s_spin *spin) +{ + const struct rzg3s_pinctrl_spin_cfg *spin_cfg = &rzg3s_pinctrl_spins[spin->spin]; + uint8_t iolh = spin->drive_strength_microamp; + uint16_t port_reg = spin_cfg->reg_idx; + uint8_t pin = spin_cfg->reg_pin; + uint32_t reg32; + + if (!spin->input_disable && !spin->input_enable) { + return 0; + } + + if (spin->input_disable && spin->input_enable) { + LOG_DEV_ERR(dev, "spin:%u: invalid input-disable|enable cfg", spin->spin); + return -EINVAL; + } + + if (!(spin_cfg->cfg & SPIN_CFG_IEN)) { + LOG_DEV_ERR(dev, "spin:%u: input-disable|enable not supported", spin->spin); + return -EINVAL; + } + + /* handle _L/_H for 32-bit register read/write */ + if (pin >= 4) { + pin -= 4; + port_reg += 4; + } + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_IEN(port_reg)); + reg32 &= ~R_IEN_VAL(pin, R_IEN_MASK); + reg32 |= R_IEN_VAL(pin, iolh); + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_IEN(port_reg)); + return 0; +} + +static int rzg3s_pinctrl_spin_oen_set(const struct device *dev, + const struct pinctrl_soc_rzg3s_spin *spin) +{ + const struct rzg3s_pinctrl_spin_cfg *spin_cfg = &rzg3s_pinctrl_spins[spin->spin]; + uint8_t pin; + uint32_t reg32; + + if (!spin->input_enable && !spin->output_enable) { + return 0; + } + + if (spin->spin == PINCTRL_RZG3S_ET0_TXC_TX_CLK_SPIN) { + pin = BIT(0); + } else if (spin->spin == PINCTRL_RZG3S_ET1_TXC_TX_CLK_SPIN) { + pin = BIT(1); + } else if (spin->spin == PINCTRL_RZG3S_ET0_TX_CTL_TX_EN_SPIN) { + pin = BIT(2); + } else if (spin->spin == PINCTRL_RZG3S_ET1_TX_CTL_TX_EN_SPIN) { + pin = BIT(3); + } else { + return 0; + } + + if (spin->input_enable && spin->output_enable) { + LOG_DEV_ERR(dev, "spin:%u:oen: invalid input-enable|output-enable cfg", spin->spin); + return -EINVAL; + } + + if (!(spin_cfg->cfg & SPIN_CFG_ETH_OEN)) { + LOG_DEV_ERR(dev, + "spin:%u:oen input-enable|output-enable not supported", spin->spin); + return -EINVAL; + } + + reg32 = sys_read32(DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_ETH_MODE); + reg32 &= ~pin; + if (spin->input_enable) { + reg32 |= pin; + } + sys_write32(reg32, DEVICE_MMIO_NAMED_GET(dev, pinctrl) + R_ETH_MODE); + return 0; +} + +static int rzg3s_pinctrl_spin_filter_set(const struct device *dev, + const struct pinctrl_soc_rzg3s_spin *spin) +{ + const struct rzg3s_pinctrl_spin_cfg *spin_cfg = &rzg3s_pinctrl_spins[spin->spin]; + uint16_t port_reg = spin_cfg->reg_idx; + uint8_t pin = spin_cfg->reg_pin; + + if (!spin->filonoff) { + return 0; + } + + if (!(spin_cfg->cfg & SPIN_CFG_FILONOFF)) { + LOG_DEV_ERR(dev, "spin:%u: invalid digital noise filter cfg", spin->spin); + return -EINVAL; + } + + /* handle _L/_H for 32-bit register read/write */ + if (pin >= 4) { + pin -= 4; + port_reg += 4; + } + + rzg3s_pinctrl_filter_set(dev, port_reg, pin, spin->filnum, spin->filclksel); + + return 0; +} + +static int rzg3s_pinctrl_spin(const struct device *dev, const struct pinctrl_soc_rzg3s_spin *spin) +{ + int ret; + + if (spin->spin >= PINCTRL_RZG3S_SPIN_LAST) { + LOG_DEV_ERR(dev, "spin:%u: invalid group", spin->spin); + return -EINVAL; + } + + ret = rzg3s_pinctrl_spin_iolh_set(dev, spin); + if (ret) { + return ret; + } + + ret = rzg3s_pinctrl_spin_ien_set(dev, spin); + if (ret) { + return ret; + } + + ret = rzg3s_pinctrl_spin_oen_set(dev, spin); + if (ret) { + return ret; + } + + return rzg3s_pinctrl_spin_filter_set(dev, spin); +} + +static int rzg3s_pinctrl_configure_pin(const struct device *dev, const pinctrl_soc_pin_t *pin) +{ + struct rzg3s_pinctrl_data *data = DEV_DATA(dev); + k_spinlock_key_t key; + int ret = 0; + + key = k_spin_lock(&data->lock); + + switch (pin->type) { + case PINCTRL_RZG3S_TYPE_PINMUX: + ret = rzg3s_pinctrl_pinmux(dev, &pin->pinmux); + break; + case PINCTRL_RZG3S_TYPE_SPIN: + ret = rzg3s_pinctrl_spin(dev, &pin->spin); + break; + case PINCTRL_RZG3S_TYPE_GRP: + ret = rzg3s_pinctrl_pingrp(dev, &pin->grp); + break; + default: + ret = -EOPNOTSUPP; + break; + } + + k_spin_unlock(&data->lock, key); + + return ret; +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + const struct device *dev = DEVICE_DT_INST_GET(0); + int ret = 0; + + ARG_UNUSED(reg); + while (pin_cnt-- > 0U) { + ret = rzg3s_pinctrl_configure_pin(dev, pins++); + if (ret < 0) { + break; + } + } + + return ret; +} + +static int rzg3s_pinctrl_init(const struct device *dev) +{ + DEVICE_MMIO_NAMED_MAP(dev, pinctrl, K_MEM_CACHE_NONE); + return 0; +} + +#define RZG3S_PINCTRL_INIT(inst) \ + static struct rzg3s_pinctrl_data rzg3s_pinctrl_##inst##_data = {}; \ + \ + static const struct rzg3s_pinctrl_cfg rzg3s_pinctrl_##inst##_cfg = { \ + DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(pinctrl, DT_DRV_INST(inst)), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, rzg3s_pinctrl_init, NULL, &rzg3s_pinctrl_##inst##_data, \ + &rzg3s_pinctrl_##inst##_cfg, PRE_KERNEL_1, \ + CONFIG_PINCTRL_RZG3S_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(RZG3S_PINCTRL_INIT); diff --git a/drivers/pwm/CMakeLists.txt b/drivers/pwm/CMakeLists.txt index 4cb108af10941e..6278ae7a5d9ee7 100644 --- a/drivers/pwm/CMakeLists.txt +++ b/drivers/pwm/CMakeLists.txt @@ -41,6 +41,8 @@ zephyr_library_sources_ifdef(CONFIG_PWM_MCUX_CTIMER pwm_mcux_ctimer.c) zephyr_library_sources_ifdef(CONFIG_PWM_NUMAKER pwm_numaker.c) zephyr_library_sources_ifdef(CONFIG_PWM_NXP_S32_EMIOS pwm_nxp_s32_emios.c) zephyr_library_sources_ifdef(CONFIG_PWM_RZA2M pwm_rza2m.c) +zephyr_library_sources_ifdef(CONFIG_POEG_RZG3S poeg_rzg3.c) + zephyr_library_sources_ifdef(CONFIG_PWM_MTU_RZA2M pwm_mtu_rza2m.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE pwm_handlers.c) diff --git a/drivers/pwm/Kconfig.rza2m b/drivers/pwm/Kconfig.rza2m index 2f300225452e5f..9ccf3de6ca6c47 100644 --- a/drivers/pwm/Kconfig.rza2m +++ b/drivers/pwm/Kconfig.rza2m @@ -6,9 +6,18 @@ config PWM_RZA2M bool "Renesas RZ/A2M General purpose PWM timer driver" default y - depends on DT_HAS_RENESAS_RZA2M_PWM_ENABLED + depends on DT_HAS_RENESAS_RZA2M_PWM_ENABLED || DT_HAS_RENESAS_RZG3S_PWM_ENABLED help - Enable General Purpose PWM timer driver. + Enable General Purpose PWM timer driver. This driver is + compatible with both RZ/A2M and RZ/G3S boards. + +config POEG_RZG3S + bool "Renesas RZ/G3S POEG driver" + default y + depends on DT_HAS_RENESAS_RZG3S_POEG_ENABLED + help + Enable POEG driver. This driver is compatible with + RZ/G3S GPT driver. config PWM_MTU_RZA2M bool "Renesas RZ/A2M multi-functional PWM timer driver" diff --git a/drivers/pwm/poeg_rzg3.c b/drivers/pwm/poeg_rzg3.c new file mode 100644 index 00000000000000..6c9a918087ef6d --- /dev/null +++ b/drivers/pwm/poeg_rzg3.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2024, EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT renesas_rzg3s_poeg + +#include +#include +#ifdef CONFIG_PINCTRL +#include +#endif +#include +#ifdef CONFIG_RESET +#include +#endif +#include +#include +#include +#include + +LOG_MODULE_REGISTER(poeg_rzg3s, CONFIG_PWM_LOG_LEVEL); + +#define LOG_DEV_ERR(dev, format, ...) LOG_ERR("%s:" #format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_WRN(dev, format, ...) LOG_WRN("%s:" #format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_INF(dev, format, ...) LOG_INF("%s:" #format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_DBG(dev, format, ...) LOG_DBG("%s:" #format, (dev)->name, ##__VA_ARGS__) + +#define PIDF BIT(0) +#define IOCF BIT(1) +#define SSF BIT(3) +#define PIDE BIT(4) +#define IOCE BIT(5) +#define ST BIT(16) +#define INV BIT(28) +#define NFEN BIT(29) +#define NFCS_MSK BIT(31) | BIT(30) +#define NFCS_OFF (30) + +#define POEG_STATUS_FLAGS (SSF | IOCF | PIDF) +#define POEG_INITIAL_CONF (NFEN | PIDE | IOCE) +struct poeg_rzg3_config { + DEVICE_MMIO_ROM; /* Must be first */ +#ifdef CONFIG_PINCTRL + const struct pinctrl_dev_config *pcfg; +#endif + const struct device *clock_dev; + struct renesas_cpg_clk mod_clk; +#ifdef CONFIG_RESET + const struct reset_dt_spec reset; +#endif + void (*cfg_irqs)(void); + int irq_line; + int invert; +}; + +struct poeg_rzg3_data { + DEVICE_MMIO_RAM; /* Must be first */ + void (*cb)(void *args); + void *args; +}; + +#define DEV_DATA(dev) ((struct poeg_rzg3_data *)((dev)->data)) +#define DEV_CFG(dev) ((struct poeg_rzg3_config *)((dev)->config)) + +static void poeg_rzg3_isr(struct device *dev) +{ + struct poeg_rzg3_data *data = DEV_DATA(dev); + + if (data->cb) { + data->cb(data->args); + } +} + +static void poeg_rzg3_set_bits(const struct device *dev, uint32_t data) +{ + uint32_t reg32 = sys_read32(DEVICE_MMIO_GET(dev)); + + sys_write32(reg32 | data, DEVICE_MMIO_GET(dev)); +} + +static void poeg_rzg3_clear_bits(const struct device *dev, uint32_t data) +{ + uint32_t reg32 = sys_read32(DEVICE_MMIO_GET(dev)); + + sys_write32(reg32 & ~(data), DEVICE_MMIO_GET(dev)); +} + +void poeg_rzg3_reset(const struct device *dev) +{ + LOG_DEV_DBG(dev, "reset POEG device"); + poeg_rzg3_clear_bits(dev, POEG_STATUS_FLAGS); +} + +uint32_t poeg_rzg3_status(const struct device *dev) +{ + return sys_read32(DEVICE_MMIO_GET(dev)) & POEG_STATUS_FLAGS; +} + +void poeg_rzg3_cb_set(const struct device *dev, void (*cb)(void *), void *args) +{ + struct poeg_rzg3_data *data = DEV_DATA(dev); + const struct poeg_rzg3_config *config = DEV_CFG(dev); + + data->cb = cb; + data->args = args; + + if (cb) { + irq_enable(config->irq_line); + } else { + irq_disable(config->irq_line); + } +} + +static int poeg_rzg3_init(const struct device *dev) +{ + int ret; + const struct poeg_rzg3_config *config = DEV_CFG(dev); + uint32_t poeg_config_reg = POEG_INITIAL_CONF; + +#ifdef CONFIG_PINCTRL + if (config->pcfg) { + /* Configure dt provided device signals when available */ + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_DEV_ERR(dev, "can't apply default pincontrol state"); + return ret; + } + } +#endif + + if (!device_is_ready(config->clock_dev)) { + LOG_DEV_ERR(dev, "cpg isn't ready"); + return -ENODEV; + } + +#ifdef CONFIG_RESET + if (device_is_ready(config->reset.dev)) { + (void)reset_line_deassert_dt(&config->reset); + } +#endif + ret = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->mod_clk); + if (ret < 0) { + LOG_DEV_ERR(dev, "can't enable module clock, ret: %d", ret); + return ret; + } + + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + + config->cfg_irqs(); + + /* POEG Initial configuration valus can be set only once after reset */ + if (config->invert) { + poeg_config_reg |= INV; + } + + poeg_rzg3_set_bits(dev, poeg_config_reg); + LOG_DEV_DBG(dev, "initialization finished"); + return 0; +} + +static const struct poeg_driver_api poeg_rzg3_driver_api = { + .reset = poeg_rzg3_reset, + .cb_set = poeg_rzg3_cb_set, + .status = poeg_rzg3_status, +}; + +#ifdef CONFIG_RESET +#define POEG_SET_RESET(n) \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(n, resets), (.reset = RESET_DT_SPEC_INST_GET(n),)) +#else +#define POEG_SET_RESET(n) +#endif + +#ifdef CONFIG_PINCTRL +#define POEG_PINCTRL_DT_INST_DEV_CONFIG_GET(n) \ + .pcfg = COND_CODE_1(DT_INST_PINCTRL_HAS_IDX(n, 0), (PINCTRL_DT_INST_DEV_CONFIG_GET(n)), \ + NULL) + +#define POEG_PINCTRL_DT_INST_DEFINE(n) \ + COND_CODE_1(DT_INST_NUM_PINCTRL_STATES(n), (PINCTRL_DT_INST_DEFINE(n);), (EMPTY)) +#else +#define POEG_PINCTRL_DT_INST_DEV_CONFIG_GET(n) +#define POEG_PINCTRL_DT_INST_DEFINE(n) +#endif + +#define POEG_DEVICE_INIT_RZG3S(n) \ + POEG_PINCTRL_DT_INST_DEFINE(n) \ + \ + static void config_isr_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), poeg_rzg3_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + } \ + \ + static const struct poeg_rzg3_config poeg_rzg3_cfg_##n = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ + POEG_PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .mod_clk.module = DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module), \ + .mod_clk.domain = DT_INST_CLOCKS_CELL_BY_IDX(n, 0, domain), \ + .cfg_irqs = config_isr_0, \ + .irq_line = DT_INST_IRQN(n), \ + .invert = DT_INST_PROP_OR(n, renesas_invert, 0), \ + POEG_SET_RESET(n)}; \ + \ + struct poeg_rzg3_data poeg_rzg3_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, &poeg_rzg3_init, NULL, &poeg_rzg3_data_##n, &poeg_rzg3_cfg_##n, \ + POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, &poeg_rzg3_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(POEG_DEVICE_INIT_RZG3S) diff --git a/drivers/pwm/pwm_rza2m.c b/drivers/pwm/pwm_rza2m.c index 957a844034d666..a1c572e59df690 100644 --- a/drivers/pwm/pwm_rza2m.c +++ b/drivers/pwm/pwm_rza2m.c @@ -4,20 +4,29 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT renesas_rza2m_pwm - #include #include #include #include #include +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) +#include +#endif #include #include #include #include - +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) +#include +#endif #include +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rza2m_pwm) +#define DT_DRV_COMPAT renesas_rza2m_pwm +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) +#define DT_DRV_COMPAT renesas_rzg3s_pwm +#endif + LOG_MODULE_REGISTER(pwm_rza2m, CONFIG_PWM_LOG_LEVEL); #define GTWP_OFFSET 0x0 /* Write-Protection Register */ @@ -131,9 +140,19 @@ LOG_MODULE_REGISTER(pwm_rza2m, CONFIG_PWM_LOG_LEVEL); #define GTIOR_OAE BIT(8) /* GTIOCA Pin Output Enable */ #define GTIOR_OBE BIT(24) /* GTIOCB Pin Output Enable */ +#define GTIOR_OADF_OFF (9) /* GTIOCA Pin Disable Value Setting */ +#define GTIOR_OADF_MASK (BIT(10) | BIT(9)) +#define GTIOR_OBDF_OFF (25) /* GTIOCB Pin Disable Value Setting */ +#define GTIOR_OBDF_MASK (BIT(26) | BIT(25)) + #define GTINTAD_OFFSET 0x38 /* Interrupt Output Setting Register */ #define GTINTAD_GTINTA BIT(0) /* GTCCRA Compare Match/InputCapture Interrupt Enable */ #define GTINTAD_GTINTB BIT(1) /* GTCCRB Compare Match/InputCapture Interrupt Enable */ +#define GTINTAD_GRPDTE BIT(28) /* Dead-Time Disable request offset */ +#define GTINTAD_GRPABH BIT(29) /* Same time output level high disable request offset */ +#define GTINTAD_GRPABL BIT(30) /* Same time output level low disable request offset */ + +#define GTINTAD_GRP_REQ_MASK (GTINTAD_GRPDTE | GTINTAD_GRPABH | GTINTAD_GRPABL) #define GTST_OFFSET 0x3C /* Status Register */ #define GTST_TCFA BIT(0) /* Input capture/compare match of GTCCRA occurred */ @@ -188,6 +207,25 @@ LOG_MODULE_REGISTER(pwm_rza2m, CONFIG_PWM_LOG_LEVEL); #define GTSOS_OFFSET 0x9C /* Output Protection Function Status Register */ #define GTSOTR_OFFSET 0xA0 /* Output Protection Function Temporary Release Register */ +#define GRP_OFF (24) /* Output disable group offset */ +#define GRPA (0 << 24) +#define GRPB (1 << 24) +#define GRPC (2 << 24) +#define GRPD (3 << 24) + +#define GTINT_PROV (1 << 6) +#define GTINTAD_GTINTPR_MASK (3 << 6) + +#define GTDTCR_OFFSET (0x88) +#define GTDVU_OFFSET (0x8c) +#define TDBUE BIT(4) +#define TDFER BIT(8) + +#define GTIOC_PIN_OUTPUT_DISABLE 0 /* Prohibit output disable */ +#define GTIOC_PIN_HIZ_DISABLE 1 /* Set GTIOC pin to Hi-Z on output disable */ +#define GTIOC_PIN_L_DISABLE 2 /* Set GTIOC pin to 0 on output disable */ +#define GTIOC_PIN_H_DISABLE 3 /* Set GTIOC pin to 1 on output disable */ + /* todo: only saw-wave mode is supported now, add other modes */ enum pwm_modes { PWM_MD_SAW_WAVE = 0, @@ -223,6 +261,45 @@ enum isr_idx { ISR_MAX, }; +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) +struct poeg_reg_params { + uint32_t value; + uint32_t reg_off; +}; + +struct poeg_params { + uint32_t poeg; + struct poeg_reg_params regs[3]; +}; + +enum poeg_channels { + POEG_A = 0, + POEG_B, + POEG_C, + POEG_D, + POEG_NOT_USED, +}; + +static const struct poeg_params poeg_channels[] = { + [POEG_A] = { + GRPA, + {{0x2, GTSSR_OFFSET}, {0x1, GTPSR_OFFSET}, {0x1, GTCSR_OFFSET}}, + }, + [POEG_B] = { + GRPB, + {{0x8, GTSSR_OFFSET}, {0x4, GTPSR_OFFSET}, {0x4, GTCSR_OFFSET}}, + }, + [POEG_C] = { + GRPC, + {{0x20, GTSSR_OFFSET}, {0x10, GTPSR_OFFSET}, {0x10, GTCSR_OFFSET}}, + }, + [POEG_D] = { + GRPD, + {{0x80, GTSSR_OFFSET}, {0x40, GTPSR_OFFSET}, {0x40, GTCSR_OFFSET}}, + }, +}; +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) */ + struct pwm_rza2m_config { DEVICE_MMIO_ROM; /* Must be first */ uint32_t channel_id; @@ -231,9 +308,16 @@ struct pwm_rza2m_config { const struct device *clock_dev; struct renesas_cpg_clk mod_clk; struct renesas_cpg_clk bus_clk; - +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) + const struct reset_dt_spec reset; +#endif uint32_t irq_lines[ISR_MAX]; void (*cfg_irqs)(const struct device *dev); +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) + int poeg_idx; + int disable_mask; + const struct device *poeg_dev; +#endif }; struct pwm_channel_pin { @@ -282,6 +366,7 @@ static inline void rza2m_pwm_set_duty_setting(mm_reg_t base, uint32_t period_cyc reg = sys_read32(base + GTUDDTYC_OFFSET); new_reg = reg & ~duty_cyc_masks[is_channel_b]; + if (period_cycles == pulse_cycles) { new_reg |= duty_cyc_cfgs[is_channel_b][DUTY_100][is_inverted]; } else if (pulse_cycles == 0) { @@ -304,11 +389,35 @@ static void rza2m_pwm_cfg_io(mm_reg_t base, bool is_channel_b, bool is_inv) {CH_A_IO_FLAGS_NORMAL, CH_A_IO_FLAGS_INV}, {CH_B_IO_FLAGS_NORMAL, CH_B_IO_FLAGS_INV}, }; + mm_reg_t reg = sys_read32(base + GTIOR_OFFSET); - sys_write32(ctior_states[is_channel_b][is_inv], base + GTIOR_OFFSET); + reg &= ~(ctior_states[is_channel_b][is_inv] | ctior_states[is_channel_b][!is_inv]); + sys_write32(reg | (ctior_states[is_channel_b][is_inv]), base + GTIOR_OFFSET); } -/* todo: add support of two in/out pins on the same channel */ +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) +static void set_channel_protection(const struct device *dev, uint32_t channel, bool is_channel_b) +{ + const struct pwm_rza2m_config *config = dev->config; + mm_reg_t base = DEVICE_MMIO_GET(dev); + mm_reg_t gtior; + + if (config->poeg_idx == POEG_NOT_USED) { + return; + } + + gtior = sys_read32(base + GTIOR_OFFSET); + gtior &= (is_channel_b) ? ~(GTIOR_OBDF_MASK) : ~(GTIOR_OADF_MASK); + if (channel & PWM_CHANNEL_PROTECTED) { + /* TODO: support PIN_L_DISABLE and PIN_H_DISABLE state */ + gtior |= (is_channel_b) ? (GTIOC_PIN_HIZ_DISABLE << GTIOR_OBDF_OFF) + : (GTIOC_PIN_HIZ_DISABLE << GTIOR_OADF_OFF); + } + + sys_write32(gtior, base + GTIOR_OFFSET); +} +#endif + static int rza2m_pwm_set_cycles(const struct device *dev, uint32_t channel, uint32_t period_cyc, uint32_t pulse_cyc, pwm_flags_t flags) { @@ -321,7 +430,7 @@ static int rza2m_pwm_set_cycles(const struct device *dev, uint32_t channel, uint bool is_channel_b = ((channel & PWM_CHANNEL_INPUT_B) == PWM_CHANNEL_INPUT_B); bool is_inv = ((flags & PWM_POLARITY_INVERTED) == PWM_POLARITY_INVERTED); - if (config->channel_id != (channel & ~PWM_CHANNEL_INPUT_B)) { + if (config->channel_id != (channel & ~(PWM_CHANNEL_INPUT_B | PWM_CHANNEL_PROTECTED))) { LOG_ERR("%s:%s: request channel (%u) from another pwm device", __func__, dev->name, channel); return -EINVAL; @@ -341,13 +450,12 @@ static int rza2m_pwm_set_cycles(const struct device *dev, uint32_t channel, uint pin_cfg = &data->pins[is_channel_b]; key = k_spin_lock(&data->lock); - if (data->pins[!is_channel_b].initialized) { - LOG_ERR("%s: currently it is possible to use only one IO pin per channel", - dev->name); - ret = -ENOTSUP; - goto exit; +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) + /* poeg_ids will always be set in pair with poeg_dev */ + if (config->poeg_idx != POEG_NOT_USED) { + poeg_reset(config->poeg_dev); } - +#endif if (pin_cfg->initialized) { if (pin_cfg->is_input) { LOG_ERR("%s: channel has been configured as input", dev->name); @@ -368,6 +476,9 @@ static int rza2m_pwm_set_cycles(const struct device *dev, uint32_t channel, uint rza2m_pwm_cfg_io(base, is_channel_b, is_inv); pin_cfg->is_inverted = is_inv; } +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) + set_channel_protection(dev, channel, is_channel_b); +#endif pin_cfg->flags = flags; goto exit; } @@ -386,26 +497,28 @@ static int rza2m_pwm_set_cycles(const struct device *dev, uint32_t channel, uint sys_write32(0, base + GTCNT_OFFSET); if (is_channel_b) { - sys_write32(pulse_cyc, base + GTCCRD_OFFSET); sys_write32(pulse_cyc, base + GTCCRB_OFFSET); + sys_write32(pulse_cyc, base + GTCCRD_OFFSET); } else { - sys_write32(pulse_cyc, base + GTCCRC_OFFSET); sys_write32(pulse_cyc, base + GTCCRA_OFFSET); + sys_write32(pulse_cyc, base + GTCCRC_OFFSET); } - /* todo: add possibility to use A and B at the same time at the same PWM channel */ sys_write32(period_cyc - 1, base + GTPR_OFFSET); sys_write32(period_cyc - 1, base + GTPBR_OFFSET); + reg = sys_read32(base + GTBER_OFFSET); /* enable bufferization for registers GTCCRA, GTCCRB and GTPR */ if (is_channel_b) { - sys_write32(GTBER_CCRB_1_BUF_EN | GTBER_PR_1_BUF, base + GTBER_OFFSET); + sys_write32(reg | GTBER_CCRB_1_BUF_EN | GTBER_PR_1_BUF, base + GTBER_OFFSET); } else { - sys_write32(GTBER_CCRA_1_BUF_EN | GTBER_PR_1_BUF, base + GTBER_OFFSET); + sys_write32(reg | GTBER_CCRA_1_BUF_EN | GTBER_PR_1_BUF, base + GTBER_OFFSET); } rza2m_pwm_cfg_io(base, is_channel_b, is_inv); - +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) + set_channel_protection(dev, channel, is_channel_b); +#endif /* start counter operation */ reg = sys_read32(base + GTCR_OFFSET); sys_write32(reg | GTCR_START_CNT, base + GTCR_OFFSET); @@ -792,6 +905,51 @@ static const struct pwm_driver_api pwm_rza2m_driver_api = { #endif /* CONFIG_PWM_CAPTURE */ }; +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) +static void pwm_set_poeg(const struct device *dev, const struct poeg_params *params) +{ + mm_reg_t base, reg; + int i; + + base = DEVICE_MMIO_GET(dev); + + reg = sys_read32(base + GTINTAD_OFFSET); + sys_write32(reg | params->poeg, base + GTINTAD_OFFSET); + + for (i = 0; i < ARRAY_SIZE(params->regs); i++) { + sys_write32(params->regs[i].value, base + params->regs[i].reg_off); + } +} + +static void pwm_set_int_cfg(const struct device *dev) +{ + mm_reg_t base, reg; + const struct pwm_rza2m_config *config = dev->config; + + base = DEVICE_MMIO_GET(dev); + + if (!config->disable_mask) { + return; + } + + reg = sys_read32(base + GTINTAD_OFFSET); + + if ((config->disable_mask & PWM_HIGH) == PWM_HIGH) { + reg |= GTINTAD_GRPABH; + } + + if ((config->disable_mask & PWM_LOW) == PWM_LOW) { + reg |= GTINTAD_GRPABL; + } + + if ((config->disable_mask & PWM_DT) == PWM_DT) { + reg |= GTINTAD_GRPDTE; + } + + sys_write32(reg, base + GTINTAD_OFFSET); +} +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) */ + static int pwm_rza2m_init(const struct device *dev) { int ret; @@ -811,6 +969,23 @@ static int pwm_rza2m_init(const struct device *dev) return -ENODEV; } +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) + if (!device_is_ready(config->reset.dev)) { + LOG_ERR("%s: resets isn't ready", dev->name); + return -ENODEV; + } + + (void)reset_line_deassert_dt(&config->reset); +#endif + +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) + if (((config->poeg_idx != POEG_NOT_USED) && (!config->poeg_dev)) || + ((config->poeg_idx == POEG_NOT_USED) && (config->poeg_dev))) { + LOG_ERR("%s: poeg settings are incorrect", dev->name); + return -ENODEV; + } +#endif + ret = clock_control_on(config->clock_dev, (clock_control_subsys_t)&config->mod_clk); if (ret < 0) { LOG_ERR("%s: can't enable module clock", dev->name); @@ -837,6 +1012,14 @@ static int pwm_rza2m_init(const struct device *dev) config->cfg_irqs(dev); } +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) + if (config->poeg_idx != POEG_NOT_USED) { + pwm_set_poeg(dev, &poeg_channels[config->poeg_idx]); + + pwm_set_int_cfg(dev); + } +#endif + return 0; } @@ -857,6 +1040,40 @@ static void pwm_rza2m_ccmpb_isr(struct device *dev) pwm_rza2m_ccmp_isr_cmn(dev, &data->pins[PIN_B], true); #endif /* CONFIG_PWM_CAPTURE */ } +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) + +#define PWM_POEG_NAME(n) \ + .poeg_idx = COND_CODE_1(DT_INST_NODE_HAS_PROP(n, renesas_poeg), \ + (DT_INST_ENUM_IDX(n, renesas_poeg)), (POEG_NOT_USED)), +#else +#define PWM_POEG_NAME(n) +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) */ + +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) +#define PWM_POEG_DEV(n) .poeg_dev = DEVICE_DT_GET_OR_NULL(DT_INST_PHANDLE(n, renesas_poeg_device)), +#else +#define PWM_POEG_DEV(n) +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) */ + +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) +#define PWM_SET_DISABLE(n) .disable_mask = DT_INST_PROP_OR(n, renesas_disable_requests, 0), +#else +#define PWM_SET_DISABLE(n) +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) */ + +#define DT_IRQ_HAS_CELL_AT_NAME(node_id, name, cell) \ + IS_ENABLED(DT_CAT6(node_id, _IRQ_NAME_, name, _VAL_, cell, _EXISTS)) + +#define DT_IRQ_FLAGS_OR_ZERO(inst, name) \ + COND_CODE_1(DT_IRQ_HAS_CELL_AT_NAME(DT_DRV_INST(inst), name, flags), \ + (DT_INST_IRQ_BY_NAME(inst, name, flags)), (0)) + +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) +#define PWM_SET_RESET(n) \ + .reset = RESET_DT_SPEC_INST_GET(n), +#else +#define PWM_SET_RESET(n) +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg3s_pwm) */ #define IRQ_GET_LINE(n, inst) DT_INST_IRQ_BY_IDX(inst, n, irq) #define GET_IRQ_LINES_ARRAY(inst) \ @@ -873,10 +1090,10 @@ static void pwm_rza2m_ccmpb_isr(struct device *dev) /* todo: add other IRQs when additional PWM modes are introduced */ \ IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, ccmpa, irq), \ DT_INST_IRQ_BY_NAME(n, ccmpa, priority), pwm_rza2m_ccmpa_isr, \ - DEVICE_DT_INST_GET(n), DT_INST_IRQ_BY_NAME(n, ccmpa, flags)); \ + DEVICE_DT_INST_GET(n), DT_IRQ_FLAGS_OR_ZERO(n, ccmpa)); \ IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, ccmpb, irq), \ DT_INST_IRQ_BY_NAME(n, ccmpb, priority), pwm_rza2m_ccmpb_isr, \ - DEVICE_DT_INST_GET(n), DT_INST_IRQ_BY_NAME(n, ccmpb, flags)); \ + DEVICE_DT_INST_GET(n), DT_IRQ_FLAGS_OR_ZERO(n, ccmpb)); \ } \ \ static const struct pwm_rza2m_config pwm_rza2m_config_##n = { \ @@ -891,7 +1108,7 @@ static void pwm_rza2m_ccmpb_isr(struct device *dev) .irq_lines = GET_IRQ_LINES_ARRAY(n), \ .cfg_irqs = config_isr_##n, \ .divider = DT_INST_PROP_OR(n, divider, 1), \ - }; \ + PWM_POEG_NAME(n) PWM_SET_RESET(n) PWM_SET_DISABLE(n) PWM_POEG_DEV(n)}; \ \ BUILD_ASSERT(DT_NUM_IRQS(DT_DRV_INST(n)) == ISR_MAX, \ "Different interrupt number in dts and driver"); \ diff --git a/drivers/reset/CMakeLists.txt b/drivers/reset/CMakeLists.txt index 36c68367d39c80..563187907aa464 100644 --- a/drivers/reset/CMakeLists.txt +++ b/drivers/reset/CMakeLists.txt @@ -9,3 +9,4 @@ zephyr_library_sources_ifdef(CONFIG_RESET_AST10X0 reset_ast10x0.c) zephyr_library_sources_ifdef(CONFIG_RESET_STM32 reset_stm32.c) zephyr_library_sources_ifdef(CONFIG_RESET_NUMAKER reset_numaker.c) zephyr_library_sources_ifdef(CONFIG_RESET_INTEL_SOCFPGA reset_intel_socfpga.c) +zephyr_library_sources_ifdef(CONFIG_RESET_RENESAS_RZG3S_CPG reset_r9a08g045_cpg.c) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index f940583c974932..0251545a4be83c 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -33,5 +33,6 @@ rsource "Kconfig.aspeed" rsource "Kconfig.stm32" rsource "Kconfig.numaker" rsource "Kconfig.intel_socfpga" +rsource "Kconfig.renesas" endif # RESET diff --git a/drivers/reset/Kconfig.renesas b/drivers/reset/Kconfig.renesas new file mode 100644 index 00000000000000..e87a08e669843b --- /dev/null +++ b/drivers/reset/Kconfig.renesas @@ -0,0 +1,9 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +config RESET_RENESAS_RZG3S_CPG + bool "Renesas RZ/G3S family clock support" + default y + depends on DT_HAS_RENESAS_R9A08G045_CPG_RESET_ENABLED + help + Enable support for Renesas CPG MSSR Reset controller driver. diff --git a/drivers/reset/reset_r9a08g045_cpg.c b/drivers/reset/reset_r9a08g045_cpg.c new file mode 100644 index 00000000000000..cfa410e8e536ea --- /dev/null +++ b/drivers/reset/reset_r9a08g045_cpg.c @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * Renesas RZ/G3S r9a08g045 CPG Reset controller + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_r9a08g045_cpg_reset + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(reset_rzg3s, CONFIG_CLOCK_CONTROL_LOG_LEVEL); + +#define LOG_DEV_ERR(dev, format, ...) LOG_ERR("%s:"#format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_WRN(dev, format, ...) LOG_WRN("%s:"#format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_INF(dev, format, ...) LOG_INF("%s:"#format, (dev)->name, ##__VA_ARGS__) +#define LOG_DEV_DBG(dev, format, ...) LOG_DBG("%s:"#format, (dev)->name, ##__VA_ARGS__) + +#define MON_REG_WAIT_US 50 + +#define RST_MON_R(reg) (0x180 + (reg)) + +struct rzg3s_cpg_reset { + uint16_t off; + uint16_t bit; +}; + +#define DEF_RST(_id, _off, _bit) \ + [_id] = { \ + .off = (_off), \ + .bit = (_bit) \ + } + +static const struct rzg3s_cpg_reset rzg3s_cpg_resets[R9A08G045_LST_RESETN] = { + DEF_RST(R9A08G045_GIC600_GICRESET_N, 0x814, 0), + DEF_RST(R9A08G045_GIC600_DBG_GICRESET_N, 0x814, 1), + DEF_RST(R9A08G045_IA55_RESETN, 0x818, 0), + DEF_RST(R9A08G045_DMAC_ARESETN, 0x82c, 0), + DEF_RST(R9A08G045_DMAC_RST_ASYNC, 0x82c, 1), + DEF_RST(R9A08G045_OSTM0_PRESETZ, 0x834, 0), + DEF_RST(R9A08G045_OSTM1_PRESETZ, 0x834, 1), + DEF_RST(R9A08G045_OSTM2_PRESETZ, 0x834, 2), + DEF_RST(R9A08G045_OSTM3_PRESETZ, 0x834, 3), + DEF_RST(R9A08G045_OSTM4_PRESETZ, 0x834, 4), + DEF_RST(R9A08G045_OSTM5_PRESETZ, 0x834, 5), + DEF_RST(R9A08G045_OSTM6_PRESETZ, 0x834, 6), + DEF_RST(R9A08G045_OSTM7_PRESETZ, 0x834, 7), + DEF_RST(R9A08G045_MTU_X_PRESET_MTU3, 0x838, 0), + DEF_RST(R9A08G045_POE3_RST_M_REG, 0x83c, 0), + DEF_RST(R9A08G045_GPT_RST_C, 0x840, 0), + DEF_RST(R9A08G045_POEG_A_RST, 0x844, 0), + DEF_RST(R9A08G045_POEG_B_RST, 0x844, 1), + DEF_RST(R9A08G045_POEG_C_RST, 0x844, 2), + DEF_RST(R9A08G045_POEG_D_RST, 0x844, 3), + DEF_RST(R9A08G045_WDT0_PRESETN, 0x848, 0), + DEF_RST(R9A08G045_WDT1_PRESETN, 0x848, 1), + DEF_RST(R9A08G045_WDT2_PRESETN, 0x848, 2), + DEF_RST(R9A08G045_SPI_HRESETN, 0x850, 0), + DEF_RST(R9A08G045_SPI_ARESETN, 0x850, 1), + DEF_RST(R9A08G045_SDHI0_IXRST, 0x854, 0), + DEF_RST(R9A08G045_SDHI1_IXRST, 0x854, 1), + DEF_RST(R9A08G045_SDHI2_IXRST, 0x854, 2), + DEF_RST(R9A08G045_SSI0_RST_M2_REG, 0x870, 0), + DEF_RST(R9A08G045_SSI1_RST_M2_REG, 0x870, 1), + DEF_RST(R9A08G045_SSI2_RST_M2_REG, 0x870, 2), + DEF_RST(R9A08G045_SSI3_RST_M2_REG, 0x870, 3), + DEF_RST(R9A08G045_SRC_RST, 0x874, 0), + DEF_RST(R9A08G045_USB_U2H0_HRESETN, 0x878, 0), + DEF_RST(R9A08G045_USB_U2H1_HRESETN, 0x878, 1), + DEF_RST(R9A08G045_USB_U2P_EXL_SYSRST, 0x878, 2), + DEF_RST(R9A08G045_USB_PRESETN, 0x878, 3), + DEF_RST(R9A08G045_ETH0_RST_HW_N, 0x87c, 0), + DEF_RST(R9A08G045_ETH1_RST_HW_N, 0x87c, 1), + DEF_RST(R9A08G045_I2C0_MRST, 0x880, 0), + DEF_RST(R9A08G045_I2C1_MRST, 0x880, 1), + DEF_RST(R9A08G045_I2C2_MRST, 0x880, 2), + DEF_RST(R9A08G045_I2C3_MRST, 0x880, 3), + DEF_RST(R9A08G045_SCIF0_RST_SYSTEM_N, 0x884, 0), + DEF_RST(R9A08G045_SCIF1_RST_SYSTEM_N, 0x884, 1), + DEF_RST(R9A08G045_SCIF2_RST_SYSTEM_N, 0x884, 2), + DEF_RST(R9A08G045_SCIF3_RST_SYSTEM_N, 0x884, 3), + DEF_RST(R9A08G045_SCIF4_RST_SYSTEM_N, 0x884, 4), + DEF_RST(R9A08G045_SCIF5_RST_SYSTEM_N, 0x884, 5), + DEF_RST(R9A08G045_SCI0_RST, 0x888, 0), + DEF_RST(R9A08G045_SCI1_RST, 0x888, 1), + DEF_RST(R9A08G045_RSPI0_RST, 0x890, 0), + DEF_RST(R9A08G045_RSPI1_RST, 0x890, 1), + DEF_RST(R9A08G045_RSPI2_RST, 0x890, 2), + DEF_RST(R9A08G045_RSPI3_RST, 0x890, 3), + DEF_RST(R9A08G045_RSPI4_RST, 0x890, 4), + DEF_RST(R9A08G045_CANFD_RSTP_N, 0x894, 0), + DEF_RST(R9A08G045_CANFD_RSTC_N, 0x894, 1), + DEF_RST(R9A08G045_GPIO_RSTN, 0x898, 0), + DEF_RST(R9A08G045_GPIO_PORT_RESETN, 0x898, 1), + DEF_RST(R9A08G045_GPIO_SPARE_RESETN, 0x898, 2), + DEF_RST(R9A08G045_ADC_PRESETN, 0x8a8, 0), + DEF_RST(R9A08G045_ADC_ADRST_N, 0x8a8, 1), + DEF_RST(R9A08G045_TSU_PRESETN, 0x8ac, 0), + DEF_RST(R9A08G045_OCTA_ARESETN, 0x8f4, 0), + DEF_RST(R9A08G045_PDM0_PRESETNT, 0x904, 0), + DEF_RST(R9A08G045_PCI_ARESETN, 0x908, 0), + DEF_RST(R9A08G045_PCI_RST_B, 0x908, 1), + DEF_RST(R9A08G045_PCI_RST_GP_B, 0x908, 2), + DEF_RST(R9A08G045_PCI_RST_PS_B, 0x908, 3), + DEF_RST(R9A08G045_PCI_RST_RSM_B, 0x908, 4), + DEF_RST(R9A08G045_PCI_RST_CFG_B, 0x908, 5), + DEF_RST(R9A08G045_PCI_RST_LOAD_B, 0x908, 6), + DEF_RST(R9A08G045_SPDIF_RST, 0x90c, 0), + DEF_RST(R9A08G045_I3C_TRESETN, 0x910, 0), + DEF_RST(R9A08G045_I3C_PRESETN, 0x910, 1), + DEF_RST(R9A08G045_VBAT_BRESETN, 0x914, 0), + DEF_RST(R9A08G045_MHU_RESETN, 0x820, 0), + +}; + +struct rzg3s_reset_cpg_config { + const struct rzg3s_cpg_reset *mod_rsts; + const struct device *cpg_dev; +}; + +struct rzg3s_reset_cpg_data { + mm_reg_t base_addr; + + struct k_spinlock lock; +}; + +static void rzg3s_cpg_change_reg_bits(mm_reg_t reg, uint32_t bitmask, bool set) +{ + uint32_t reg_val = (bitmask << 16); + + if (set) { + reg_val |= bitmask; + } + + sys_write32(reg_val, reg); +} + +static int rzg3s_cpg_wait_bit_val(mm_reg_t reg_addr, uint32_t mask, uint32_t val, + int32_t us_wait) +{ + uint32_t reg_val; + int32_t wait_cnt = (us_wait / 5); + + do { + reg_val = sys_read32(reg_addr) & mask; + + if (reg_val == val) { + break; + } + + if (wait_cnt > 0) { + int loops = 500; + + while (loops-- > 0) { + arch_nop(); + } + } + } while (wait_cnt-- > 0); + + return wait_cnt; +} + +static int rzg3s_reset_cpg_init(const struct device *dev) +{ + const struct rzg3s_reset_cpg_config *cfg = dev->config; + struct rzg3s_reset_cpg_data *data = dev->data; + + /* Get IO addr from parent */ + data->base_addr = DEVICE_MMIO_GET(cfg->cpg_dev); + + return 0; +} + +static int rzg3s_reset_cpg_checkpar(const struct device *dev, uint32_t id) +{ + if (!dev) { + return -EINVAL; + } + + if (id >= R9A08G045_LST_RESETN) { + LOG_DEV_ERR(dev, "wrong module reset id %u", id); + return -EINVAL; + } + + return 0; +} + +static int rzg3s_reset_cpg_doreset(const struct device *dev, uint32_t id) +{ + const struct rzg3s_reset_cpg_config *cfg = dev->config; + struct rzg3s_reset_cpg_data *data = dev->data; + const struct rzg3s_cpg_reset *mod_rst; + k_spinlock_key_t key; + mm_reg_t reg_addr; + uint32_t val; + int ret; + + ret = rzg3s_reset_cpg_checkpar(dev, id); + if (ret) { + return ret; + } + + mod_rst = &cfg->mod_rsts[id]; + + key = k_spin_lock(&data->lock); + /* reset assert */ + reg_addr = data->base_addr + cfg->mod_rsts[id].off; + val = BIT(cfg->mod_rsts[id].bit); + rzg3s_cpg_change_reg_bits(reg_addr, val, false); + + /* monitor mod reset */ + reg_addr = data->base_addr + RST_MON_R(cfg->mod_rsts[id].off); + ret = rzg3s_cpg_wait_bit_val(reg_addr, val, val, MON_REG_WAIT_US); + if (!ret) { + LOG_DEV_DBG(dev, "module id %u resetA tmo", id); + } + + /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */ + k_busy_wait(35); + + /* reset de-assert */ + reg_addr = data->base_addr + cfg->mod_rsts[id].off; + val = BIT(cfg->mod_rsts[id].bit); + rzg3s_cpg_change_reg_bits(reg_addr, val, true); + + /* monitor mod reset */ + reg_addr = data->base_addr + RST_MON_R(cfg->mod_rsts[id].off); + ret = rzg3s_cpg_wait_bit_val(reg_addr, val, 0, MON_REG_WAIT_US); + if (!ret) { + LOG_DEV_DBG(dev, "module id %u resetD tmo", id); + } + k_spin_unlock(&data->lock, key); + + return 0; +} + +static int rzg3s_reset_cpg_assert(const struct device *dev, uint32_t id) +{ + const struct rzg3s_reset_cpg_config *cfg = dev->config; + struct rzg3s_reset_cpg_data *data = dev->data; + const struct rzg3s_cpg_reset *mod_rst; + k_spinlock_key_t key; + mm_reg_t reg_addr; + uint32_t val; + int ret; + + ret = rzg3s_reset_cpg_checkpar(dev, id); + if (ret) { + return ret; + } + + mod_rst = &cfg->mod_rsts[id]; + + key = k_spin_lock(&data->lock); + /* reset assert */ + reg_addr = data->base_addr + mod_rst->off; + val = BIT(mod_rst->bit); + rzg3s_cpg_change_reg_bits(reg_addr, val, false); + + /* monitor mod reset */ + reg_addr = data->base_addr + RST_MON_R(mod_rst->off); + ret = rzg3s_cpg_wait_bit_val(reg_addr, val, val, MON_REG_WAIT_US); + if (!ret) { + LOG_DEV_DBG(dev, "module id %u resetA tmo", id); + ret = -EIO; + } + k_spin_unlock(&data->lock, key); + + return 0; +} + +static int rzg3s_reset_cpg_deassert(const struct device *dev, uint32_t id) +{ + const struct rzg3s_reset_cpg_config *cfg = dev->config; + struct rzg3s_reset_cpg_data *data = dev->data; + const struct rzg3s_cpg_reset *mod_rst; + k_spinlock_key_t key; + mm_reg_t reg_addr; + uint32_t val; + int ret; + + ret = rzg3s_reset_cpg_checkpar(dev, id); + if (ret) { + return ret; + } + + mod_rst = &cfg->mod_rsts[id]; + + key = k_spin_lock(&data->lock); + /* reset de-assert */ + reg_addr = data->base_addr + mod_rst->off; + val = BIT(mod_rst->bit); + rzg3s_cpg_change_reg_bits(reg_addr, val, true); + + /* monitor mod reset */ + reg_addr = data->base_addr + RST_MON_R(mod_rst->off); + ret = rzg3s_cpg_wait_bit_val(reg_addr, val, 0, MON_REG_WAIT_US); + if (!ret) { + LOG_DEV_DBG(dev, "module id %u resetD tmo", id); + ret = -EIO; + } + k_spin_unlock(&data->lock, key); + + return 0; +} + +static int rzg3s_reset_cpg_status(const struct device *dev, uint32_t id, uint8_t *status) +{ + const struct rzg3s_reset_cpg_config *cfg = dev->config; + struct rzg3s_reset_cpg_data *data = dev->data; + const struct rzg3s_cpg_reset *mod_rst; + mm_reg_t reg_addr; + int ret; + + ret = rzg3s_reset_cpg_checkpar(dev, id); + if (ret) { + return ret; + } + + mod_rst = &cfg->mod_rsts[id]; + + /* monitor mod reset */ + reg_addr = data->base_addr + RST_MON_R(mod_rst->off); + *status = !!(sys_read32(reg_addr) & BIT(mod_rst->bit)); + + return 0; +} + +static const struct reset_driver_api rzg3s_cpg_reset_driver_api = { + .status = rzg3s_reset_cpg_status, + .line_assert = rzg3s_reset_cpg_assert, + .line_deassert = rzg3s_reset_cpg_deassert, + .line_toggle = rzg3s_reset_cpg_doreset, +}; + +#define RZG3S_RESET_CPG_INIT(inst) \ + static const struct rzg3s_reset_cpg_config rzg3s_reset_cpg_##inst##_cfg = { \ + .mod_rsts = rzg3s_cpg_resets, \ + .cpg_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + }; \ + \ + static struct rzg3s_reset_cpg_data rzg3s_reset_cpg_##inst##_data = {}; \ + \ + DEVICE_DT_INST_DEFINE(inst, rzg3s_reset_cpg_init, NULL, &rzg3s_reset_cpg_##inst##_data, \ + &rzg3s_reset_cpg_##inst##_cfg, PRE_KERNEL_1, \ + CONFIG_RESET_INIT_PRIORITY, &rzg3s_cpg_reset_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(RZG3S_RESET_CPG_INIT) diff --git a/drivers/serial/Kconfig.renesas b/drivers/serial/Kconfig.renesas index a543c9ad4def38..19295a6cf91ade 100644 --- a/drivers/serial/Kconfig.renesas +++ b/drivers/serial/Kconfig.renesas @@ -7,10 +7,11 @@ config UART_SCIF bool "Renesas SCIF UART Driver" default y - depends on DT_HAS_RENESAS_RCAR_SCIF_ENABLED || DT_HAS_RENESAS_RZA2M_SCIF_ENABLED + depends on DT_HAS_RENESAS_RCAR_SCIF_ENABLED || DT_HAS_RENESAS_RZA2M_SCIF_ENABLED || DT_HAS_RENESAS_RZG3S_SCIF_ENABLED select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT - select SERIAL_SUPPORT_ASYNC if DT_HAS_RENESAS_RZA2_DMA_ENABLED + select SERIAL_SUPPORT_ASYNC if DT_HAS_RENESAS_RZA2_DMA_ENABLED || DT_HAS_RENESAS_RZG3_DMA_ENABLED + select DMA if UART_ASYNC_API help Enable Renesas SCIF UART Driver. diff --git a/drivers/serial/uart_scif.c b/drivers/serial/uart_scif.c index 1e18865f4ec907..0a8eb2c5edc3e1 100644 --- a/drivers/serial/uart_scif.c +++ b/drivers/serial/uart_scif.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -77,10 +78,12 @@ struct uart_scif_cfg { struct renesas_cpg_clk mod_clk; struct renesas_cpg_clk bus_clk; const struct pinctrl_dev_config *pcfg; + const struct reset_dt_spec reset; const struct scif_params *params; uint32_t type; - bool usart_mode; - bool external_clock; + bool usart_mode: 1; + bool external_clock: 1; + bool loopback_en: 1; #ifdef CONFIG_UART_INTERRUPT_DRIVEN void (*irq_config_func)(const struct device *dev); #endif @@ -457,6 +460,9 @@ static int uart_scif_configure(const struct device *dev, const struct uart_confi reg_val = uart_scif_read_16(dev, SCFCR); reg_val &= ~(SCFCR_RTRG1 | SCFCR_RTRG0 | SCFCR_TTRG1 | SCFCR_TTRG0 | SCFCR_MCE | SCFCR_TFRST | SCFCR_RFRST); + if (config->loopback_en) { + reg_val |= SCFCR_LOOP; + } uart_scif_write_16(dev, SCFCR, reg_val); /* Enable Transmit & Receive + disable Interrupts */ @@ -549,8 +555,7 @@ static void uart_scif_async_init(const struct device *dev) /* Configure dma rx config */ offset = config->params->regs[SCFRDR].offset; memset(&data->dma_rx.blk_cfg, 0, sizeof(data->dma_rx.blk_cfg)); - data->dma_rx.blk_cfg.source_address = - (uint32_t)DEVICE_MMIO_ROM_PTR(dev)->phys_addr + offset; + data->dma_rx.blk_cfg.source_address = *(mm_reg_t *)DEVICE_MMIO_ROM_PTR(dev) + offset; data->dma_rx.blk_cfg.dest_address = 0; /* dest not ready */ if (data->dma_rx.src_addr_increment) { @@ -580,7 +585,7 @@ static void uart_scif_async_init(const struct device *dev) offset = config->params->regs[SCFTDR].offset; memset(&data->dma_tx.blk_cfg, 0, sizeof(data->dma_tx.blk_cfg)); - data->dma_tx.blk_cfg.dest_address = (uint32_t)DEVICE_MMIO_ROM_PTR(dev)->phys_addr + offset; + data->dma_tx.blk_cfg.dest_address = *(mm_reg_t *)DEVICE_MMIO_ROM_PTR(dev) + offset; data->dma_tx.blk_cfg.source_address = 0; /* not ready */ @@ -634,6 +639,10 @@ static int uart_scif_init(const struct device *dev) return ret; } + if (config->reset.dev) { + (void)reset_line_deassert_dt(&config->reset); + } + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); ret = uart_scif_configure(dev, &data->current_config); @@ -1011,6 +1020,8 @@ static void uart_scif_dma_replace_buffer(const struct device *dev) return; } + uart_scif_write_16(dev, SCSCR, uart_scif_read_16(dev, SCSCR) | SCSCR_RE | SCSCR_RIE); + /* Request next buffer */ scif_async_evt_rx_buf_request(data); } @@ -1126,7 +1137,11 @@ static int uart_scif_async_tx_abort(const struct device *dev) { struct uart_scif_data *data = dev->data; + /* Turn off TX Interrupts to prevent hung in ISR */ + uart_scif_write_16(dev, SCSCR, uart_scif_read_16(dev, SCSCR) & ~(SCSCR_TIE)); (void)k_work_cancel_delayable(&data->dma_tx.timeout_work); + /* Turn off TX Interrupts to prevent hung in ISR */ + uart_scif_write_16(dev, SCSCR, uart_scif_read_16(dev, SCSCR) & ~(SCSCR_TIE)); return 0; } @@ -1228,6 +1243,8 @@ static void dma_tx_callback(const struct device *dev, void *user_data, if (!dma_get_status(data->dma_tx.dma_dev, data->dma_tx.dma_channel, &stat)) { data->dma_tx.counter = data->dma_tx.buffer_length - stat.pending_length; } + /* Turn off TX Interrupts to prevent hung in ISR */ + uart_scif_write_16(uart_dev, SCSCR, uart_scif_read_16(uart_dev, SCSCR) & ~(SCSCR_TIE)); scif_async_evt_tx_done(data); K_SPINLOCK(&data->dma_tx.lock) { data->dma_tx.buffer_length = 0; @@ -1240,6 +1257,9 @@ static void dma_rx_callback(const struct device *dev, void *user_data, const struct device *uart_dev = user_data; struct uart_scif_data *data = uart_dev->data; + /* Turn off RX Interrupts to prevent hung in ISR */ + uart_scif_write_16(uart_dev, SCSCR, uart_scif_read_16(uart_dev, SCSCR) & ~(SCSCR_RIE)); + (void)k_work_cancel_delayable(&data->dma_rx.timeout_work); if (status < 0) { scif_async_evt_rx_err(data, status); @@ -1305,19 +1325,17 @@ static const struct uart_driver_api uart_scif_driver_api = { static const struct uart_scif_cfg uart_scif_cfg_##n = { \ DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ - .mod_clk.module = \ - DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module), \ - .mod_clk.domain = \ - DT_INST_CLOCKS_CELL_BY_IDX(n, 0, domain), \ - .bus_clk.module = \ - DT_INST_CLOCKS_CELL_BY_IDX(n, 1, module), \ - .bus_clk.domain = \ - DT_INST_CLOCKS_CELL_BY_IDX(n, 1, domain), \ + .mod_clk.module = DT_INST_CLOCKS_CELL_BY_NAME(n, fck, module), \ + .mod_clk.domain = DT_INST_CLOCKS_CELL_BY_NAME(n, fck, domain), \ + .bus_clk.module = DT_INST_CLOCKS_CELL_BY_NAME(n, bus, module), \ + .bus_clk.domain = DT_INST_CLOCKS_CELL_BY_NAME(n, bus, domain), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .params = &port_params[soc_type], \ .usart_mode = DT_INST_PROP(n, usart_mode), \ .external_clock = DT_INST_PROP(n, external_clock), \ + .loopback_en = DT_INST_PROP_OR(n, renesas_loopback, false), \ .type = soc_type, \ + SCIF_RESET(n) \ IRQ_FUNC_INIT \ } @@ -1341,13 +1359,17 @@ static const struct uart_driver_api uart_scif_driver_api = { \ irq_enable(DT_INST_IRQ_BY_NAME(n, name, irq)); +#define IRQ_DEFINE(inst, label) COND_CODE_1(DT_IRQ_HAS_NAME(DT_DRV_INST(inst), label), \ + (UART_SET_IRQ(inst, label);), (EMPTY)) + #define UART_SCIF_IRQ_CONFIG_FUNC_RZ(n) \ static void irq_config_func_##n(const struct device *dev) \ { \ - UART_SET_IRQ(n, eri); \ - UART_SET_IRQ(n, rxi); \ - UART_SET_IRQ(n, txi); \ - UART_SET_IRQ(n, tei); \ + IRQ_DEFINE(n, eri); \ + IRQ_DEFINE(n, bri); \ + IRQ_DEFINE(n, rxi); \ + IRQ_DEFINE(n, txi); \ + IRQ_DEFINE(n, tei); \ } #define UART_SCIF_IRQ_CFG_FUNC_INIT(n) \ .irq_config_func = irq_config_func_##n @@ -1422,6 +1444,7 @@ static const struct uart_driver_api uart_scif_driver_api = { #ifdef CONFIG_UART_INTERRUPT_DRIVEN #define UART_SCIF_IRQ_CONFIG_FUNC UART_SCIF_IRQ_CONFIG_FUNC_SCIFA #endif +#define SCIF_RESET(n) DT_INST_FOREACH_STATUS_OKAY(UART_SCIF_SCIFA_INIT) #undef DT_DRV_COMPAT @@ -1432,3 +1455,14 @@ DT_INST_FOREACH_STATUS_OKAY(UART_SCIF_SCIFA_INIT) #endif #define UART_SCIF_RZ_INIT(n) UART_SCIF_XXX_INIT(n, SCIF_RZ_SCIFA_TYPE) DT_INST_FOREACH_STATUS_OKAY(UART_SCIF_RZ_INIT) + +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT renesas_rzg3s_scif +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +#undef UART_SCIF_IRQ_CONFIG_FUNC +#define UART_SCIF_IRQ_CONFIG_FUNC UART_SCIF_IRQ_CONFIG_FUNC_RZ +#endif +#undef SCIF_RESET +#define SCIF_RESET(n) .reset = RESET_DT_SPEC_INST_GET(n), +#define UART_SCIF_RZ_INIT(n) UART_SCIF_XXX_INIT(n, SCIF_RZ_SCIFA_TYPE) +DT_INST_FOREACH_STATUS_OKAY(UART_SCIF_RZ_INIT) diff --git a/drivers/spi/Kconfig.renesas b/drivers/spi/Kconfig.renesas index 193d81082b89e4..7efba13ec7b233 100644 --- a/drivers/spi/Kconfig.renesas +++ b/drivers/spi/Kconfig.renesas @@ -10,10 +10,10 @@ config SPI_SMARTBOND Enables SPI driver for Renesas SmartBond(tm) DA1469x series MCU. config SPI_RZA2M - bool "Renesas RZ/A2M Serial Peripheral Interface" + bool "Renesas RZ/A2M and RZ/G3S Serial Peripheral Interface" default y - depends on SOC_R7S9210 depends on DT_HAS_RENESAS_RSPI_RZ_ENABLED select DMA if SPI_ASYNC help - Enables SPI driver for Renesas Serial Peripheral Interface on RZ/A2M series SoC. + Enables SPI driver for Renesas Serial Peripheral Interface + on RZ/A2M and RZ/G3S series SoC. diff --git a/drivers/spi/spi_rza2m.c b/drivers/spi/spi_rza2m.c index 770fdd3ae397de..942a475654244a 100644 --- a/drivers/spi/spi_rza2m.c +++ b/drivers/spi/spi_rza2m.c @@ -4,8 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT renesas_rspi_rz - #define LOG_LEVEL CONFIG_SPI_LOG_LEVEL #include LOG_MODULE_REGISTER(spi_rza2m); @@ -17,6 +15,9 @@ LOG_MODULE_REGISTER(spi_rza2m); #include #include #include +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rspi_r9a08g045) +#include +#endif #include #include #ifdef CONFIG_SPI_ASYNC @@ -120,12 +121,15 @@ LOG_MODULE_REGISTER(spi_rza2m); struct rza2m_spi_cfg { DEVICE_MMIO_ROM; - const uint16_t *reg_offset; + const uint32_t base_addr; const struct device *clk_dev; struct renesas_cpg_clk clk_mod; const struct pinctrl_dev_config *pcfg; uint32_t num_cs; void (*irq_config)(void); +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rspi_r9a08g045) + struct reset_dt_spec rspin_rst; +#endif #ifdef CONFIG_SPI_ASYNC const struct device *dma_dev; uint8_t tx_dma_slot; @@ -557,7 +561,7 @@ static int rza2m_spi_dma_rx_load(const struct device *dev, uint8_t *buf, size_t dma_blk.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE; } - dma_blk.source_address = (uint32_t)DEVICE_MMIO_ROM_PTR(dev)->phys_addr + RSPI_SPDR; + dma_blk.source_address = cfg->base_addr + RSPI_SPDR; dma_blk.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE; retval = dma_config(cfg->dma_dev, cfg->rx_dma_channel, &dma_cfg); @@ -608,7 +612,7 @@ static int rza2m_spi_dma_tx_load(const struct device *dev, const uint8_t *buf, s dma_blk.source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE; } - dma_blk.dest_address = (uint32_t)DEVICE_MMIO_ROM_PTR(dev)->phys_addr + RSPI_SPDR; + dma_blk.dest_address = cfg->base_addr + RSPI_SPDR; dma_blk.dest_addr_adj = DMA_ADDR_ADJ_NO_CHANGE; retval = dma_config(cfg->dma_dev, cfg->tx_dma_channel, &dma_cfg); @@ -839,6 +843,10 @@ static int rza2m_spi_init(const struct device *dev) return ret; } +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rspi_r9a08g045) + (void)reset_line_toggle_dt(&cfg->rspin_rst); +#endif + ret = spi_context_cs_configure_all(&ctx->spi_ctx); if (ret < 0) { LOG_DEV_ERR(dev, "Failed to configure CS pins: %d", ret); @@ -858,7 +866,21 @@ static int rza2m_spi_init(const struct device *dev) return 0; } -#define RZA2M_SPI_IRQ_CONFIG_FUNC(n) \ +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_rspi_r7s9210) +/* RZ/A2M compatible */ +#define DT_DRV_COMPAT renesas_rspi_r7s9210 +#define RSPI_IRQ_CONFIG_FUNC RSPI_GIC_IRQ_CONFIG_FUNC +#define RSPI_RESET(n) +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rspi_r9a08g045) +/* RZ/G3S compatible */ +#define DT_DRV_COMPAT renesas_rspi_r9a08g045 +#define RSPI_IRQ_CONFIG_FUNC RSPI_NVIC_IRQ_CONFIG_FUNC +#define RSPI_RESET(n) .rspin_rst = RESET_DT_SPEC_INST_GET_BY_IDX(n, 0), +#else +#error "Wrong compatible for Renesas RSPI" +#endif + +#define RSPI_GIC_IRQ_CONFIG_FUNC(n) \ static void rza2m_irq_config_##n(void) \ { \ IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, rx, irq), \ @@ -873,6 +895,21 @@ static int rza2m_spi_init(const struct device *dev) irq_enable(DT_INST_IRQ_BY_NAME(n, tx, irq)); \ } +#define RSPI_NVIC_IRQ_CONFIG_FUNC(n) \ + static void rza2m_irq_config_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, rx, irq), \ + DT_INST_IRQ_BY_NAME(n, rx, priority), \ + rza2m_spi_irq_rx, \ + DEVICE_DT_INST_GET(n), 0); \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, tx, irq), \ + DT_INST_IRQ_BY_NAME(n, tx, priority), \ + rza2m_spi_irq_tx, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQ_BY_NAME(n, rx, irq)); \ + irq_enable(DT_INST_IRQ_BY_NAME(n, tx, irq)); \ + } + #ifdef CONFIG_SPI_ASYNC #define SPI_RZA2M_DMA_CHANNELS(n) \ .dma_dev = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(n, tx)), \ @@ -886,15 +923,17 @@ static int rza2m_spi_init(const struct device *dev) #define RZA2M_SPI_DEVICE(n) \ PINCTRL_DT_INST_DEFINE(n); \ - RZA2M_SPI_IRQ_CONFIG_FUNC(n) \ + RSPI_IRQ_CONFIG_FUNC(n) \ static const struct rza2m_spi_cfg rza2m_spi_##id##_cfg = { \ DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ + .base_addr = DT_INST_REG_ADDR(n), \ .clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_IDX(n, 0)), \ .clk_mod.module = DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module), \ .clk_mod.domain = DT_INST_CLOCKS_CELL_BY_IDX(n, 0, domain), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .num_cs = DT_INST_PROP_OR(n, num_cs, 1), \ .irq_config = rza2m_irq_config_##n, \ + RSPI_RESET(n) \ SPI_RZA2M_DMA_CHANNELS(n) \ }; \ static struct rza2m_spi_ctx rza2m_spi_##id##_data = { \ @@ -903,7 +942,8 @@ static int rza2m_spi_init(const struct device *dev) SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), spi_ctx) \ }; \ DEVICE_DT_INST_DEFINE(n, rza2m_spi_init, NULL, &rza2m_spi_##id##_data, \ - &rza2m_spi_##id##_cfg, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \ + &rza2m_spi_##id##_cfg, POST_KERNEL, \ + CONFIG_SPI_INIT_PRIORITY, \ &rza2m_spi_driver_api); DT_INST_FOREACH_STATUS_OKAY(RZA2M_SPI_DEVICE) diff --git a/drivers/timer/Kconfig.rz b/drivers/timer/Kconfig.rz index c9d1035c1b2c46..bf671d77efe865 100644 --- a/drivers/timer/Kconfig.rz +++ b/drivers/timer/Kconfig.rz @@ -4,10 +4,10 @@ config RZ_OS_TIMER bool "Renesas RZ OS timer" default y - depends on DT_HAS_RENESAS_OSTM_ENABLED + depends on DT_HAS_RENESAS_OSTM_TIMER_ENABLED select TIMER_READS_ITS_FREQUENCY_AT_RUNTIME select SYSTEM_TIMER_HAS_DISABLE_SUPPORT select TICKLESS_CAPABLE help - This module implements a kernel device driver for the Renesas RZ + This module implements a kernel device driver for the Renesas RZ A2M/G3S platform provides the standard "system clock driver" interfaces. diff --git a/drivers/timer/rz_os_timer.c b/drivers/timer/rz_os_timer.c index 933207047031f6..307f82667c6356 100644 --- a/drivers/timer/rz_os_timer.c +++ b/drivers/timer/rz_os_timer.c @@ -10,8 +10,11 @@ #include #include #include +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045_timer) +#include +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045_timer) */ -#define DT_DRV_COMPAT renesas_ostm +#define DT_DRV_COMPAT renesas_ostm_timer DEVICE_MMIO_TOPLEVEL_STATIC(ostm_base, DT_DRV_INST(0)); @@ -146,6 +149,9 @@ static int sys_clock_driver_init(void) { int ret; const struct device *clk; +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045_timer) + struct reset_dt_spec rspin_rst = RESET_DT_SPEC_INST_GET(0); +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045_timer) */ struct renesas_cpg_clk mod_clk = { .module = DT_INST_CLOCKS_CELL(0, module), @@ -157,6 +163,12 @@ static int sys_clock_driver_init(void) return -ENODEV; } +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045_timer) + if (!device_is_ready(rspin_rst.dev)) { + return -ENODEV; + } +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045_timer) */ + ret = clock_control_on(clk, (clock_control_subsys_t)&mod_clk); if (ret < 0) { return ret; @@ -168,12 +180,20 @@ static int sys_clock_driver_init(void) return ret; } +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045_timer) + (void)reset_line_deassert_dt(&rspin_rst); +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045_timer) */ + cyc_per_tick = sys_clock_hw_cycles_per_sec() / CONFIG_SYS_CLOCK_TICKS_PER_SEC; DEVICE_MMIO_TOPLEVEL_MAP(ostm_base, K_MEM_CACHE_NONE); +#if DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045_timer) + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), ostm_irq_handler, NULL, 0); +#else IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), ostm_irq_handler, NULL, DT_INST_IRQ(0, flags)); +#endif /* DT_HAS_COMPAT_STATUS_OKAY(renesas_ostm_r9a08g045_timer) */ /* restarting the timer will cause reset of CNT register in free-running mode */ sys_clock_disable(); diff --git a/drivers/watchdog/CMakeLists.txt b/drivers/watchdog/CMakeLists.txt index 3223a3f52a784e..ae54ff2a5a320a 100644 --- a/drivers/watchdog/CMakeLists.txt +++ b/drivers/watchdog/CMakeLists.txt @@ -26,7 +26,8 @@ zephyr_library_sources_ifdef(CONFIG_WDT_NPM1300 wdt_npm1300.c) zephyr_library_sources_ifdef(CONFIG_WDT_NPM6001 wdt_npm6001.c) zephyr_library_sources_ifdef(CONFIG_WDT_NRFX wdt_nrfx.c) zephyr_library_sources_ifdef(CONFIG_WDT_RPI_PICO wdt_rpi_pico.c) -zephyr_library_sources_ifdef(CONFIG_WDT_RZ wdt_rza.c) +zephyr_library_sources_ifdef(CONFIG_WDT_RZA wdt_rza.c) +zephyr_library_sources_ifdef(CONFIG_WDT_RZG wdt_rzg.c) zephyr_library_sources_ifdef(CONFIG_WDT_SAM wdt_sam.c) zephyr_library_sources_ifdef(CONFIG_WDT_SAM0 wdt_sam0.c) zephyr_library_sources_ifdef(CONFIG_WDT_SIFIVE wdt_sifive.c) diff --git a/drivers/watchdog/Kconfig.rz b/drivers/watchdog/Kconfig.rz index b59fd5f79a6936..7565a171e33cf7 100644 --- a/drivers/watchdog/Kconfig.rz +++ b/drivers/watchdog/Kconfig.rz @@ -3,17 +3,25 @@ # Copyright (C) 2023 EPAM Systems # SPDX-License-Identifier: Apache-2.0 -config WDT_RZ - bool "Renesas RZ Watchdog (WDT) Driver" +config WDT_RZA + bool "Renesas RZA Watchdog (WDT) Driver" default y depends on DT_HAS_RENESAS_RZA_WDT_ENABLED depends on CLOCK_CONTROL help - Enable WDT driver for Renesas RZ. + Enable WDT driver for Renesas RZA. + +config WDT_RZG + bool "Renesas RZG Watchdog (WDT) Driver" + default y + depends on DT_HAS_RENESAS_RZG_WDT_ENABLED + depends on CLOCK_CONTROL + help + Enable WDT driver for Renesas RZG. config WDT_RZ_INIT_PRIORITY int "Renesas RZ Watchdog driver initialization priority" - depends on WDT_RZ + depends on WDT_RZA || WDT_RZG default 65 help Initialization priority for the Renesas RZ Watchdog driver. diff --git a/drivers/watchdog/wdt_rzg.c b/drivers/watchdog/wdt_rzg.c new file mode 100644 index 00000000000000..23781df687b2bd --- /dev/null +++ b/drivers/watchdog/wdt_rzg.c @@ -0,0 +1,504 @@ +/* + * Copyright (C) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_rzg_wdt + +/* + * *************************** INCLUDES ***************************** + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * *************************** CONSTANTS ***************************** + */ +/* WDT registers */ +#define WDTCNT 0x00 +#define WDTSET 0x04 +#define WDTTIM 0x08 +#define WDTINT 0x0C +#define PECR 0x10 +#define PEEN 0x14 + +/* WDT Register bits */ +#define WDTCNT_WDTEN BIT(0) +#define WDTINT_INTDISP BIT(0) +#define PEEN_FORCE BIT(0) + +/* System controller registers */ +#define SYS_WDT1_CTRL 0x260 +#define SYS_WDT2_CTRL 0x270 + +/* System controller register bits */ +#define WDTN_CTRL_WDTSTOPMASK BIT(16) + +/* CPG WDT registers */ +#define CPG_WDTOVF_RST 0x0 +#define CPG_WDTRST_SEL 0x4 + +/* CPG WDT register bits */ +#define CPG_WDTRST_SEL1 BIT(1) +#define CPG_WDTRST_SEL2 BIT(2) +#define CPG_WDTRST_SEL9 BIT(9) +#define CPG_WDTRST_SEL10 BIT(10) +#define CPG_WDTRST_SEL1_WEN BIT(17) +#define CPG_WDTRST_SEL2_WEN BIT(18) +#define CPG_WDTRST_SEL9_WEN BIT(25) +#define CPG_WDTRST_SEL10_WEN BIT(26) + +/* Other constants */ +#define WDTSET_COUNTER_VAL(f) ((f) << 20) + +/* + * **************************** MACROS ******************************* + */ +LOG_MODULE_REGISTER(wdt_rzg, CONFIG_WDT_LOG_LEVEL); + +#define DEV_DATA(dev) ((struct wdt_rzg_data *)((dev)->data)) +#define DEV_CFG(dev) ((struct wdt_rzg_config *)((dev)->config)) + +#define RZG_WDT_REG(dev) DEVICE_MMIO_NAMED_GET(dev, wdt_reg) +#define RZG_CPG_REG(dev) DEVICE_MMIO_NAMED_GET(dev, cpg_reg) + +/* + * *********************** TYPE DECLARATIONS ************************* + */ +enum wdt_timer_idx { + WDT1_IDX = 1, + WDT2_IDX = 2 +}; + +struct wdt_rzg_config { + /* Must be first */ + DEVICE_MMIO_NAMED_ROM(wdt_reg); + DEVICE_MMIO_NAMED_ROM(cpg_reg); + /* pointer to clock device for WDT */ + const struct device *cpg; + /* pointer to IRQ configuration function */ + void (*irq_config)(void); + /* WDT clocks */ + struct renesas_cpg_clk pclk; + struct renesas_cpg_clk oscclk; + /* reset controller */ + struct reset_dt_spec wdt_rstn; + /* pointer to system controller */ + const struct device *syscon; + /* timer index */ + const enum wdt_timer_idx timer_idx; + /* WDT IRQ number */ + const uint8_t irq_num; +}; + +struct wdt_rzg_data { + /* Must be first */ + DEVICE_MMIO_NAMED_RAM(wdt_reg); + DEVICE_MMIO_NAMED_RAM(cpg_reg); + uint32_t clk_rate; + /* user callback */ + wdt_callback_t callback; +}; + +/* + * ************************* PRIVATE FUNCTIONS *************************** + */ + +/** + * @brief Function calculate WDTTIME value for WDTSET_n register + * + * @param wdt_clk - Watchdog clock rate in Hz + * @param wdt_cycle_ms - Required watchdog cycle time in ms + * + * @return WDTTIME value. If value < 0 or > 0xFFF this means an error + */ +static int32_t wdt_rzg_get_wdttime(uint32_t wdt_clk, uint32_t wdt_cycle_ms) +{ + return (wdt_clk / 1000) * wdt_cycle_ms / (1024 * 1024) - 1; +} + +/** + * @brief Function performs write value to RZ/G WDT register + * + * @param dev - Pointer to RZ/G watchdog device + * @param value - Value to write + * @param reg - WDT register offset + * + * @return none + */ +static void wdt_rzg_write(const struct device *dev, uint32_t value, uint32_t reg) +{ + sys_write32(value, RZG_WDT_REG(dev) + reg); + + /* Registers other than the WDTINT is always synchronized with WDT_CLK */ + if (reg != WDTINT) { + k_busy_wait(1); + } +} + +/** + * @brief Function performs write value to RZ/G CPG register related to WDT + * Used for accessing to CPG_WDTOVF_RST and CPG_WDTRST_SEL registers + * + * @param dev - Pointer to RZ/G watchdog device + * @param value - Value to write + * @param reg - CPG register offset (start from CPG_WDTOVF_RST) + * + * @return none + */ +static void wdt_cpg_rzg_write(const struct device *dev, uint32_t value, uint32_t reg) +{ + sys_write32(value, RZG_CPG_REG(dev) + reg); +} + +/** + * @brief Function performs read value from RZ/G CPG register related to WDT + * Used for accessing to CPG_WDTOVF_RST and CPG_WDTRST_SEL registers + * + * @param dev - Pointer to RZ/G watchdog device + * @param reg - CPG register offset (start from CPG_WDTOVF_RST) + * + * @return Read value + */ +static uint32_t wdt_cpg_rzg_read(const struct device *dev, uint32_t reg) +{ + return sys_read32(RZG_CPG_REG(dev) + reg); +} + +/** + * @brief Function controls the stop function of WDT + * from CoreSight during debugging + * + * @param dev - Pointer to RZ/G watchdog device + * @param on - if true, stops WDT counting during debugging, + * if false, not stop WDT counting during debugging + * + * @return none + */ +static void wdt_rzg_set_stop_in_dbg(const struct device *dev, bool on) +{ + const struct wdt_rzg_config *config = dev->config; + const struct device *syscon = config->syscon; + uint32_t reg, val; + + /* We use timer index to identify wdt1 or wdt2 */ + switch (config->timer_idx) { + case WDT1_IDX: + reg = SYS_WDT1_CTRL; + break; + + case WDT2_IDX: + reg = SYS_WDT2_CTRL; + break; + + default: + LOG_ERR("%s: wrong index: %d", dev->name, config->timer_idx); + return; + } + + syscon_read_reg(syscon, reg, &val); + /* WDTSTOPMASK must be 0 for stops WDT during debugging */ + if (on) { + syscon_write_reg(syscon, reg, (val & ~WDTN_CTRL_WDTSTOPMASK)); + } else { + syscon_write_reg(syscon, reg, (val | WDTN_CTRL_WDTSTOPMASK)); + } +} + +/** + * @brief Function enable or disable entire system reset from WDT + * + * @param dev - Pointer to RZ/G watchdog device + * @param on - if true, system reset from this WDT enabled + * if false, system reset from this WDT disabled + * + * @return none + */ +static void wdt_rzg_set_system_reset(const struct device *dev, bool on) +{ + const struct wdt_rzg_config *config = dev->config; + uint32_t val = wdt_cpg_rzg_read(dev, CPG_WDTRST_SEL); + + /* We use timer index to identify wdt1 or wdt2 */ + switch (config->timer_idx) { + case WDT1_IDX: + val |= CPG_WDTRST_SEL1_WEN; + val = (on) ? (val | CPG_WDTRST_SEL1) : (val & ~CPG_WDTRST_SEL1); + break; + + case WDT2_IDX: + val |= CPG_WDTRST_SEL2_WEN; + val = (on) ? (val | CPG_WDTRST_SEL2) : (val & ~CPG_WDTRST_SEL2); + break; + + default: + LOG_ERR("%s: wrong index: %d", dev->name, config->timer_idx); + return; + } + + wdt_cpg_rzg_write(dev, val, CPG_WDTRST_SEL); +} + +/** + * @brief Function enable or disable single core cold-reset from WDT + * WDT1 used to reset Cortex-M33, WDT2 used to reset Cortex-M33_FPU + * + * @param dev - Pointer to RZ/G watchdog device + * @param on - if true, corresponding core reset from this WDT enabled + * if false, corresponding core reset from this WDT disabled + * + * @return none + */ +static void wdt_rzg_set_core_reset(const struct device *dev, bool on) +{ + const struct wdt_rzg_config *config = dev->config; + uint32_t val = wdt_cpg_rzg_read(dev, CPG_WDTRST_SEL); + + /* We use timer index to identify wdt1 or wdt2 */ + switch (config->timer_idx) { + case WDT1_IDX: + val |= CPG_WDTRST_SEL9_WEN; + val = (on) ? (val | CPG_WDTRST_SEL9) : (val & ~CPG_WDTRST_SEL9); + break; + + case WDT2_IDX: + val |= CPG_WDTRST_SEL10_WEN; + val = (on) ? (val | CPG_WDTRST_SEL10) : (val & ~CPG_WDTRST_SEL10); + break; + + default: + LOG_ERR("%s: wrong index: %d", dev->name, config->timer_idx); + return; + } + + wdt_cpg_rzg_write(dev, val, CPG_WDTRST_SEL); +} + +static int wdt_rzg_disable(const struct device *dev) +{ + const struct wdt_rzg_config *config = dev->config; + + irq_disable(config->irq_num); + + /* We have no other way to stop the WDT other than resetting it */ + return reset_line_toggle_dt(&config->wdt_rstn); +} + +static int wdt_rzg_setup(const struct device *dev, uint8_t options) +{ + if (options & WDT_OPT_PAUSE_IN_SLEEP) { + LOG_ERR("%s: pause in sleep not supported", dev->name); + return -ENOTSUP; + } + + /* TODO: Figure out why WDT doesn't stop during debugging! */ + wdt_rzg_set_stop_in_dbg(dev, !!(options & WDT_OPT_PAUSE_HALTED_BY_DBG)); + + /* Reset watchdog counter register */ + wdt_rzg_write(dev, 0, WDTTIM); + + /* Enable watchdog timer*/ + wdt_rzg_write(dev, WDTCNT_WDTEN, WDTCNT); + + return 0; +} + +/** + * @brief This function must be called periodically to avoid WDT overflow + * and system reset + * + * @param dev - Pointer to RZ/G watchdog device + * @param channel_id - Not used + * @param reg - 0 on success + * + * @return none + */ +static int wdt_rzg_feed(const struct device *dev, int channel_id) +{ + struct wdt_rzg_data *data = dev->data; + const struct wdt_rzg_config *config = dev->config; + + /* Clear overflow interrupt */ + wdt_rzg_write(dev, WDTINT_INTDISP, WDTINT); + + if (data->callback) { + /* Re-enable interrupts, if we use callback */ + irq_enable(config->irq_num); + } + + return 0; +} + +static int wdt_rzg_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *timeout) +{ + struct wdt_rzg_data *data = dev->data; + const struct wdt_rzg_config *config = dev->config; + int32_t wdttime; + +#ifdef CONFIG_WDT_MULTISTAGE + if (timeout->next) { + LOG_ERR("%s: multistaging isn't supported", dev->name); + return -ENOTSUP; + } +#endif + + if (!timeout->window.max || timeout->window.min > timeout->window.max) { + LOG_ERR("%s: invalid timeout val(s) min %u max %u", + dev->name, timeout->window.min, timeout->window.max); + return -EINVAL; + } + + data->callback = timeout->callback; + + wdt_rzg_disable(dev); + + /* Set mode of watchdog and callback */ + wdt_rzg_set_system_reset(dev, false); + wdt_rzg_set_core_reset(dev, false); + switch (timeout->flags) { + case WDT_FLAG_RESET_SOC: + wdt_rzg_set_system_reset(dev, true); + LOG_DBG("%s: configuring reset SOC mode", dev->name); + break; + case WDT_FLAG_RESET_CPU_CORE: + wdt_rzg_set_core_reset(dev, true); + LOG_DBG("%s: configuring reset single core mode", dev->name); + break; + case WDT_FLAG_RESET_NONE: + LOG_DBG("%s: configuring non-reset mode", dev->name); + break; + default: + LOG_ERR("%s: unsupported watchdog config flag (0x%08x)", dev->name, timeout->flags); + return -EINVAL; + } + + if (data->callback) { + /* Enable interrupts, only if we use callback */ + irq_enable(config->irq_num); + } + + /* 2 consecutive overflow cycle needed to trigger reset */ + wdttime = wdt_rzg_get_wdttime(data->clk_rate, timeout->window.max / 2); + if (wdttime < 0 || wdttime > 0xFFF) { + LOG_ERR("%s: The requested timeout %u is outside the possible limits", + dev->name, timeout->window.max); + return -EINVAL; + } + wdt_rzg_write(dev, WDTSET_COUNTER_VAL(wdttime), WDTSET); + + return 0; +} + +static int wdt_rzg_init(const struct device *dev) +{ + const struct wdt_rzg_config *config = dev->config; + struct wdt_rzg_data *data = dev->data; + const struct device *cpg = config->cpg; + int ret; + + if (!device_is_ready(cpg)) { + LOG_ERR("%s: error cpg isn't ready", dev->name); + return -ENODEV; + } + + ret = clock_control_on(cpg, (clock_control_subsys_t)&config->pclk); + if (ret != 0) { + LOG_ERR("Can't turn on pclk clock for %s\n", dev->name); + return ret; + } + + ret = clock_control_on(cpg, (clock_control_subsys_t)&config->oscclk); + if (ret != 0) { + LOG_ERR("Can't turn on oscclk clock for %s\n", dev->name); + goto err; + } + + /* We don't expect that someone would change the rate after initializing the CPG driver */ + ret = clock_control_get_rate(cpg, (clock_control_subsys_t)&config->oscclk, + &data->clk_rate); + if (ret < 0) { + LOG_ERR("Can't get clock rate for %s\n", dev->name); + goto err; + } + + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + + /* Reset device */ + (void)reset_line_toggle_dt(&config->wdt_rstn); + + config->irq_config(); + + return 0; + +err: + /* On error */ + clock_control_off(cpg, (clock_control_subsys_t)&config->oscclk); + clock_control_off(cpg, (clock_control_subsys_t)&config->pclk); + return ret; +} + +static void wdt_rgz_isr(const struct device *dev) +{ + struct wdt_rzg_data *data = dev->data; + const struct wdt_rzg_config *config = dev->config; + + LOG_DBG("%s: wdtr irq", dev->name); + /* Disable interrupts to avoid IRQ storm */ + irq_disable(config->irq_num); + + if (data->callback) { + data->callback(dev, 0); + } +} + +/* + * ************************* DRIVER INSTANTIATION SECTION *************************** + */ +static const struct wdt_driver_api wdt_rzg_api = { + .setup = wdt_rzg_setup, + .disable = wdt_rzg_disable, + .install_timeout = wdt_rzg_install_timeout, + .feed = wdt_rzg_feed, +}; + +#define WDT_RGZ_IRQ_CONFIG_FUNC(n) \ + static void wdt_rgz_irq_config_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, wdt, irq), \ + DT_INST_IRQ_BY_NAME(n, wdt, priority), \ + wdt_rgz_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + } + +#define WDT_RZG_DEFINE(n) \ + WDT_RGZ_IRQ_CONFIG_FUNC(n) \ + static const struct wdt_rzg_config wdt_rzg_config##n = { \ + DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(wdt_reg, DT_DRV_INST(n)), \ + DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(cpg_reg, DT_DRV_INST(n)), \ + .cpg = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .irq_config = wdt_rgz_irq_config_##n, \ + .oscclk.module = DT_INST_CLOCKS_CELL_BY_NAME(n, oscclk, module), \ + .oscclk.domain = DT_INST_CLOCKS_CELL_BY_NAME(n, oscclk, domain), \ + .pclk.module = DT_INST_CLOCKS_CELL_BY_NAME(n, pclk, module), \ + .pclk.domain = DT_INST_CLOCKS_CELL_BY_NAME(n, pclk, domain), \ + .wdt_rstn = RESET_DT_SPEC_INST_GET_BY_IDX(n, 0), \ + .syscon = DEVICE_DT_GET(DT_NODELABEL(syscon)), \ + .timer_idx = DT_INST_PROP(n, timer_idx), \ + .irq_num = DT_INST_IRQN(n), \ + }; \ + \ + static struct wdt_rzg_data wdt_rzg_data##n; \ + DEVICE_DT_INST_DEFINE(n, &wdt_rzg_init, NULL, &wdt_rzg_data##n, \ + &wdt_rzg_config##n, POST_KERNEL, \ + CONFIG_WDT_RZ_INIT_PRIORITY, \ + &wdt_rzg_api); + +DT_INST_FOREACH_STATUS_OKAY(WDT_RZG_DEFINE) diff --git a/dts/arm/renesas/rz/r7s9210.dtsi b/dts/arm/renesas/rz/r7s9210.dtsi index 299d04107db07b..641844fafb601b 100644 --- a/dts/arm/renesas/rz/r7s9210.dtsi +++ b/dts/arm/renesas/rz/r7s9210.dtsi @@ -541,6 +541,7 @@ interrupt-names = "tei", "ri", "ti", "spi", "sti", "nacki", "ali", "tmoi"; clocks = <&cpg CPG_MOD 87>, <&cpg CPG_CORE R7S9210_CLK_P1>; + clock-names = "fck", "bus"; status = "disabled"; }; i2c1: i2c@e803a400 { @@ -561,6 +562,7 @@ interrupt-names = "tei", "ri", "ti", "spi", "sti", "nacki", "ali", "tmoi"; clocks = <&cpg CPG_MOD 86>, <&cpg CPG_CORE R7S9210_CLK_P1>; + clock-names = "fck", "bus"; status = "disabled"; }; i2c2: i2c@e803a800 { @@ -581,6 +583,7 @@ interrupt-names = "tei", "ri", "ti", "spi", "sti", "nacki", "ali", "tmoi"; clocks = <&cpg CPG_MOD 85>, <&cpg CPG_CORE R7S9210_CLK_P1>; + clock-names = "fck", "bus"; status = "disabled"; }; i2c3: i2c@e803ac00 { @@ -601,6 +604,7 @@ interrupt-names = "tei", "ri", "ti", "spi", "sti", "nacki", "ali", "tmoi"; clocks = <&cpg CPG_MOD 84>, <&cpg CPG_CORE R7S9210_CLK_P1>; + clock-names = "fck", "bus"; status = "disabled"; }; diff --git a/dts/arm/renesas/rz/r9a08g045.dtsi b/dts/arm/renesas/rz/r9a08g045.dtsi new file mode 100644 index 00000000000000..4fb4dffb3c8fb8 --- /dev/null +++ b/dts/arm/renesas/rz/r9a08g045.dtsi @@ -0,0 +1,1064 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/ { + compatible = "renesas,r9a08g045"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m33"; + reg = <0>; + clock-frequency = <250000000>; + #address-cells = <1>; + #size-cells = <1>; + + mpu: mpu@e000ed90 { + compatible = "arm,armv8m-mpu"; + reg = <0xe000ed90 0x40>; + arm,num-mpu-regions = <16>; + }; + }; + }; + + extal_clk: extal-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + /* This value must be overridden by the board */ + clock-frequency = <0>; + }; + + /* External CAN clock - to be overridden by boards that provide it */ + can_clk: can-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <0>; + }; + + soc { + cpg: clock-controller@41010000 { + compatible = "renesas,r9a08g045-cpg-mssr"; + reg = <0x41010000 0x10000>; + clocks = <&extal_clk>; + clock-names = "extal"; + #clock-cells = <2>; + + cpg_rctl: reset-controller { + compatible = "renesas,r9a08g045-cpg-reset"; + #reset-cells = <1>; + status = "okay"; + }; + }; + + syscon: system-controller@41020000 { + compatible = "syscon"; + reg = <0x41020000 0xE30>; + status = "okay"; + }; + + dma0: dma@41800000 { /* Secure DMA */ + compatible = "renesas,rzg3-dma"; + reg = <0x41800000 0x800>, <0x41810000 0x20>; + reg-names = "reg_main", "ext"; + interrupts = <95 0>, <96 0>, <97 0>, <98 0>, + <99 0>, <100 0>, <101 0>, <102 0>, + <103 0>, <104 0>, <105 0>, <106 0>, + <107 0>, <108 0>, <109 0>, <110 0>, + <94 0>; /* DMAERR1 */ + interrupt-names = "ch0", "ch1", "ch2", "ch3", + "ch4", "ch5", "ch6", "ch7", + "ch8", "ch9", "ch10", "ch11", + "ch12", "ch13", "ch14", "ch15", + "err1"; + dma-channels = <16>; + #dma-cells = <3>; + clocks = <&cpg CPG_MOD R9A08G045_DMAC_ACLK>, + <&cpg CPG_MOD R9A08G045_DMAC_PCLK>; + clock-names = "aclk", "pclk"; + resets = <&cpg_rctl R9A08G045_DMAC_ARESETN>, + <&cpg_rctl R9A08G045_DMAC_RST_ASYNC>; + dma-buf-addr-alignment = <4>; + status = "disabled"; + }; + + pinctrl: pin-controller@41030000 { + compatible = "renesas,r9a08g045-pinctrl"; + reg = <0x41030000 DT_SIZE_K(64)>; + reg-names = "pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + + gpio: gpio-controller@TINT_OFFSET_NODE { + compatible = "renesas,r9a08g045-gpio"; + reg = ; + reg-names = "tint"; + interrupts = + <429 0>, <430 0>, <431 0>, <432 0>, + <433 0>, <434 0>, <435 0>, <436 0>, + <437 0>, <438 0>, <439 0>, <440 0>, + <441 0>, <442 0>, <443 0>, <444 0>, + <445 0>, <446 0>, <447 0>, <448 0>, + <449 0>, <450 0>, <451 0>, <452 0>, + <453 0>, <454 0>, <455 0>, <456 0>, + <457 0>, <458 0>, <459 0>, <460 0>; + #address-cells = <1>; + #size-cells = <0>; + + port0: gpio@0 { + reg = <0x0>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <4>; + status = "disabled"; + }; + + port1: gpio@1 { + reg = <0x1>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <5>; + status = "disabled"; + }; + + port2: gpio@2 { + reg = <0x2>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <4>; + status = "disabled"; + }; + + port3: gpio@3 { + reg = <0x3>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <4>; + status = "disabled"; + }; + + port4: gpio@4 { + reg = <0x4>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <6>; + status = "disabled"; + }; + + port5: gpio@5 { + reg = <0x5>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <5>; + status = "disabled"; + }; + + port6: gpio@6 { + reg = <0x6>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <5>; + status = "disabled"; + }; + + port7: gpio@7 { + reg = <0x7>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <5>; + status = "disabled"; + }; + + port8: gpio@8 { + reg = <0x8>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <5>; + status = "disabled"; + }; + + port9: gpio@9 { + reg = <0x9>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <4>; + status = "disabled"; + }; + + port10: gpio@a { + reg = <0xa>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <5>; + status = "disabled"; + }; + + port11: gpio@b { + reg = <0xb>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <4>; + status = "disabled"; + }; + + port12: gpio@c { + reg = <0xc>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <2>; + status = "disabled"; + }; + + port13: gpio@d { + reg = <0xd>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <5>; + status = "disabled"; + }; + + port14: gpio@e { + reg = <0xe>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <3>; + status = "disabled"; + }; + + port15: gpio@f { + reg = <0xf>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <4>; + status = "disabled"; + }; + + port16: gpio@10 { + reg = <0x10>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <2>; + status = "disabled"; + }; + + port17: gpio@11 { + reg = <0x11>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <4>; + status = "disabled"; + }; + + port18: gpio@12 { + reg = <0x12>; + gpio-controller; + #gpio-cells=<2>; + ngpios = <6>; + status = "disabled"; + }; + }; + }; + + scif0: serial@4004b800 { + compatible = "renesas,rzg3s-scif"; + reg = <0x4004b800 0x18>; + interrupts = <320 0>, <321 0>, <322 0>, <323 0>, <324 0>; + interrupt-names = "eri", "bri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A08G045_SCIF0_CLK_PCK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + clock-names = "fck", "bus"; + resets = <&cpg_rctl R9A08G045_SCIF0_RST_SYSTEM_N>; + status = "disabled"; + }; + scif1: serial@4004bc00 { + compatible = "renesas,rzg3s-scif"; + reg = <0x4004bc00 0x18>; + interrupts = <325 0>, <326 0>, <327 0>, <328 0>, <329 0>; + interrupt-names = "eri", "bri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A08G045_SCIF1_CLK_PCK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + clock-names = "fck", "bus"; + resets = <&cpg_rctl R9A08G045_SCIF1_RST_SYSTEM_N>; + status = "disabled"; + }; + scif2: serial@4004c000 { + compatible = "renesas,rzg3s-scif"; + reg = <0x4004c000 0x18>; + interrupts = <330 0>, <331 0>, <332 0>, <333 0>, <334 0>; + interrupt-names = "eri", "bri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A08G045_SCIF2_CLK_PCK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + clock-names = "fck", "bus"; + resets = <&cpg_rctl R9A08G045_SCIF2_RST_SYSTEM_N>; + status = "disabled"; + }; + scif3: serial@4004c400 { + compatible = "renesas,rzg3s-scif"; + reg = <0x4004c400 0x18>; + interrupts = <335 0>, <336 0>, <337 0>, <338 0>, <339 0>; + interrupt-names = "eri", "bri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A08G045_SCIF3_CLK_PCK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + clock-names = "fck", "bus"; + resets = <&cpg_rctl R9A08G045_SCIF3_RST_SYSTEM_N>; + status = "disabled"; + }; + scif4: serial@4004c800 { + compatible = "renesas,rzg3s-scif"; + reg = <0x4004c800 0x18>; + interrupts = <340 0>, <341 0>, <342 0>, <343 0>, <344 0>; + interrupt-names = "eri", "bri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A08G045_SCIF4_CLK_PCK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + clock-names = "fck", "bus"; + resets = <&cpg_rctl R9A08G045_SCIF4_RST_SYSTEM_N>; + status = "disabled"; + }; + scif5: serial@4004e000 { + compatible = "renesas,rzg3s-scif"; + reg = <0x4004e000 0x18>; + interrupts = <345 0>, <346 0>, <347 0>, <348 0>, <349 0>; + interrupt-names = "eri", "bri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A08G045_SCIF5_CLK_PCK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + clock-names = "fck", "bus"; + resets = <&cpg_rctl R9A08G045_SCIF5_RST_SYSTEM_N>; + status = "disabled"; + }; + + intc: interrupt-controller@INTC_OFFSET_NODE { + compatible = "renesas,r9a08g045-intc"; + reg = ; + #interrupt-cells = <2>; + #address-cells = <0>; + interrupts = + <0 0>, /* NMI */ + <1 0>, <2 0>, <3 0>, <4 0>, + <5 0>, <6 0>, <7 0>, <8 0>; + map = <0 1 2 3 4 5 6 7 8>; + interrupt-controller; + interrupt-parent = <&nvic>; + }; + + i2c0: i2c@40090000 { + compatible = "renesas,rzg-riic"; + clock-frequency = <100000>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40090000 0x15>; + interrupts = <257 0>, <258 0>, <259 0>, <260 0>, + <261 0>, <262 0>, <263 0>, <264 0>; + interrupt-names = "tei", "nacki", "spi", "sti", "ali", "tmoi", "ri", "ti"; + clocks = <&cpg CPG_MOD R9A08G045_I2C0_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + clock-names = "fck", "bus"; + resets = < &cpg_rctl R9A08G045_I2C0_MRST>; + status = "disabled"; + }; + i2c1: i2c@40090400 { + compatible = "renesas,rzg-riic"; + clock-frequency = <100000>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40090400 0x15>; + interrupts = <265 0>, <266 0>, <267 0>, <268 0>, + <269 0>, <270 0>, <271 0>, <272 0>; + interrupt-names = "tei", "nacki", "spi", "sti", "ali", "tmoi", "ri", "ti"; + clocks = <&cpg CPG_MOD R9A08G045_I2C1_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + clock-names = "fck", "bus"; + resets = < &cpg_rctl R9A08G045_I2C1_MRST>; + status = "disabled"; + }; + i2c2: i2c@40090800 { + compatible = "renesas,rzg-riic"; + clock-frequency = <100000>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40090800 0x15>; + interrupts = <273 0>, <274 0>, <275 0>, <276 0>, + <277 0>, <278 0>, <279 0>, <280 0>; + interrupt-names = "tei", "nacki", "spi", "sti", "ali", "tmoi", "ri", "ti"; + clocks = <&cpg CPG_MOD R9A08G045_I2C2_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + clock-names = "fck", "bus"; + resets = < &cpg_rctl R9A08G045_I2C2_MRST>; + status = "disabled"; + }; + i2c3: i2c@40090c00 { + compatible = "renesas,rzg-riic"; + clock-frequency = <100000>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40090c00 0x15>; + interrupts = <281 0>, <282 0>, <283 0>, <284 0>, + <285 0>, <286 0>, <287 0>, <288 0>; + interrupt-names = "tei", "nacki", "spi", "sti", "ali", "tmoi", "ri", "ti"; + clocks = <&cpg CPG_MOD R9A08G045_I2C3_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + clock-names = "fck", "bus"; + resets = < &cpg_rctl R9A08G045_I2C3_MRST>; + status = "disabled"; + }; + + spi0: spi@400aa000 { + compatible = "renesas,rspi-r9a08g045", "renesas,rspi-rz"; + reg = <0x400aa000 0x24>; + interrupts = <358 0>, <359 0>, <360 0>; + interrupt-names = "error", "rx", "tx"; + interrupt-parent = <&nvic>; + clocks = <&cpg CPG_MOD R9A08G045_RSPI0_CLKB>; + resets = <&cpg_rctl R9A08G045_RSPI0_RST>; + num-cs = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi1: spi@400aa400 { + compatible = "renesas,rspi-r9a08g045", "renesas,rspi-rz"; + reg = <0x400aa400 0x24>; + interrupts = <361 0>, <362 0>, <363 0>; + interrupt-names = "error", "rx", "tx"; + interrupt-parent = <&nvic>; + clocks = <&cpg CPG_MOD R9A08G045_RSPI1_CLKB>; + resets = <&cpg_rctl R9A08G045_RSPI1_RST>; + num-cs = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi2: spi@400aa800 { + compatible = "renesas,rspi-r9a08g045", "renesas,rspi-rz"; + reg = <0x400aa800 0x24>; + interrupts = <364 0>, <365 0>, <366 0>; + interrupt-names = "error", "rx", "tx"; + interrupt-parent = <&nvic>; + clocks = <&cpg CPG_MOD R9A08G045_RSPI2_CLKB>; + resets = <&cpg_rctl R9A08G045_RSPI2_RST>; + num-cs = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi3: spi@400aac00 { + compatible = "renesas,rspi-r9a08g045", "renesas,rspi-rz"; + reg = <0x400aac00 0x24>; + interrupts = <367 0>, <368 0>, <369 0>; + interrupt-names = "error", "rx", "tx"; + interrupt-parent = <&nvic>; + clocks = <&cpg CPG_MOD R9A08G045_RSPI3_CLKB>; + resets = <&cpg_rctl R9A08G045_RSPI3_RST>; + num-cs = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi4: spi@400ab000 { + compatible = "renesas,rspi-r9a08g045", "renesas,rspi-rz"; + reg = <0x400ab000 0x24>; + interrupts = <370 0>, <371 0>, <372 0>; + interrupt-names = "error", "rx", "tx"; + interrupt-parent = <&nvic>; + clocks = <&cpg CPG_MOD R9A08G045_RSPI4_CLKB>; + resets = <&cpg_rctl R9A08G045_RSPI4_RST>; + num-cs = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + /* WDT to check the operation of Cortex-M33 CPU */ + wdt1: watchdog@42800400 { + compatible = "renesas,r9a08g045-wdt", "renesas,rzg-wdt"; + reg = <0x42800400 0x24>, <0x41010B10 0x8>; + reg-names = "wdt_reg", "cpg_reg"; + timer-idx = <1>; + clocks = <&cpg CPG_MOD R9A08G045_WDT1_PCLK>, + <&cpg CPG_MOD R9A08G045_WDT1_CLK>; + clock-names = "pclk", "oscclk"; + interrupts = <55 0>, <54 0>; + interrupt-names = "wdt", "perrout"; + resets = <&cpg_rctl R9A08G045_WDT1_PRESETN>; + status = "disabled"; + }; + /* WDT to check the operation of Cortex-M33 CPU with FPU */ + wdt2: watchdog@42800000 { + compatible = "renesas,r9a08g045-wdt", "renesas,rzg-wdt"; + reg = <0x42800000 0x24>, <0x41010B10 0x8>; + reg-names = "wdt_reg", "cpg_reg"; + timer-idx = <2>; + clocks = <&cpg CPG_MOD R9A08G045_WDT2_PCLK>, + <&cpg CPG_MOD R9A08G045_WDT2_CLK>; + clock-names = "pclk", "oscclk"; + interrupts = <57 0>, <56 0>; + interrupt-names = "wdt", "perrout"; + resets = <&cpg_rctl R9A08G045_WDT2_PRESETN>; + status = "disabled"; + }; + + adc: adc@40058000 { + compatible = "renesas,rzg3s-adc"; + reg = <0x40058000 0x80>; + interrupts = <312 0>; + clocks = <&cpg CPG_MOD R9A08G045_ADC_ADCLK>, + <&cpg CPG_MOD R9A08G045_ADC_PCLK>; + clock-names = "adclk", "pclk"; + resets = <&cpg_rctl R9A08G045_ADC_PRESETN>, + <&cpg_rctl R9A08G045_ADC_ADRST_N>; + reset-names = "presetn", "adrst-n"; + status = "disabled"; + #io-channel-cells = <1>; + }; + + canfd: can@400c0000 { + compatible = "renesas,r9a08g045-canfd", "renesas,rzg3s-canfd"; + reg = <0x400c0000 DT_SIZE_K(128)>; + interrupts = <373 0>, <374 0>; + interrupt-names = "g_err", "g_recc"; + clocks = <&cpg CPG_MOD R9A08G045_CANFD_CLK_RAM>, + <&cpg CPG_MOD R9A08G045_CANFD_PCLK>, + <&can_clk>; + clock-names = "fck", "canfd", "can_clk"; + resets = <&cpg_rctl R9A08G045_CANFD_RSTP_N>, + <&cpg_rctl R9A08G045_CANFD_RSTC_N>; + reset-names = "rstp_n", "rstc_n"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + + canfd0: can_channel@0 { + reg = <0x0>; + interrupts = <375 0>, <377 0>, <379 0>; + interrupt-names = "ch_rec", "ch_err", "ch_trx"; + status = "disabled"; + }; + + canfd1: can_channel@1 { + reg = <0x1>; + interrupts = <376 0>, <378 0>, <380 0>; + interrupt-names = "ch_rec", "ch_err", "ch_trx"; + status = "disabled"; + }; + }; + + gtm0: timer@42801000 { + compatible = "renesas,ostm-r9a08g045", "renesas,ostm"; + reg = <0x42801000 0x30>; + interrupts = <44 0>; + clocks = <&cpg CPG_MOD R9A08G045_OSTM0_PCLK>; + resets = <&cpg_rctl R9A08G045_OSTM0_PRESETZ>; + status = "disabled"; + }; + + gtm1: timer@42801400 { + compatible = "renesas,ostm-r9a08g045", "renesas,ostm"; + reg = <0x42801400 0x30>; + interrupts = <45 0>; + clocks = <&cpg CPG_MOD R9A08G045_OSTM1_PCLK>; + resets = <&cpg_rctl R9A08G045_OSTM1_PRESETZ>; + status = "disabled"; + }; + + gtm2: timer@42801800 { + compatible = "renesas,ostm-r9a08g045", "renesas,ostm"; + reg = <0x42801800 0x30>; + interrupts = <46 0>; + clocks = <&cpg CPG_MOD R9A08G045_OSTM2_PCLK>; + resets = <&cpg_rctl R9A08G045_OSTM2_PRESETZ>; + status = "disabled"; + }; + + gtm3: timer@42801c00 { + compatible = "renesas,ostm-r9a08g045", "renesas,ostm"; + reg = <0x42801c00 0x30>; + interrupts = <47 0>; + clocks = <&cpg CPG_MOD R9A08G045_OSTM3_PCLK>; + resets = <&cpg_rctl R9A08G045_OSTM3_PRESETZ>; + status = "disabled"; + }; + + gtm4: timer@42802000 { + compatible = "renesas,ostm-r9a08g045", "renesas,ostm"; + reg = <0x42802000 0x30>; + interrupts = <48 0>; + clocks = <&cpg CPG_MOD R9A08G045_OSTM4_PCLK>; + resets = <&cpg_rctl R9A08G045_OSTM4_PRESETZ>; + status = "disabled"; + }; + + gtm5: timer@42802400 { + compatible = "renesas,ostm-r9a08g045", "renesas,ostm"; + reg = <0x42802400 0x30>; + interrupts = <49 0>; + clocks = <&cpg CPG_MOD R9A08G045_OSTM5_PCLK>; + resets = <&cpg_rctl R9A08G045_OSTM5_PRESETZ>; + status = "disabled"; + }; + + gtm6: timer@42802800 { + compatible = "renesas,ostm-r9a08g045", "renesas,ostm"; + reg = <0x42802800 0x30>; + interrupts = <50 0>; + clocks = <&cpg CPG_MOD R9A08G045_OSTM6_PCLK>; + resets = <&cpg_rctl R9A08G045_OSTM6_PRESETZ>; + status = "disabled"; + }; + + gtm7: timer@42802c00 { + compatible = "renesas,ostm-r9a08g045", "renesas,ostm"; + reg = <0x42802c00 0x30>; + interrupts = <51 0>; + clocks = <&cpg CPG_MOD R9A08G045_OSTM7_PCLK>; + resets = <&cpg_rctl R9A08G045_OSTM7_PRESETZ>; + status = "disabled"; + }; + + /* General Purpose PWM Timer Channels */ + gpt32e0: gpt32e0@50048000 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x50048000 0xa4>; + reg-names = "GPT32E"; + interrupts = <128 0>, + <129 0>, + <130 0>, + <131 0>, + <132 0>, + <133 0>, + <134 0>, + <135 0>, + <136 0>, + <137 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <0>; + status = "disabled"; + }; + + gpt32e1: gpt32e1@50048100 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x50048100 0xa4>; + reg-names = "GPT32E"; + interrupts = <141 0>, + <142 0>, + <143 0>, + <144 0>, + <145 0>, + <146 0>, + <147 0>, + <148 0>, + <149 0>, + <150 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <1>; + status = "disabled"; + }; + + gpt32e2: gpt32e2@50048200 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x50048200 0xa4>; + reg-names = "GPT32E"; + interrupts = <154 0>, + <155 0>, + <156 0>, + <157 0>, + <158 0>, + <159 0>, + <160 0>, + <161 0>, + <162 0>, + <163 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <2>; + status = "disabled"; + }; + + gpt32e3: gpt32e3@50048300 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x50048300 0xa4>; + reg-names = "GPT32E"; + interrupts = <167 0>, + <168 0>, + <169 0>, + <170 0>, + <171 0>, + <172 0>, + <173 0>, + <174 0>, + <175 0>, + <176 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <3>; + status = "disabled"; + }; + + gpt32e4: gpt32e4@50048400 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x50048400 0xa4>; + reg-names = "GPT32E"; + interrupts = <180 0>, + <181 0>, + <182 0>, + <183 0>, + <184 0>, + <185 0>, + <186 0>, + <187 0>, + <188 0>, + <189 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <4>; + status = "disabled"; + }; + + gpt32e5: gpt32e5@50048500 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x50048500 0xa4>; + reg-names = "GPT32E"; + interrupts = <193 0>, + <194 0>, + <195 0>, + <196 0>, + <197 0>, + <198 0>, + <199 0>, + <200 0>, + <201 0>, + <202 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <5>; + status = "disabled"; + }; + + gpt32e6: gpt32e6@50048600 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x50048600 0xa4>; + reg-names = "GPT32E"; + interrupts = <206 0>, + <207 0>, + <208 0>, + <209 0>, + <210 0>, + <211 0>, + <212 0>, + <213 0>, + <214 0>, + <215 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <6>; + status = "disabled"; + }; + + gpt32e7: gpt32e7@50048700 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x50048700 0xa4>; + reg-names = "GPT32E"; + interrupts = <219 0>, + <220 0>, + <221 0>, + <222 0>, + <223 0>, + <224 0>, + <225 0>, + <226 0>, + <227 0>, + <228 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <7>; + status = "disabled"; + }; + + gpt32e0_s: gpt32e0@40048000 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x40048000 0xa4>; + reg-names = "GPT32E"; + interrupts = <128 0>, + <129 0>, + <130 0>, + <131 0>, + <132 0>, + <133 0>, + <134 0>, + <135 0>, + <136 0>, + <137 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <0>; + status = "disabled"; + }; + + gpt32e1_s: gpt32e1@40048100 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x40048100 0xa4>; + reg-names = "GPT32E"; + interrupts = <141 0>, + <142 0>, + <143 0>, + <144 0>, + <145 0>, + <146 0>, + <147 0>, + <148 0>, + <149 0>, + <150 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <1>; + status = "disabled"; + }; + + gpt32e2_s: gpt32e2@40048200 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x40048200 0xa4>; + reg-names = "GPT32E"; + interrupts = <154 0>, + <155 0>, + <156 0>, + <157 0>, + <158 0>, + <159 0>, + <160 0>, + <161 0>, + <162 0>, + <163 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <2>; + status = "disabled"; + }; + + gpt32e3_s: gpt32e3@40048300 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x40048300 0xa4>; + reg-names = "GPT32E"; + interrupts = <167 0>, + <168 0>, + <169 0>, + <170 0>, + <171 0>, + <172 0>, + <173 0>, + <174 0>, + <175 0>, + <176 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <3>; + status = "disabled"; + }; + + gpt32e4_s: gpt32e4@40048400 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x40048400 0xa4>; + reg-names = "GPT32E"; + interrupts = <180 0>, + <181 0>, + <182 0>, + <183 0>, + <184 0>, + <185 0>, + <186 0>, + <187 0>, + <188 0>, + <189 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <4>; + status = "disabled"; + }; + + gpt32e5_s: gpt32e5@40048500 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x40048500 0xa4>; + reg-names = "GPT32E"; + interrupts = <193 0>, + <194 0>, + <195 0>, + <196 0>, + <197 0>, + <198 0>, + <199 0>, + <200 0>, + <201 0>, + <202 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <5>; + status = "disabled"; + }; + + gpt32e6_s: gpt32e6@40048600 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x40048600 0xa4>; + reg-names = "GPT32E"; + interrupts = <206 0>, + <207 0>, + <208 0>, + <209 0>, + <210 0>, + <211 0>, + <212 0>, + <213 0>, + <214 0>, + <215 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <6>; + status = "disabled"; + }; + + gpt32e7_s: gpt32e7@40048700 { + compatible = "renesas,rzg3s-pwm"; + reg = <0x40048700 0xa4>; + reg-names = "GPT32E"; + interrupts = <219 0>, + <220 0>, + <221 0>, + <222 0>, + <223 0>, + <224 0>, + <225 0>, + <226 0>, + <227 0>, + <228 0>; + interrupt-names = "ccmpa", "ccmpb", "cmpc", "cmpd", "cmpe", "cmpf", + "adtrga", "adtrgb", "ovf", "unf"; + clocks = <&cpg CPG_MOD R9A08G045_GPT_PCLK>, + <&cpg CPG_CORE R9A08G045_CLK_P0>; + resets = <&cpg_rctl R9A08G045_GPT_RST_C>; + #pwm-cells = <3>; + channel-id = <7>; + status = "disabled"; + }; + + poega: poega@40048800 { + compatible = "renesas,rzg3s-poeg"; + reg = <0x40048800 0x4>; + interrupts = <236 0>; + clocks = <&cpg CPG_MOD R9A08G045_POEG_A_CLKP>; + resets = <&cpg_rctl R9A08G045_POEG_A_RST>; + status = "disabled"; + }; + + poegb: poegb@40048c00 { + compatible = "renesas,rzg3s-poeg"; + reg = <0x40048c00 0x4>; + interrupts = <237 0>; + clocks = <&cpg CPG_MOD R9A08G045_POEG_B_CLKP>; + resets = <&cpg_rctl R9A08G045_POEG_B_RST>; + status = "disabled"; + }; + + poegc: poegc@40049000 { + compatible = "renesas,rzg3s-poeg"; + reg = <0x40049000 0x4>; + interrupts = <238 0>; + clocks = <&cpg CPG_MOD R9A08G045_POEG_C_CLKP>; + resets = <&cpg_rctl R9A08G045_POEG_C_RST>; + status = "disabled"; + }; + + poegd: poegc@40049400 { + compatible = "renesas,rzg3s-poeg"; + reg = <0x40049400 0x4>; + interrupts = <239 0>; + clocks = <&cpg CPG_MOD R9A08G045_POEG_D_CLKP>; + resets = <&cpg_rctl R9A08G045_POEG_D_RST>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <7>; +}; diff --git a/dts/bindings/adc/renesas,rzg3s-adc.yaml b/dts/bindings/adc/renesas,rzg3s-adc.yaml new file mode 100644 index 00000000000000..23981dfe48853e --- /dev/null +++ b/dts/bindings/adc/renesas,rzg3s-adc.yaml @@ -0,0 +1,47 @@ +# Copyright (c) 2024, EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +description: | + Renesas RZ/G3S ADC controller + + "input" cell in io-channel-cells indicate the ADC input channel index. + RZ/G3S has 8 analog inputs (ADC_CH0 to ADC_CH7) and one Thermal Sensor Unit (TSU). + Accordingly, input can be from 0 to 8. For example io-channels for 0, 1 and 8 channel: + + / { + zephyr,user { + io-channels = <&adc 0>, <&adc 1>, <&adc 8>; + }; + }; + +compatible: "renesas,rzg3s-adc" + +include: [adc-controller.yaml, pinctrl-device.yaml, reset-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + clocks: + required: true + + resets: + required: true + + vref-mv: + type: int + default: 1800 + description: | + Indicate the reference voltage of the ADC in mV. + RZ/G3S has one voltage reference (ADC_AVDD18 pin). + And it is usually connected to VDD. + In such case, set this property to the VDD (in mV) value. + + "#io-channel-cells": + const: 1 + +io-channel-cells: + - input diff --git a/dts/bindings/can/renesas,rzg3s-canfd.yaml b/dts/bindings/can/renesas,rzg3s-canfd.yaml new file mode 100644 index 00000000000000..96aff3424a9621 --- /dev/null +++ b/dts/bindings/can/renesas,rzg3s-canfd.yaml @@ -0,0 +1,65 @@ +description: | + Renesas RZ G3S CAN-FD controller bindings. The RZ G3S is 2-channel CAN-FD module (CAN-FD) that + complies with ISO 11898-1 (2015) Standards. It transmits and receives both formats of messages: + the standard identifier (11 bits) and extended ID (29 bits). + - number of receive rules (0 to 128) for each channel + - transmit buffers up to 32 per channel; + - receive buffers 128 total, up to 64 buffers per channel; + - Transmitter Delay Compensation; + - RX/TX message timestamping. + +compatible: "renesas,rzg3s-canfd" + +include: [base.yaml, pinctrl-device.yaml, reset-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + clocks: + required: true + + clock-names: + required: true + + resets: + required: true + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +child-binding: + description: | + CAN-FD controller channels + + include: + - name: can-fd-controller.yaml + property-blocklist: + - compatible + + properties: + reg: + required: true + + sample-point: + required: true + + sample-point-data: + required: true + + renesas,tx-delay-comp-offset-only: + description: | + The only provided "tx-delay-comp-offset" is used if "tx-delay-comp-offset-only" is provided. + RZ G3S CAN-FD controller supports Transmitter Delay Compensation (TDC) and, by default, the + TDC is applied as "tx-delay-comp-offset" + CFDCnFDSTS.TDCR. + Where + - "tx-delay-comp-offset" is provided by user in CAN channel DLL clock cycles and + stored in CFDCnFDCFG.TDCO (TDCO + 1 value is applied). + - CFDCnFDSTS.TDCR is the measured Transceiver Delay Compensation Result + type: boolean diff --git a/dts/bindings/clock/renesas,r9a08g045-cpg-mssr.yaml b/dts/bindings/clock/renesas,r9a08g045-cpg-mssr.yaml new file mode 100644 index 00000000000000..0eaead17d6fb9f --- /dev/null +++ b/dts/bindings/clock/renesas,r9a08g045-cpg-mssr.yaml @@ -0,0 +1,14 @@ +# Copyright (c) 2023 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +description: | + Renesas RZ/G3S R9A08G045 SoC Clock Pulse Generator/Module Standby and + Software Reset controller + +compatible: "renesas,r9a08g045-cpg-mssr" + +include: [base.yaml, "renesas,rcar-cpg-mssr.yaml"] + +properties: + clocks: + required: true diff --git a/dts/bindings/counter/renesas,ostm-counter.yaml b/dts/bindings/counter/renesas,ostm-counter.yaml new file mode 100644 index 00000000000000..10d65ca7962dba --- /dev/null +++ b/dts/bindings/counter/renesas,ostm-counter.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 +description: Renesas OS timer Counter + +compatible: "renesas,ostm" + +include: [base.yaml, reset-device.yaml] + +properties: + reg: + required: true + + clocks: + required: true + + interrupts: + required: true diff --git a/dts/bindings/counter/renesas,ostm-rzg3s-counter.yaml b/dts/bindings/counter/renesas,ostm-rzg3s-counter.yaml new file mode 100644 index 00000000000000..12fa00d14b0651 --- /dev/null +++ b/dts/bindings/counter/renesas,ostm-rzg3s-counter.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 +description: Renesas OS timer Counter + +compatible: "renesas,ostm-r9a08g045" + +include: ["renesas,ostm-counter.yaml", reset-device.yaml] + +properties: + resets: + required: true diff --git a/dts/bindings/dma/renesas,rzg3-dma.yaml b/dts/bindings/dma/renesas,rzg3-dma.yaml new file mode 100644 index 00000000000000..f5243f83380103 --- /dev/null +++ b/dts/bindings/dma/renesas,rzg3-dma.yaml @@ -0,0 +1,32 @@ +# Copyright (c) 2024, EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +description: | + RZG3 DMA controller + + channel: Select channel for data transmitting + + slot: Select peripheral to connect DMA. Slots defined in rza2_dma.h header. + + config: A 32bit mask specifying the DMA channel configuration + + Example of device-tree configuration + + &ssi0 { + status = "okay"; + + dmas = <&dma0 0 DMA_RS_SSIF_DMA_RX0 0>, <&dma0 5 DMA_RS_SSIF_DMA_TX0 0>; + dma-names = "rx", "tx"; + }; + +include: ["renesas,rza2-dma.yaml", base.yaml, reset-device.yaml] + +compatible: "renesas,rzg3-dma" + +properties: + + resets: + required: true + + clocks: + required: true diff --git a/dts/bindings/gpio/renesas,rzg3s-gpio.yaml b/dts/bindings/gpio/renesas,rzg3s-gpio.yaml new file mode 100644 index 00000000000000..5d6683351d8bc4 --- /dev/null +++ b/dts/bindings/gpio/renesas,rzg3s-gpio.yaml @@ -0,0 +1,52 @@ +# Copyright (c) 2024 Epam Systems +# SPDX-License-Identifier: Apache-2.0 + +description: | + Reneses RZ G3S R9A08G045 GPIO controller node. + It has to be a subnode of the Renesas RZ G3S R9A08G045 SoC pin-controller node + ("renesas,r9a08g045-pinctrl"). + +compatible: "renesas,r9a08g045-gpio" + +include: base.yaml + +properties: + reg: + required: true + description: | + GPIO amd TINT I/O regions + + reg-names: + required: true + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +child-binding: + description: | + This bindings describe the RZ G3S GPIO port configuration + + include: + - name: base.yaml + property-allowlist: + - status + - reg + - label + - name: gpio-controller.yaml + + properties: + reg: + required: true + description: | + GPIO port number. RZ G3S board has a number of GPIO ports that + are used to identify correct pin number. + + "#gpio-cells": + const: 2 + + gpio-cells: + - pin + - flags diff --git a/dts/bindings/i2c/renesas,rzg-riic.yaml b/dts/bindings/i2c/renesas,rzg-riic.yaml new file mode 100644 index 00000000000000..a0cfb616ae5328 --- /dev/null +++ b/dts/bindings/i2c/renesas,rzg-riic.yaml @@ -0,0 +1,48 @@ +# Copyright (c) 2021, IoT.bzh +# Copyright (c) 2024, EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RZ/G3S I2C controller + +compatible: "renesas,rzg-riic" + +include: [i2c-controller.yaml, pinctrl-device.yaml, reset-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + clocks: + required: true + + scl-rising-time-ns: + type: int + default: 0 + description: | + Number of nanoseconds the SCL signal takes to rise; t(r) in the I2C specification. + + scl-falling-time-ns: + type: int + default: 0 + description: | + Number of nanoseconds the SCL signal takes to fall; t(f) in the I2C specification. + + dmas: + description: | + Optional TX & RX dma specifiers. Mandatory if defined CONFIG_I2C_RIIC_DMA_DRIVEN + Each specifier will have a phandle reference to the dmac controller, + the channel number, slot and config. Use same channel for TX and RX. + + For example dmas for TX, RX on I2C3: + dmas = <&dma0 2 DMA_RS_INTRIIC_TI3 0>, <&dma0 2 DMA_RS_INTRIIC_RI3 0>; + + dma-names: + description: | + Required if the dmas property exists. This should be "tx" and "rx" + to match the dmas property. + + For example: + dma-names = "tx", "rx"; diff --git a/dts/bindings/interrupt-controller/renesas,r9a08g045-intc.yaml b/dts/bindings/interrupt-controller/renesas,r9a08g045-intc.yaml new file mode 100644 index 00000000000000..46ea058e0d7639 --- /dev/null +++ b/dts/bindings/interrupt-controller/renesas,r9a08g045-intc.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas r9a08g045 INTC interrupt controller + +compatible: "renesas,r9a08g045-intc" + +include: + - name: renesas,r7s9210-intc.yaml + property-blocklist: + - nmi-edge diff --git a/dts/bindings/mhu/renesas,mhu.yaml b/dts/bindings/mhu/renesas,mhu.yaml new file mode 100644 index 00000000000000..b9008388b811cb --- /dev/null +++ b/dts/bindings/mhu/renesas,mhu.yaml @@ -0,0 +1,35 @@ +# Copyright (c) 2024, EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas MHU (Message Handling Unit) + +compatible: "renesas,mhu" + +include: [base.yaml, reset-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + renesas,mhu-type: + type: int + required: true + enum: [0, 1] + description: | + Set the role of the MHU controller. + Possible values are 0 for MHU_SEND and 1 for MHU_RSP. + When 0 is set then MHU controller works as transmitter + to send messages and receive responses. + When 1 is set then MHU conroller works as responder + expecting notifiers from the master device and getting + responces. + + memory-region: + type: phandle + description: | + Reference to the shared memory region that is going + to be used for the buffer communication between + MHU units. No data will be transmitted if not set. diff --git a/dts/bindings/pinctrl/renesas,rzg3s-pinctrl.yaml b/dts/bindings/pinctrl/renesas,rzg3s-pinctrl.yaml new file mode 100644 index 00000000000000..a55b8424a11d55 --- /dev/null +++ b/dts/bindings/pinctrl/renesas,rzg3s-pinctrl.yaml @@ -0,0 +1,164 @@ +# Copyright (c) 2024 Epam Systems +# SPDX-License-Identifier: Apache-2.0 + +description: | + Renesas RZ G3S r9a08g045 SoC series has combined Pin Function and GPIO Controller module. + This DT bindings represent Pin multiplexing and configuration HW definition. + The RZ G3S pin controller performs HW pin configurations on: + - a GPIO per-pin basis for configuration of: + -- pin functions (GPIO or Peripheral Function) + -- pin pull-up/down + -- pin driving ability + -- input GPIO pin Interrupt Enable + -- input GPIO pin Digital Noise Filter + - a Special Purpose per-pin basis for configuration of: + -- pin driving ability + -- input pin Digital Noise Filter + -- input enable + -- output-enable + - a Special Purpose Pin Groups for configuration of: + -- power source + -- high impedance state + -- low power mode + + The GPIO pins are grouped in Ports with up to 8 pins per ports, each of them configurable as + GPIO or Peripheral Function mode. Up to 8 different alternate function modes exist for + each single GPIO pin. + + The RZ G3S pin controller supports pin groups, like "ETH0", "ETH1", "XSPI", etc., + for which the Power source, Standby mode and high impedance state can be configured + and such settings affects on all pins in group. + + The RZ G3S pin controller supports configurable Special Purpose pins like + "TDO", "TMS_SWDIO", "AUDIO_CLK1", ... + + See "Renesas Microprocessor RZ Family / RZ/G Series User’s Manual: Hardware" + "General Purpose Input Output Port (GPIO)" section for more information. + + Below generic example shows of supported pinctrl definitions: + + #include + example_pins: devx_pins { + devx-pinmux { + pinmux = , + ; + bias-pull-pin-default; + drive-strength-microamp = ; + }; + + devx-grp { + groups = "XSPI"; + power-source = <1800>; + }; + + devx-spins { + pins = "NMI", "AUDIO_CLK1", "TMS_SWDIO"; + input-enable; + drive-strength-microamp = ; + }; + }; + + pinmux, groups and pins nodes are combined to form the full list of pins settings to select. + +compatible: renesas,r9a08g045-pinctrl + +include: base.yaml +properties: + reg: + required: true + + reg-names: + required: true + +child-binding: + description: | + This RZ G3S pins mux/cfg nodes description. + + child-binding: + description: | + The RZ G3S pinmux/pincfg/groups configuration nodes description. + + include: + - name: pincfg-node.yaml + property-allowlist: + - bias-disable + - bias-high-impedance + - bias-pull-down + - bias-pull-up + - bias-pull-pin-default + - drive-strength-microamp + - input-enable + - input-disable + - output-enable + - power-source + - low-power-enable + - low-power-disable + - input-debounce + + properties: + pinmux: + type: array + description: | + Pinmux configuration node. + Values are constructed from GPIO port number, pin number, and + alternate function configuration number using the RZG3S_PINMUX() + helper macro in pinctrl-r9a08g045.h + + groups: + type: string + enum: + - ETH0 + - ETH1 + - SD_CH0 + - SD_CH1 + - XSPI + - I3C + description: | + Pins group configuration node. + Specify pin groups name to select for this pin group configuration node. + (See ETHx_POC, SD_CHx_POC, XSPI_POC, I3C_SET and XSPI/OCTA Hi-Z registers + in Hardware User’s Manual) + + pins: + type: string-array + description: | + Special Purpose pins configuration node. + Specify list of Special Purpose pin names to select for this configuration node. + + Allowed values: + [ "NMI", "TMS_SWDIO", "TDO", "XSPI_SPCLK", "XSPI_RESET", "XSPI_WP", "XSPI_DS", "XSPI_CS0", + "XSPI_CS1", "XSPI_IO0", "XSPI_IO1", "XSPI_IO2", "XSPI_IO3", "XSPI_IO4", "XSPI_IO5", + "XSPI_IO6", "XSPI_IO7", "WDTOVF_PERROUT", "SD0_CLK", "SD0_CMD", "SD0_RST", + "SD0_DATA0", "SD0_DATA1", "SD0_DATA2", "SD0_DATA3", "SD0_DATA4", "SD0_DATA5", + "SD0_DATA6", "SD0_DATA7", "SD1_CLK", "SD1_CMD", "SD1_DATA0", "SD1_DATA1", "SD1_DATA2", + "SD1_DATA3", "AUDIO_CLK1", "AUDIO_CLK2", "I3C_SDA", "I3C_SCL", "SD2_CMD", "SD2_DATA0", + "SD2_DATA1", "SD2_DATA2", "SD2_DATA3", "ET0_TXC_TX_CLK", "ET1_TXC_TX_CLK", + "ET0_TX_CTL_TX_EN","ET1_TX_CTL_TX_EN" ] + + power-source: + type: int + description: select between different power supplies in mV + enum: + - 1200 + - 1800 + - 2500 + - 3300 + + drive-strength-microamp: + type: int + description: | + maximum sink or source current in μA for pin which shell be defined + using PINCTRL_RZG3S_IOLH_* helper macro in pinctrl-r9a08g045.h depending on pin group and + selected power supply. + + input-debounce: + type: int + description: | + Digital Noise Filter configuration for a pin which shell be defined + using PINCTRL_RZG3S_FILTER_SET() helper macro in pinctrl-r9a08g045.h to specify + FILNUM_m and FILCLKSEL_m. With 24Mhz external clock: + - min debounce time will be 166.666ns for FILNUM_m=0 and FILCLKSEL_m=0 + - max debounce time will be 24ms for FILNUM_m=3 and FILCLKSEL_m=3. + This property intentionally redefined to avoid unnecessary conversation from usec to + FILNUM_m and FILCLKSEL_m values depending on external clock value as this configuration + is static. diff --git a/dts/bindings/pwm/renesas,rzg3s-poeg.yaml b/dts/bindings/pwm/renesas,rzg3s-poeg.yaml new file mode 100644 index 00000000000000..d8b009af8d8ada --- /dev/null +++ b/dts/bindings/pwm/renesas,rzg3s-poeg.yaml @@ -0,0 +1,28 @@ +# Copyright (c) 2024, EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RZ G3S POEG driver for GPT + +compatible: "renesas,rzg3s-poeg" + +include: [base.yaml, pinctrl-device.yaml, reset-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + clocks: + required: true + + renesas,invert: + type: int + enum: + - 0 + - 1 + description: | + Sets output request level of the external source. When external + pin initial state is high then ivertion should be made to raise + output request on low state. diff --git a/dts/bindings/pwm/renesas,rzg3s-pwm.yaml b/dts/bindings/pwm/renesas,rzg3s-pwm.yaml new file mode 100644 index 00000000000000..3983185da6e0b5 --- /dev/null +++ b/dts/bindings/pwm/renesas,rzg3s-pwm.yaml @@ -0,0 +1,40 @@ +# Copyright (c) 2024, EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RZ G3S general purpose PWM timer channel + +compatible: "renesas,rzg3s-pwm" + +include: ["renesas,rza2m-pwm.yaml", reset-device.yaml] + +properties: + resets: + required: true + + renesas,poeg: + type: string + enum: + - "POEGA" + - "POEGB" + - "POEGC" + - "POEGD" + description: | + Associated POEG device name choice. Should be set if + `renesas,poeg-device` phandle was provided. + + renesas,disable-requests: + type: int + description: | + Sets the Output-disable requests from POEG. + Possible values are: + - PWM_HIGH to sends output-disable requests if both GTIOCA and + GTICB are in HIGH state + - PWM_LOW to sends output-disable requests if both GTIOCA and + GTICB are in LOW state + - PWM_DT to sends output-disable requests if deadtime error occurred. + + renesas,poeg-device: + type: phandle + description: | + Link to the POEG device which controls GPT channel + This phandle should be set if `renesas,poeg` property was provided. diff --git a/dts/bindings/reset/renesas,r9a08g045-cpg-reset.yaml b/dts/bindings/reset/renesas,r9a08g045-cpg-reset.yaml new file mode 100644 index 00000000000000..f85b67707278d3 --- /dev/null +++ b/dts/bindings/reset/renesas,r9a08g045-cpg-reset.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +description: | + Renesas RZ/G3S R9A08G045 SoC CPG Reset controller. + It has to be a subnode of the Renesas RZ/G3S R9A08G045 SoC CPG clock-controller node + ("renesas,r9a08g045-cpg-mssr"). + +compatible: "renesas,r9a08g045-cpg-reset" + +include: [reset-controller.yaml, base.yaml] + +properties: + "#reset-cells": + const: 1 + +reset-cells: + - id diff --git a/dts/bindings/serial/renesas,rzg3s-scif.yaml b/dts/bindings/serial/renesas,rzg3s-scif.yaml new file mode 100644 index 00000000000000..a62a569388909c --- /dev/null +++ b/dts/bindings/serial/renesas,rzg3s-scif.yaml @@ -0,0 +1,49 @@ +description: Renesas RZ/A2M UART + +compatible: "renesas,rzg3s-scif" + +include: [uart-controller.yaml, pinctrl-device.yaml, reset-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + clocks: + description: | + Clock source for calculating BRR value + + dmas: + description: | + Optional TX & RX dma specifiers. Mandatory if defined CONFIG_UART_ASYNC_API + Each specifier will have a phandle reference to the dmac controller, + the channel number, slot and config. + + For example dmas for TX, RX on scif3 + dmas = <&dma0 5 DMA_RS_TXI3 0>, <&dma0 6 DMA_RS_RXI3 0>; + + dma-names: + description: | + Required if the dmas property exists. This should be "tx" and "rx" + to match the dmas property. + + For example + dma-names = "tx", "rx"; + + usart-mode: + type: boolean + description: + Optional boolean parameter which turns on Clock Synchronous mode + + external-clock: + type: boolean + description: + This parameter actual only in Clock Synchronous mode. Use external + source as clock + + renesas,loopback: + type: boolean + description: + Enable test loopback mode diff --git a/dts/bindings/spi/renesas,rza2m-spi.yaml b/dts/bindings/spi/renesas,rspi-rz.yaml similarity index 90% rename from dts/bindings/spi/renesas,rza2m-spi.yaml rename to dts/bindings/spi/renesas,rspi-rz.yaml index 0d868be0d764f7..fd5f21d650407c 100644 --- a/dts/bindings/spi/renesas,rza2m-spi.yaml +++ b/dts/bindings/spi/renesas,rspi-rz.yaml @@ -1,11 +1,11 @@ # Copyright (c) 2023 EPAM Systems # SPDX-License-Identifier: Apache-2.0 -description: Renesas RZ/A2M SPI +description: Renesas RZ/A2M, RZ/G3S SPI compatible: "renesas,rspi-rz" -include: [spi-controller.yaml, pinctrl-device.yaml] +include: [spi-controller.yaml, pinctrl-device.yaml, reset-device.yaml] properties: reg: diff --git a/dts/bindings/timer/renesas,ostm-rzg3s.yaml b/dts/bindings/timer/renesas,ostm-rzg3s.yaml new file mode 100644 index 00000000000000..4f291c3d35871c --- /dev/null +++ b/dts/bindings/timer/renesas,ostm-rzg3s.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas OS timer + +compatible: "renesas,ostm-r9a08g045-timer" + +include: ["renesas,ostm.yaml", reset-device.yaml] + +properties: + resets: + required: true diff --git a/dts/bindings/timer/renesas,ostm.yaml b/dts/bindings/timer/renesas,ostm.yaml index 123694a9e32f30..24adf1cfd8c488 100644 --- a/dts/bindings/timer/renesas,ostm.yaml +++ b/dts/bindings/timer/renesas,ostm.yaml @@ -1,6 +1,9 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + description: Renesas OS timer -compatible: "renesas,ostm" +compatible: "renesas,ostm-timer" include: base.yaml diff --git a/dts/bindings/watchdog/renesas,rzg-wdt.yaml b/dts/bindings/watchdog/renesas,rzg-wdt.yaml new file mode 100644 index 00000000000000..c884b821c87172 --- /dev/null +++ b/dts/bindings/watchdog/renesas,rzg-wdt.yaml @@ -0,0 +1,32 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas RZ/G Watchdog + +compatible: "renesas,rzg-wdt" + +include: [base.yaml, reset-device.yaml] + +properties: + reg: + required: true + + clocks: + required: true + + timer-idx: + type: int + required: true + description: | + Index of watchdog timer channel index (1 or 2). + Watchdog channel 1 checking the operation of Cortex-M33 CPU + and channel 2 checking the operation of Cortex-M33 CPU + with FPU. Each channel should be provided with the + corresponding clocks and resets that are controlling + this channel. + enum: + - 1 + - 2 + + resets: + required: true diff --git a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld index 92b6f02d029e99..f921bee5c124c3 100644 --- a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld +++ b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld @@ -107,7 +107,11 @@ SECTIONS GROUP_START(ROMABLE_REGION) - __rom_region_start = ROM_ADDR; +#if defined(CONFIG_XIP) + __rom_region_start = ROM_ADDR; +#else + __rom_region_start = RAM_ADDR; +#endif SECTION_PROLOGUE(rom_start,,) { @@ -171,6 +175,7 @@ SECTIONS *(.ARM.exidx* gnu.linkonce.armexidx.*) #endif __exidx_end = .; + . = ALIGN(_region_min_align); } GROUP_LINK_IN(ROMABLE_REGION) __rodata_region_start = .; @@ -190,6 +195,7 @@ SECTIONS #include #include +#include /* * For XIP images, in order to avoid the situation when __data_rom_start @@ -202,9 +208,13 @@ SECTIONS * usually 4k aligned. */ . = ALIGN(4); - } GROUP_LINK_IN(ROMABLE_REGION) -#include + /* + * RODATA must be the last section so that the size of the entire read + * only area will be filled to a power of 2. + */ + MPU_ALIGN(ABSOLUTE(.) - __rom_region_start); + } GROUP_LINK_IN(ROMABLE_REGION) #if defined(CONFIG_BUILD_ALIGN_LMA) /* diff --git a/include/zephyr/arch/arm/mpu/arm_mpu_v8.h b/include/zephyr/arch/arm/mpu/arm_mpu_v8.h index cf60cca99da9ce..edc197c19aeac6 100644 --- a/include/zephyr/arch/arm/mpu/arm_mpu_v8.h +++ b/include/zephyr/arch/arm/mpu/arm_mpu_v8.h @@ -259,6 +259,42 @@ .attr = p_attr(p_base, p_size), \ } +#define REGION_RAM_ATTR_NO_EXEC(limit) \ + { \ + .rbar = NOT_EXEC | \ + P_RW_U_NA_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \ + /* Cache-ability */ \ + .mair_idx = MPU_MAIR_INDEX_SRAM, \ + .r_limit = (limit) - 1, /* Region Limit */ \ + } + +#define REGION_RAM_TEXT_ATTR(limit) \ + { \ + .rbar = P_RO_U_RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \ + /* Cache-ability */ \ + .mair_idx = MPU_MAIR_INDEX_SRAM, \ + .r_limit = (limit) - 1, /* Region Limit */ \ + } + +#define REGION_RAM_RO_ATTR(limit) \ + { \ + .rbar = NOT_EXEC | \ + P_RO_U_RO_Msk | NON_SHAREABLE_Msk, /* AP, XN, SH */ \ + /* Cache-ability */ \ + .mair_idx = MPU_MAIR_INDEX_SRAM, \ + .r_limit = (limit) - 1, /* Region Limit */ \ + } + +#define REGION_DEVICE_ATTR(limit) \ + { \ + /* AP, XN, SH */ \ + .rbar = NOT_EXEC | P_RW_U_NA_Msk | NON_SHAREABLE_Msk, \ + /* Cache-ability */ \ + .mair_idx = MPU_MAIR_INDEX_SRAM_NOCACHE, \ + /* Region Limit */ \ + .r_limit = (limit) - 1, \ + } + /* On Cortex-M, we can only set the XN bit when CONFIG_XIP=y. When * CONFIG_XIP=n, the entire image will be linked to SRAM, so we need to keep * the SRAM region XN bit clear or the application code will not be executable. diff --git a/include/zephyr/drivers/interrupt_controller/gic.h b/include/zephyr/drivers/interrupt_controller/gic.h index f8d10ff85070f0..eb895bd4fa0e84 100644 --- a/include/zephyr/drivers/interrupt_controller/gic.h +++ b/include/zephyr/drivers/interrupt_controller/gic.h @@ -309,6 +309,13 @@ bool arm_gic_irq_is_pending(unsigned int irq); */ void arm_gic_irq_clear_pending(unsigned int irq); +/** + * @brief Set the pending irq + * + * @param irq interrupt ID + */ +void arm_gic_irq_set_pending(unsigned int irq); + /** * @brief Set interrupt priority * diff --git a/include/zephyr/drivers/poeg.h b/include/zephyr/drivers/poeg.h new file mode 100644 index 00000000000000..d239682f50556b --- /dev/null +++ b/include/zephyr/drivers/poeg.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2024, EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public Port Output Enable for GPT (POEG) Driver APIs + */ + +#ifndef _ZEPHYR_INCLUDE_DRIVERS_POEG_H_ +#define _ZEPHYR_INCLUDE_DRIVERS_POEG_H_ + +typedef void (*poeg_callback_t)(void *args); + +/** + * @brief POEG reset callback handler function signature + * + * @note The callback handler may be called in interrupt context. + * + * @note Resets POEG flags to enable output for PWM driver + * + * @param[in] dev POEG device instance. + */ +typedef void (*poeg_reset_t)(const struct device *dev); + +/** + * @brief POEG callback handler function signature + * + * @note Sets callback to call when on Output disable request + * + * @param[in] dev POEG device instance. + * @param[in] cb pointer to the callback function. + * @param[in] args pointer to the callback argument structure. + */ +typedef void (*poeg_cb_set_t)(const struct device *dev, poeg_callback_t cb, void *args); + +/** + * @brief POEG status handler function signature + * + * @note Returns current POEG status flags + * + * @param[out] driver specific POEG status flags. + */ +typedef uint32_t (*poeg_status_t)(const struct device *dev); + +/** @brief POEG driver API definition. */ +__subsystem struct poeg_driver_api { + poeg_reset_t reset; + poeg_cb_set_t cb_set; + poeg_status_t status; +}; + +/** + * @brief Reset POEG status flags + * + * Resets POEG disable flags to enable PWM output. + * This should be called after processing disable request to + * clear POEG status + * + * @param[in] dev POEG device instance. + */ +__syscall void poeg_reset(const struct device *dev); + +static inline void z_impl_poeg_reset(const struct device *dev) +{ + const struct poeg_driver_api *api = (const struct poeg_driver_api *)dev->api; + + if (!api || !api->reset) { + return; + } + + api->reset(dev); +} +/** + * @brief Set callback to the POEG on disable request + * + * Sets the callback on the POEG device to be called on + * disable request from external pin or from PWM + * + * @param[in] dev POEG device instance. + * @param[in] cb pointer to the callback function. + * @param[in] args pointer to the callback argument structure. + */ +__syscall void poeg_cb_set(const struct device *dev, poeg_callback_t cb, void *args); + +static inline void z_impl_poeg_cb_set(const struct device *dev, void (*cb)(void *), void *args) +{ + const struct poeg_driver_api *api = (const struct poeg_driver_api *)dev->api; + + if (!api || !api->cb_set) { + return; + } + + api->cb_set(dev, cb, args); +} + +/** + * @brief POEG status + * + * @note Returns current POEG status flags + * + * @param[out] driver specific POEG status flags. + */ +__syscall uint32_t poeg_status(const struct device *dev); + +static inline uint32_t z_impl_poeg_status(const struct device *dev) +{ + const struct poeg_driver_api *api = (const struct poeg_driver_api *)dev->api; + + if (!api || !api->status) { + return -ENOSYS; + } + + return api->status(dev); +} + +/** + * @} + */ + +#include + +#endif /* _ZEPHYR_INCLUDE_DRIVERS_POEG_H_ */ diff --git a/include/zephyr/dt-bindings/clock/r9a08g045_cpg_mssr.h b/include/zephyr/dt-bindings/clock/r9a08g045_cpg_mssr.h new file mode 100644 index 00000000000000..c53fb0809fd214 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/r9a08g045_cpg_mssr.h @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_RENESAS_CLOCK_R9A07G054_CPG_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_RENESAS_CLOCK_R9A07G054_CPG_H_ + +#include "renesas_cpg_mssr.h" + +/* R9A08G045 CPG Core Clocks */ +#define R9A08G045_CLK_I 0 +#define R9A08G045_CLK_I2 1 +#define R9A08G045_CLK_I3 2 +#define R9A08G045_CLK_S0 3 +#define R9A08G045_CLK_SPI0 4 +#define R9A08G045_CLK_SPI1 5 +#define R9A08G045_CLK_SD0 6 +#define R9A08G045_CLK_SD1 7 +#define R9A08G045_CLK_SD2 8 +#define R9A08G045_CLK_M0 9 +#define R9A08G045_CLK_HP 10 +#define R9A08G045_CLK_TSU 11 +#define R9A08G045_CLK_ZT 12 +#define R9A08G045_CLK_P0 13 +#define R9A08G045_CLK_P1 14 +#define R9A08G045_CLK_P2 15 +#define R9A08G045_CLK_P3 16 +#define R9A08G045_CLK_P4 17 +#define R9A08G045_CLK_P5 18 +#define R9A08G045_CLK_AT 19 +#define R9A08G045_CLK_OC0 20 +#define R9A08G045_CLK_OC1 21 +#define R9A08G045_OSCCLK 22 +#define R9A08G045_OSCCLK2 23 + +/* R9A08G045 Module Clocks */ +#define R9A08G045_CA55_SCLK 0 +#define R9A08G045_CA55_PCLK 1 +#define R9A08G045_CA55_ATCLK 2 +#define R9A08G045_CA55_GICCLK 3 +#define R9A08G045_CA55_PERICLK 4 +#define R9A08G045_CA55_ACLK 5 +#define R9A08G045_CA55_TSCLK 6 +#define R9A08G045_GIC600_GICCLK 7 +#define R9A08G045_IA55_CLK 8 +#define R9A08G045_IA55_PCLK 9 +#define R9A08G045_MHU_PCLK 10 +#define R9A08G045_SYC_CNT_CLK 11 +#define R9A08G045_DMAC_ACLK 12 +#define R9A08G045_DMAC_PCLK 13 +#define R9A08G045_OSTM0_PCLK 14 +#define R9A08G045_OSTM1_PCLK 15 +#define R9A08G045_OSTM2_PCLK 16 +#define R9A08G045_OSTM3_PCLK 17 +#define R9A08G045_OSTM4_PCLK 18 +#define R9A08G045_OSTM5_PCLK 19 +#define R9A08G045_OSTM6_PCLK 20 +#define R9A08G045_OSTM7_PCLK 21 +#define R9A08G045_MTU_X_MCK_MTU3 22 +#define R9A08G045_POE3_CLKM_POE 23 +#define R9A08G045_GPT_PCLK 24 +#define R9A08G045_POEG_A_CLKP 25 +#define R9A08G045_POEG_B_CLKP 26 +#define R9A08G045_POEG_C_CLKP 27 +#define R9A08G045_POEG_D_CLKP 28 +#define R9A08G045_WDT0_PCLK 29 +#define R9A08G045_WDT0_CLK 30 +#define R9A08G045_WDT1_PCLK 31 +#define R9A08G045_WDT1_CLK 32 +#define R9A08G045_WDT2_PCLK 33 +#define R9A08G045_WDT2_CLK 34 +#define R9A08G045_SPI_HCLK 35 +#define R9A08G045_SPI_ACLK 36 +#define R9A08G045_SPI_CLK 37 +#define R9A08G045_SPI_CLKX2 38 +#define R9A08G045_SDHI0_IMCLK 39 +#define R9A08G045_SDHI0_IMCLK2 40 +#define R9A08G045_SDHI0_CLK_HS 41 +#define R9A08G045_SDHI0_ACLK 42 +#define R9A08G045_SDHI1_IMCLK 43 +#define R9A08G045_SDHI1_IMCLK2 44 +#define R9A08G045_SDHI1_CLK_HS 45 +#define R9A08G045_SDHI1_ACLK 46 +#define R9A08G045_SDHI2_IMCLK 47 +#define R9A08G045_SDHI2_IMCLK2 48 +#define R9A08G045_SDHI2_CLK_HS 49 +#define R9A08G045_SDHI2_ACLK 50 +#define R9A08G045_SSI0_PCLK2 51 +#define R9A08G045_SSI0_PCLK_SFR 52 +#define R9A08G045_SSI1_PCLK2 53 +#define R9A08G045_SSI1_PCLK_SFR 54 +#define R9A08G045_SSI2_PCLK2 55 +#define R9A08G045_SSI2_PCLK_SFR 56 +#define R9A08G045_SSI3_PCLK2 57 +#define R9A08G045_SSI3_PCLK_SFR 58 +#define R9A08G045_SRC_CLKP 59 +#define R9A08G045_USB_U2H0_HCLK 60 +#define R9A08G045_USB_U2H1_HCLK 61 +#define R9A08G045_USB_U2P_EXR_CPUCLK 62 +#define R9A08G045_USB_PCLK 63 +#define R9A08G045_USB_SCLK 64 +#define R9A08G045_ETH0_CLK_AXI 65 +#define R9A08G045_ETH0_CLK_CHI 66 +#define R9A08G045_ETH0_REFCLK 67 +#define R9A08G045_ETH1_CLK_AXI 68 +#define R9A08G045_ETH1_CLK_CHI 69 +#define R9A08G045_ETH1_REFCLK 70 +#define R9A08G045_I2C0_PCLK 71 +#define R9A08G045_I2C1_PCLK 72 +#define R9A08G045_I2C2_PCLK 73 +#define R9A08G045_I2C3_PCLK 74 +#define R9A08G045_SCIF0_CLK_PCK 75 +#define R9A08G045_SCIF1_CLK_PCK 76 +#define R9A08G045_SCIF2_CLK_PCK 77 +#define R9A08G045_SCIF3_CLK_PCK 78 +#define R9A08G045_SCIF4_CLK_PCK 79 +#define R9A08G045_SCIF5_CLK_PCK 80 +#define R9A08G045_SCI0_CLKP 81 +#define R9A08G045_SCI1_CLKP 82 +#define R9A08G045_IRDA_CLKP 83 +#define R9A08G045_RSPI0_CLKB 84 +#define R9A08G045_RSPI1_CLKB 85 +#define R9A08G045_RSPI2_CLKB 86 +#define R9A08G045_RSPI3_CLKB 87 +#define R9A08G045_RSPI4_CLKB 88 +#define R9A08G045_CANFD_PCLK 89 +#define R9A08G045_CANFD_CLK_RAM 90 +#define R9A08G045_GPIO_HCLK 91 +#define R9A08G045_ADC_ADCLK 92 +#define R9A08G045_ADC_PCLK 93 +#define R9A08G045_TSU_PCLK 94 +#define R9A08G045_OCTA_ACLK 95 +#define R9A08G045_OCTA_MCLK 96 +#define R9A08G045_PDM_PCLK 97 +#define R9A08G045_PDM_CCLK 98 +#define R9A08G045_PCI_CLKL1PM 99 +#define R9A08G045_PCI_ACLK 100 +#define R9A08G045_SPDIF_PCLK 101 +#define R9A08G045_I3C_PCLK 102 +#define R9A08G045_I3C_TCLK 103 +#define R9A08G045_VBAT_BCLK 104 +#define R9A08G045_LAST_CLK (R9A08G045_VBAT_BCLK + 1) + +/* R9A08G045 Resets */ +#define R9A08G045_CA55_RST_1_0 0 +#define R9A08G045_CA55_RST_3_0 1 +#define R9A08G045_CA55_RST_4 2 +#define R9A08G045_CA55_RST_5 3 +#define R9A08G045_CA55_RST_6 4 +#define R9A08G045_CA55_RST_7 5 +#define R9A08G045_CA55_RST_8 6 +#define R9A08G045_CA55_RST_9 7 +#define R9A08G045_CA55_RST_10 8 +#define R9A08G045_CA55_RST_11 9 +#define R9A08G045_CA55_RST_12 10 +#define R9A08G045_GIC600_GICRESET_N 11 +#define R9A08G045_GIC600_DBG_GICRESET_N 12 +#define R9A08G045_IA55_RESETN 13 +#define R9A08G045_MHU_RESETN 14 +#define R9A08G045_DMAC_ARESETN 15 +#define R9A08G045_DMAC_RST_ASYNC 16 +#define R9A08G045_SYC_RESETN 17 +#define R9A08G045_OSTM0_PRESETZ 18 +#define R9A08G045_OSTM1_PRESETZ 19 +#define R9A08G045_OSTM2_PRESETZ 20 +#define R9A08G045_OSTM3_PRESETZ 21 +#define R9A08G045_OSTM4_PRESETZ 22 +#define R9A08G045_OSTM5_PRESETZ 23 +#define R9A08G045_OSTM6_PRESETZ 24 +#define R9A08G045_OSTM7_PRESETZ 25 +#define R9A08G045_MTU_X_PRESET_MTU3 26 +#define R9A08G045_POE3_RST_M_REG 27 +#define R9A08G045_GPT_RST_C 28 +#define R9A08G045_POEG_A_RST 29 +#define R9A08G045_POEG_B_RST 30 +#define R9A08G045_POEG_C_RST 31 +#define R9A08G045_POEG_D_RST 32 +#define R9A08G045_WDT0_PRESETN 33 +#define R9A08G045_WDT1_PRESETN 34 +#define R9A08G045_WDT2_PRESETN 35 +#define R9A08G045_SPI_HRESETN 36 +#define R9A08G045_SPI_ARESETN 37 +#define R9A08G045_SDHI0_IXRST 38 +#define R9A08G045_SDHI1_IXRST 39 +#define R9A08G045_SDHI2_IXRST 40 +#define R9A08G045_SSI0_RST_M2_REG 41 +#define R9A08G045_SSI1_RST_M2_REG 42 +#define R9A08G045_SSI2_RST_M2_REG 43 +#define R9A08G045_SSI3_RST_M2_REG 44 +#define R9A08G045_SRC_RST 45 +#define R9A08G045_USB_U2H0_HRESETN 46 +#define R9A08G045_USB_U2H1_HRESETN 47 +#define R9A08G045_USB_U2P_EXL_SYSRST 48 +#define R9A08G045_USB_PRESETN 49 +#define R9A08G045_ETH0_RST_HW_N 50 +#define R9A08G045_ETH1_RST_HW_N 51 +#define R9A08G045_I2C0_MRST 52 +#define R9A08G045_I2C1_MRST 53 +#define R9A08G045_I2C2_MRST 54 +#define R9A08G045_I2C3_MRST 55 +#define R9A08G045_SCIF0_RST_SYSTEM_N 56 +#define R9A08G045_SCIF1_RST_SYSTEM_N 57 +#define R9A08G045_SCIF2_RST_SYSTEM_N 58 +#define R9A08G045_SCIF3_RST_SYSTEM_N 59 +#define R9A08G045_SCIF4_RST_SYSTEM_N 60 +#define R9A08G045_SCIF5_RST_SYSTEM_N 61 +#define R9A08G045_SCI0_RST 62 +#define R9A08G045_SCI1_RST 63 +#define R9A08G045_IRDA_RST 64 +#define R9A08G045_RSPI0_RST 65 +#define R9A08G045_RSPI1_RST 66 +#define R9A08G045_RSPI2_RST 67 +#define R9A08G045_RSPI3_RST 68 +#define R9A08G045_RSPI4_RST 69 +#define R9A08G045_CANFD_RSTP_N 70 +#define R9A08G045_CANFD_RSTC_N 71 +#define R9A08G045_GPIO_RSTN 72 +#define R9A08G045_GPIO_PORT_RESETN 73 +#define R9A08G045_GPIO_SPARE_RESETN 74 +#define R9A08G045_ADC_PRESETN 75 +#define R9A08G045_ADC_ADRST_N 76 +#define R9A08G045_TSU_PRESETN 77 +#define R9A08G045_OCTA_ARESETN 78 +#define R9A08G045_PDM0_PRESETNT 79 +#define R9A08G045_PCI_ARESETN 80 +#define R9A08G045_PCI_RST_B 81 +#define R9A08G045_PCI_RST_GP_B 82 +#define R9A08G045_PCI_RST_PS_B 83 +#define R9A08G045_PCI_RST_RSM_B 84 +#define R9A08G045_PCI_RST_CFG_B 85 +#define R9A08G045_PCI_RST_LOAD_B 86 +#define R9A08G045_SPDIF_RST 87 +#define R9A08G045_I3C_TRESETN 88 +#define R9A08G045_I3C_PRESETN 89 +#define R9A08G045_VBAT_BRESETN 90 +#define R9A08G045_LST_RESETN (R9A08G045_VBAT_BRESETN + 1) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_RENESAS_CLOCK_R9A07G054_CPG_H_ */ diff --git a/include/zephyr/dt-bindings/dma/rzg3_dma.h b/include/zephyr/dt-bindings/dma/rzg3_dma.h new file mode 100644 index 00000000000000..8b368c960d5f0d --- /dev/null +++ b/include/zephyr/dt-bindings/dma/rzg3_dma.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_RZG3_DMA_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_RZG3_DMA_H_ + +#define DMA_MEM_2_MEM 0 +#define DMA_RS_GTM_OSTM0TINT 1 +#define DMA_RS_GTM_OSTM1TINT 2 +#define DMA_RS_GTM_OSTM2TINT 3 +#define DMA_RS_GTM_OSTM3TINT 4 +#define DMA_RS_GTM_OSTM4TINT 5 +#define DMA_RS_GTM_OSTM5TINT 6 +#define DMA_RS_GTM_OSTM6TINT 7 +#define DMA_RS_GTM_OSTM7TINT 8 +#define DMA_RS_MTU3_TGIA0 9 +#define DMA_RS_MTU3_TGIB0 10 +#define DMA_RS_MTU3_TGIC0 11 +#define DMA_RS_MTU3_TGID0 12 +#define DMA_RS_MTU3_TGIA1 13 +#define DMA_RS_MTU3_TGIB1 14 +#define DMA_RS_MTU3_TGIA2 15 +#define DMA_RS_MTU3_TGIB2 16 +#define DMA_RS_MTU3_TGIA3 17 +#define DMA_RS_MTU3_TGIB3 18 +#define DMA_RS_MTU3_TGIC3 19 +#define DMA_RS_MTU3_TGID3 20 +#define DMA_RS_MTU3_TGIA4 21 +#define DMA_RS_MTU3_TGIB4 22 +#define DMA_RS_MTU3_TGIC4 23 +#define DMA_RS_MTU3_TGID4 24 +#define DMA_RS_MTU3_TCIV4 25 +#define DMA_RS_MTU3_TGIU5 26 +#define DMA_RS_MTU3_TGIV5 27 +#define DMA_RS_MTU3_TGIW5 28 +#define DMA_RS_MTU3_TGIA6 29 +#define DMA_RS_MTU3_TGIB6 30 +#define DMA_RS_MTU3_TGIC6 31 +#define DMA_RS_MTU3_TGID6 32 +#define DMA_RS_MTU3_TGIA7 33 +#define DMA_RS_MTU3_TGIB7 34 +#define DMA_RS_MTU3_TGIC7 35 +#define DMA_RS_MTU3_TGID7 36 +#define DMA_RS_MTU3_TCIV7 37 +#define DMA_RS_MTU3_TGIA8 38 +#define DMA_RS_MTU3_TGIB8 39 +#define DMA_RS_MTU3_TGIC8 40 +#define DMA_RS_MTU3_TGID8 41 +#define DMA_RS_GPT_CCMPA0 42 +#define DMA_RS_GPT_CCMPB0 43 +#define DMA_RS_GPT_CMPC0 44 +#define DMA_RS_GPT_CMPD0 45 +#define DMA_RS_GPT_CMPE0 46 +#define DMA_RS_GPT_CMPF0 47 +#define DMA_RS_GPT_ADTRGA0 48 +#define DMA_RS_GPT_ADTRGB0 49 +#define DMA_RS_GPT_OVF0 50 +#define DMA_RS_GPT_UNF0 51 +#define DMA_RS_GPT_CCMPA1 52 +#define DMA_RS_GPT_CCMPB1 53 +#define DMA_RS_GPT_CMPC1 54 +#define DMA_RS_GPT_CMPD1 55 +#define DMA_RS_GPT_CMPE1 56 +#define DMA_RS_GPT_CMPF1 57 +#define DMA_RS_GPT_ADTRGA1 58 +#define DMA_RS_GPT_ADTRGB1 59 +#define DMA_RS_GPT_OVF1 60 +#define DMA_RS_GPT_UNF1 61 +#define DMA_RS_GPT_CCMPA2 62 +#define DMA_RS_GPT_CCMPB2 63 +#define DMA_RS_GPT_CMPC2 64 +#define DMA_RS_GPT_CMPD2 65 +#define DMA_RS_GPT_CMPE2 66 +#define DMA_RS_GPT_CMPF2 67 +#define DMA_RS_GPT_ADTRGA2 68 +#define DMA_RS_GPT_ADTRGB2 69 +#define DMA_RS_GPT_OVF2 70 +#define DMA_RS_GPT_UNF2 71 +#define DMA_RS_GPT_CCMPA3 72 +#define DMA_RS_GPT_CCMPB3 73 +#define DMA_RS_GPT_CMPC3 74 +#define DMA_RS_GPT_CMPD3 75 +#define DMA_RS_GPT_CMPE3 76 +#define DMA_RS_GPT_CMPF3 77 +#define DMA_RS_GPT_ADTRGA3 78 +#define DMA_RS_GPT_ADTRGB3 79 +#define DMA_RS_GPT_OVF3 80 +#define DMA_RS_GPT_UNF3 81 +#define DMA_RS_GPT_CCMPA4 82 +#define DMA_RS_GPT_CCMPB4 83 +#define DMA_RS_GPT_CMPC4 84 +#define DMA_RS_GPT_CMPD4 85 +#define DMA_RS_GPT_CMPE4 86 +#define DMA_RS_GPT_CMPF4 87 +#define DMA_RS_GPT_ADTRGA4 88 +#define DMA_RS_GPT_ADTRGB4 89 +#define DMA_RS_GPT_OVF4 90 +#define DMA_RS_GPT_UNF4 91 +#define DMA_RS_GPT_CCMPA5 92 +#define DMA_RS_GPT_CCMPB5 93 +#define DMA_RS_GPT_CMPC5 94 +#define DMA_RS_GPT_CMPD5 95 +#define DMA_RS_GPT_CMPE5 96 +#define DMA_RS_GPT_CMPF5 97 +#define DMA_RS_GPT_ADTRGA5 98 +#define DMA_RS_GPT_ADTRGB5 99 +#define DMA_RS_GPT_OVF5 100 +#define DMA_RS_GPT_UNF5 101 +#define DMA_RS_GPT_CCMPA6 102 +#define DMA_RS_GPT_CCMPB6 103 +#define DMA_RS_GPT_CMPC6 104 +#define DMA_RS_GPT_CMPD6 105 +#define DMA_RS_GPT_CMPE6 106 +#define DMA_RS_GPT_CMPF6 107 +#define DMA_RS_GPT_ADTRGA6 108 +#define DMA_RS_GPT_ADTRGB6 109 +#define DMA_RS_GPT_OVF6 110 +#define DMA_RS_GPT_UNF6 111 +#define DMA_RS_GPT_CCMPA7 112 +#define DMA_RS_GPT_CCMPB7 113 +#define DMA_RS_GPT_CMPC7 114 +#define DMA_RS_GPT_CMPD7 115 +#define DMA_RS_GPT_CMPE7 116 +#define DMA_RS_GPT_CMPF7 117 +#define DMA_RS_GPT_ADTRGA7 118 +#define DMA_RS_GPT_ADTRGB7 119 +#define DMA_RS_GPT_OVF7 120 +#define DMA_RS_GPT_UNF7 121 +#define DMA_RS_SSIF_DMA_RX0 122 +#define DMA_RS_SSIF_DMA_TX0 123 +#define DMA_RS_SSIF_DMA_RX1 124 +#define DMA_RS_SSIF_DMA_TX1 125 +#define DMA_RS_SSIF_DMA_RX2 126 +#define DMA_RS_SSIF_DMA_TX2 127 +#define DMA_RS_SSIF_DMA_RX3 128 +#define DMA_RS_SSIF_DMA_TX3 129 +#define DMA_RS_SRC_IDEI 130 +#define DMA_RS_SRC_ODFI 131 +#define DMA_RS_I2C_INTRIIC_RI0 132 +#define DMA_RS_I2C_INTRIIC_TI0 133 +#define DMA_RS_I2C_INTRIIC_RI1 134 +#define DMA_RS_I2C_INTRIIC_TI1 135 +#define DMA_RS_I2C_INTRIIC_RI2 136 +#define DMA_RS_I2C_INTRIIC_TI2 137 +#define DMA_RS_I2C_INTRIIC_RI3 138 +#define DMA_RS_I2C_INTRIIC_TI3 139 +#define DMA_RS_I3C_INTRESP 140 +#define DMA_RS_I3C_INTCMD 141 +#define DMA_RS_I3C_INTIBI 142 +#define DMA_RS_I3C_INTRX 143 +#define DMA_RS_I3C_INTTX 144 +#define DMA_RS_I3C_INTRCV 145 +#define DMA_RS_I3C_INTHRESP 146 +#define DMA_RS_I3C_INTHCMD 147 +#define DMA_RS_I3C_INTHRX 148 +#define DMA_RS_I3C_INTHTX 149 +#define DMA_RS_SCIF_RXI0 150 +#define DMA_RS_SCIF_TXI0 151 +#define DMA_RS_SCIF_RXI1 152 +#define DMA_RS_SCIF_TXI1 153 +#define DMA_RS_SCIF_RXI2 154 +#define DMA_RS_SCIF_TXI2 155 +#define DMA_RS_SCIF_RXI3 156 +#define DMA_RS_SCIF_TXI3 157 +#define DMA_RS_SCIF_RXI4 158 +#define DMA_RS_SCIF_TXI4 159 +#define DMA_RS_SCIF_RXI5 160 +#define DMA_RS_SCIF_TXI5 161 +#define DMA_RS_SCIg_RXI0 162 +#define DMA_RS_SCIg_TXI0 163 +#define DMA_RS_SCIg_RXI1 164 +#define DMA_RS_SCIg_TXI1 165 +#define DMA_RS_RSPI_SPRI0 166 +#define DMA_RS_RSPI_SPTI0 167 +#define DMA_RS_RSPI_SPRI1 168 +#define DMA_RS_RSPI_SPTI1 169 +#define DMA_RS_RSPI_SPRI2 170 +#define DMA_RS_RSPI_SPTI2 171 +#define DMA_RS_RSPI_SPRI3 172 +#define DMA_RS_RSPI_SPTI3 173 +#define DMA_RS_RSPI_SPRI4 174 +#define DMA_RS_RSPI_SPTI4 175 +#define DMA_RS_CANFD_RXF_DMA0 176 +#define DMA_RS_CANFD_RXF_DMA1 177 +#define DMA_RS_CANFD_RXF_DMA2 178 +#define DMA_RS_CANFD_RXF_DMA3 179 +#define DMA_RS_CANFD_RXF_DMA4 180 +#define DMA_RS_CANFD_RXF_DMA5 181 +#define DMA_RS_CANFD_RXF_DMA6 182 +#define DMA_RS_CANFD_RXF_DMA7 183 +#define DMA_RS_CANFD_COM_DMA0 184 +#define DMA_RS_CANFD_COM_DMA1 185 +#define DMA_RS_SPDIF_RBDMAREQN_TX 186 +#define DMA_RS_SPDIF_RBDMAREQN_RX 187 +#define DMA_RS_PDM_INT_PDM_DAT0 188 +#define DMA_RS_PDM_INT_PDM_DAT1 189 +#define DMA_RS_PDM_INT_PDM_DAT2 190 + +#define LAST_RESOURCE_MARKER 191 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_RZG3_DMA_H_ */ diff --git a/include/zephyr/dt-bindings/gpio/rzg3s-gpio.h b/include/zephyr/dt-bindings/gpio/rzg3s-gpio.h new file mode 100644 index 00000000000000..282e301545339a --- /dev/null +++ b/include/zephyr/dt-bindings/gpio/rzg3s-gpio.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RZG3S_GPIO_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RZG3S_GPIO_H_ + +/** + * @brief RZ G3S specific GPIO Flags + * + * The pin driving ability flags are encoded in the 8 upper bits of @ref gpio_dt_flags_t as + * follows: + * + * - Bit 8: Pin driving ability present + * - Bit 10..9: Pin driving ability value using PINCTRL_RZG3S_PIN_IOLH_xx macro as specified in + * dt-bindings/pinctrl/renesas/pinctrl-r9a08g045.h + * + * Use RZG3S_GPIO_DRIVE_IOLH_SET(iolh_val) macro for the GPIO pin driving ability configuration. + * + * - Bit 11: Pin Digital Noise Filter ability present + * - Bit 13..12: Digital Noise Filter Number value + * - Bit 15..14: Digital Noise Filter Clock Selection value + * + * @ingroup gpio_interface + * @{ + */ + +/** + * @name RZ G3S pin driving ability flags + * @brief RZ G3S pin driving ability flags + * @{ + */ + +/** @cond INTERNAL_HIDDEN */ +/** Pin driving ability value shift */ +#define RZG3S_GPIO_DRIVE_IOLH_SHIFT 9U +#define RZG3S_GPIO_DRIVE_IOLH_MASK (0x3 << RZG3S_GPIO_DRIVE_IOLH_SHIFT) + +/** Pin Digital Noise Filter Number */ +#define RZG3S_GPIO_FILTER_NUM_SHIFT 12U +#define RZG3S_GPIO_FILTER_NUM_MASK (0x3 << RZG3S_GPIO_FILTER_NUM_SHIFT) + +/** Pin Digital Noise Filter Clock Selection */ +#define RZG3S_GPIO_FILTER_CLK_SHIFT 14U +#define RZG3S_GPIO_FILTER_CLK_MASK (0x3 << RZG3S_GPIO_FILTER_CLK_SHIFT) + +/** @endcond */ + +/** Pin driving ability present */ +#define RZG3S_GPIO_DRIVE_IOLH_PRESENT BIT(8) + +/** Pin Digital Noise Filter present */ +#define RZG3S_GPIO_FILTER_PRESENT BIT(11) + +/** Pin driving ability configuration macro */ +#define RZG3S_GPIO_DRIVE_IOLH_SET(iolh_val) \ + (RZG3S_GPIO_DRIVE_IOLH_PRESENT | ((iolh_val) << RZG3S_GPIO_DRIVE_IOLH_SHIFT))) + +#define RZG3S_GPIO_DRIVE_IOLH_GET(flags) \ + (((flags) & RZG3S_GPIO_DRIVE_IOLH_MASK) >> RZG3S_GPIO_DRIVE_IOLH_SHIFT) + +/** Pin Digital Noise Filter ability configuration macro */ +#define RZG3S_GPIO_FILTER_SET(filnum, filclksel) \ + (RZG3S_GPIO_FILTER_PRESENT | ((filnum) << RZG3S_GPIO_FILTER_NUM_SHIFT) | \ + ((filclksel) << RZG3S_GPIO_FILTER_CLK_SHIFT)) + +#define RZG3S_GPIO_FILTER_NUM_GET(flags) \ + (((flags) & RZG3S_GPIO_FILTER_NUM_MASK) >> RZG3S_GPIO_FILTER_NUM_SHIFT) + +#define RZG3S_GPIO_FILTER_CLK_GET(flags) \ + (((flags) & RZG3S_GPIO_FILTER_CLK_MASK) >> RZG3S_GPIO_FILTER_CLK_SHIFT) + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_RZG3S_GPIO_H_ */ diff --git a/include/zephyr/dt-bindings/interrupt-controller/r7s9210-intc.h b/include/zephyr/dt-bindings/interrupt-controller/r7s9210-intc.h index 71000ce181b926..8400b62fcc6458 100644 --- a/include/zephyr/dt-bindings/interrupt-controller/r7s9210-intc.h +++ b/include/zephyr/dt-bindings/interrupt-controller/r7s9210-intc.h @@ -6,14 +6,24 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_R7S9210_INTC_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_R7S9210_INTC_H_ -#define R7S9210_IRQ0 0 -#define R7S9210_IRQ1 1 -#define R7S9210_IRQ2 2 -#define R7S9210_IRQ3 3 -#define R7S9210_IRQ4 4 -#define R7S9210_IRQ5 5 -#define R7S9210_IRQ6 6 -#define R7S9210_IRQ7 7 +#define R7S9210_IRQ0 0 +#define R7S9210_IRQ1 1 +#define R7S9210_IRQ2 2 +#define R7S9210_IRQ3 3 +#define R7S9210_IRQ4 4 +#define R7S9210_IRQ5 5 +#define R7S9210_IRQ6 6 +#define R7S9210_IRQ7 7 + +#define R9A08G045_IRQ_NMI 0 +#define R9A08G045_IRQ0 1 +#define R9A08G045_IRQ1 2 +#define R9A08G045_IRQ2 3 +#define R9A08G045_IRQ3 4 +#define R9A08G045_IRQ4 5 +#define R9A08G045_IRQ5 6 +#define R9A08G045_IRQ6 7 +#define R9A08G045_IRQ7 8 #define IRQ_TYPE_LOW_LEVEL BIT(1) #define IRQ_TYPE_EDGE_FALLING BIT(2) diff --git a/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-r9a08g045.h b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-r9a08g045.h new file mode 100644 index 00000000000000..19615d63dcdcff --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-r9a08g045.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_R9A08G045_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_R9A08G045_H_ + +#define RZG_PIN_NUM_IN_PORT 8 + +/* Port names as labeled in the Hardware Manual */ +#define PORT0 0 +#define PORT1 1 +#define PORT2 2 +#define PORT3 3 +#define PORT4 4 +#define PORT5 5 +#define PORT6 6 +#define PORT7 7 +#define PORT8 8 +#define PORT9 9 +#define PORT10 10 +#define PORT11 11 +#define PORT12 12 +#define PORT13 13 +#define PORT14 14 +#define PORT15 15 +#define PORT16 16 +#define PORT17 17 +#define PORT18 18 + +#define PINCTRL_RZG3S_FUNC_GPIO 0x0 + +/* + * Create the pin index from its bank and position numbers and store in + * the upper 16 bits the alternate function identifier + * + * b: port number 0..18 + * p: pin number within port 0.. + * f: pin function + */ +#define RZG3S_PINMUX(b, p, f) ((b) * RZG_PIN_NUM_IN_PORT + (p) | ((f) << 16)) + +/* Driving Ability Control Register (IOLH_m) + * Group-A 3.3V + */ +#define PINCTRL_RZG3S_PIN_IOLH_A_3_3V_1900 0 +#define PINCTRL_RZG3S_PIN_IOLH_A_3_3V_4000 1 +#define PINCTRL_RZG3S_PIN_IOLH_A_3_3V_8000 2 +#define PINCTRL_RZG3S_PIN_IOLH_A_3_3V_9000 3 +/* Group-A 1.8V */ +#define PINCTRL_RZG3S_PIN_IOLH_A_1_8V_2200 0 +#define PINCTRL_RZG3S_PIN_IOLH_A_1_8V_4400 1 +#define PINCTRL_RZG3S_PIN_IOLH_A_1_8V_9000 2 +#define PINCTRL_RZG3S_PIN_IOLH_A_1_8V_10000 3 + +/* Group-B 3.3V */ +#define PINCTRL_RZG3S_PIN_IOLH_B_3_3V_4000 0 +#define PINCTRL_RZG3S_PIN_IOLH_B_3_3V_6000 1 +#define PINCTRL_RZG3S_PIN_IOLH_B_3_3V_8000 2 +#define PINCTRL_RZG3S_PIN_IOLH_B_3_3V_9000 3 +/* Group-B 1.8V */ +#define PINCTRL_RZG3S_PIN_IOLH_B_1_8V_7000 0 +#define PINCTRL_RZG3S_PIN_IOLH_B_1_8V_8000 1 +#define PINCTRL_RZG3S_PIN_IOLH_B_1_8V_9000 2 +#define PINCTRL_RZG3S_PIN_IOLH_B_1_8V_10000 3 + +/* Group-C 3.3V */ +#define PINCTRL_RZG3S_PIN_IOLH_C_3_3V_4500 0 +#define PINCTRL_RZG3S_PIN_IOLH_C_3_3V_5200 1 +#define PINCTRL_RZG3S_PIN_IOLH_C_3_3V_5700 2 +#define PINCTRL_RZG3S_PIN_IOLH_C_3_3V_6050 3 +/* Group-C 2.5V */ +#define PINCTRL_RZG3S_PIN_IOLH_C_2_5V_4700 0 +#define PINCTRL_RZG3S_PIN_IOLH_C_2_5V_5300 1 +#define PINCTRL_RZG3S_PIN_IOLH_C_2_5V_5800 2 +#define PINCTRL_RZG3S_PIN_IOLH_C_2_5V_6100 3 +/* Group-C 1.8V */ +#define PINCTRL_RZG3S_PIN_IOLH_C_1_8V_5200 0 +#define PINCTRL_RZG3S_PIN_IOLH_C_1_8V_6000 1 +#define PINCTRL_RZG3S_PIN_IOLH_C_1_8V_6550 2 +#define PINCTRL_RZG3S_PIN_IOLH_C_1_8V_6800 3 + +/* Pin Digital Noise Filter Number */ +#define PINCTRL_RZG3S_FILTER_NUM_SHIFT 0x0 +#define PINCTRL_RZG3S_FILTER_NUM_MASK (0x3 << PINCTRL_RZG3S_FILTER_NUM_SHIFT) +/* Pin Digital Noise Filter Clock Selection */ +#define PINCTRL_RZG3S_FILTER_CLK_SHIFT 0x2 +#define PINCTRL_RZG3S_FILTER_CLK_MASK (0x3 << PINCTRL_RZG3S_FILTER_CLK_SHIFT) + +/* + * Pin Digital Noise Filter ability configuration macro + * @filnum - number of filter stages (FILNUM_m) + * @filclksel - filter clk divider (FILCLKSEL_m) + */ +#define PINCTRL_RZG3S_FILTER_SET(filnum, filclksel) \ + ((((filnum) << PINCTRL_RZG3S_FILTER_NUM_SHIFT) & PINCTRL_RZG3S_FILTER_NUM_MASK) | \ + (((filclksel) << PINCTRL_RZG3S_FILTER_CLK_SHIFT) & PINCTRL_RZG3S_FILTER_CLK_MASK)) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_R9A08G045_H_ */ diff --git a/include/zephyr/dt-bindings/pwm/rza2m_pwm.h b/include/zephyr/dt-bindings/pwm/rza2m_pwm.h index e43e6454074144..d52b24c63e361f 100644 --- a/include/zephyr/dt-bindings/pwm/rza2m_pwm.h +++ b/include/zephyr/dt-bindings/pwm/rza2m_pwm.h @@ -9,6 +9,14 @@ #define PWM_CHANNEL_INPUT_A (0 << 31) #define PWM_CHANNEL_INPUT_B (1 << 31) +#define PWM_CHANNEL_PROTECTED (1 << 30) + +#define PWM_PROTECTED(x) (x | PWM_CHANNEL_PROTECTED) + +#define PWM_HIGH BIT(0) +#define PWM_LOW BIT(1) +#define PWM_DT BIT(2) + #define MTU_PWM_CH_IO_A 0 #define MTU_PWM_CH_IO_B 1 #define MTU_PWM_CH_IO_C 2 diff --git a/samples/arch/mpu/mpu_test/src/main.c b/samples/arch/mpu/mpu_test/src/main.c index c850a9dd9029f9..589c6fed210fe7 100644 --- a/samples/arch/mpu/mpu_test/src/main.c +++ b/samples/arch/mpu/mpu_test/src/main.c @@ -11,6 +11,7 @@ #include #include #include +#include #define PR_SHELL(sh, fmt, ...) \ shell_fprintf(sh, SHELL_NORMAL, fmt, ##__VA_ARGS__) @@ -19,8 +20,16 @@ /* Assumption: our devices have less than 64MB of memory */ #define RESERVED_MEM_MAP (CONFIG_SRAM_BASE_ADDRESS + 0x4000000) + +#if defined(CONFIG_SOC_SERIES_RZ_G) +#define FLASH_MEM (uintptr_t)__rom_region_start +#define RO_ADDR (FLASH_MEM + 0x100) +#define RAM_MEM (uintptr_t)__kernel_ram_start +#else #define FLASH_MEM CONFIG_FLASH_BASE_ADDRESS +#define RO_ADDR (FLASH_MEM + 0x4000) #define RAM_MEM CONFIG_SRAM_BASE_ADDRESS +#endif /* CONFIG_SOC_SERIES_RZ_G */ /* MPU test command help texts */ #define READ_CMD_HELP "Read from a reserved address in the memory map" @@ -98,9 +107,10 @@ static int cmd_write(const struct shell *sh, size_t argc, char *argv[]) ARG_UNUSED(argv); /* 16K reserved to the application */ - uint32_t *p_mem = (uint32_t *) (FLASH_MEM + 0x4000); + uint32_t *p_mem = (uint32_t *)(RO_ADDR); - PR_SHELL(sh, "write address: 0x%x\n", FLASH_MEM + 0x4000); + PR_SHELL(sh, "write address: 0x%x\n", (uint32_t)RO_ADDR); + printf("write address: 0x%x\n", (uint32_t)p_mem); /* Write in to boot FLASH/ROM */ *p_mem = 0xBADC0DE; @@ -116,6 +126,9 @@ static int cmd_run(const struct shell *sh, size_t argc, char *argv[]) void (*func_ptr)(void) = (void (*)(void)) RAM_MEM; + PR_SHELL(sh, "exec address: 0x%x\n", (uint32_t)func_ptr); + printf("exec address: 0x%x\n", (uint32_t)func_ptr); + /* Run code located in RAM */ func_ptr(); diff --git a/samples/drivers/i2s/wm8978/Kconfig b/samples/drivers/i2s/wm8978/Kconfig new file mode 100644 index 00000000000000..b685ff3b053e76 --- /dev/null +++ b/samples/drivers/i2s/wm8978/Kconfig @@ -0,0 +1,31 @@ +# Private config options for can sample app + +# Copyright (c) 2018 Alexander Wachter +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "WM8978 loopback" + +config WM8978_ANALOG_LOOPBACK + bool "Analog loopback mode" + default n + help + Set the codec to loopback mode. + This connects input line to output line. + +config WM8978_MIXER + bool "Mix input signal with DAC output" + default n + depends on WM8978_ANALOG_LOOPBACK + help + Mix input signal with DAC output + +if !WM8978_ANALOG_LOOPBACK +config WM8978_LOOPBACK + bool "Loopback mode" + default n + help + Set the codec to loopback mode. + This connects ADC to DAC. +endif + +source "Kconfig.zephyr" diff --git a/samples/drivers/i2s/wm8978/src/wm8978.c b/samples/drivers/i2s/wm8978/src/wm8978.c index 8492cc8933e0cf..132fb6c64eb463 100644 --- a/samples/drivers/i2s/wm8978/src/wm8978.c +++ b/samples/drivers/i2s/wm8978/src/wm8978.c @@ -19,10 +19,6 @@ LOG_MODULE_REGISTER(codec_wm8978); #include #include -/* #define WM8978_CALLBACK */ -/* #define WM8978_LOOPBACK */ -/* #define WM8978_MIXER */ - /* ==== Register Address ==== */ #define WM8978_REG_SOFT_RESET 0x00 #define WM8978_REG_POW_MANAGE1 0x01 @@ -147,6 +143,15 @@ static int wm8978_init(const struct device *dev) LOG_ERR("Bus device %s not ready!", cfg->bus.bus->name); return -EINVAL; } +#ifdef CONFIG_WM8978_ANALOG_LOOPBACK + LOG_WRN("Analog loopback"); +#endif +#ifdef CONFIG_WM8978_LOOPBACK + LOG_WRN("Loopback"); +#endif +#ifdef CONFIG_WM8978_MIXER + LOG_WRN("Analog mixer"); +#endif return 0; } @@ -184,7 +189,8 @@ static int codec_configure(const struct device *dev, struct audio_codec_cfg *cfg reg |= WM8978_MANAGE2_INPPGAENR_ON; wm8978_write(dev, WM8978_CMD(WM8978_REG_POW_MANAGE2, reg)); temp = reg; -#ifdef WM8978_LOOPBACK +#ifdef CONFIG_WM8978_LOOPBACK + LOG_WRN("Set loopback"); /* ==== Set LOOPBACK = 1 in register R5. ==== */ reg = WM8978_COMPADING_LOOPBACK; wm8978_write(dev, WM8978_CMD(WM8978_REG_COMPADING_CTL, reg)); @@ -228,10 +234,12 @@ static int codec_configure(const struct device *dev, struct audio_codec_cfg *cfg reg = WM8978_DAC_CTL_INI_VALUE | WM8978_DAC_CTL_DACOSR128_ON; wm8978_write(dev, WM8978_CMD(WM8978_REG_DAC_CTL, reg)); -#ifdef WM8978_CALLBACK +#ifdef CONFIG_WM8978_ANALOG_LOOPBACK + LOG_WRN("Set analog loopback"); /* Set BYPL2LMIX = 0 in register R50. */ reg = WM8978_LMIX_CTL_INI_VALUE; -#ifndef WM9878_MIXER +#ifndef CONFIG_WM8978_MIXER + LOG_WRN("Clear mixer"); reg &= ~WM8978_LMIX_CTL_DACL2LMIX_BIT; #endif reg |= WM8978_LMIX_CTL_BYPL2LMIX_BIT; @@ -239,7 +247,8 @@ static int codec_configure(const struct device *dev, struct audio_codec_cfg *cfg /* Set BYPR2RMIX = 1 in register R51. */ reg = WM8978_RMIX_CTL_INI_VALUE; -#ifndef WM9878_MIXER +#ifndef CONFIG_WM8978_MIXER + LOG_WRN("Clear mixer"); reg &= ~WM8978_RMIX_CTL_DACR2RMIX_BIT; #endif reg |= WM8978_RMIX_CTL_BYPR2RMIX_BIT; diff --git a/samples/drivers/irq_keys/boards/rz_g3s.overlay b/samples/drivers/irq_keys/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..57aee36bb673a5 --- /dev/null +++ b/samples/drivers/irq_keys/boards/rz_g3s.overlay @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + + / { + keyboard { + compatible = "irq-keys"; + + pinctrl-names = "default"; + pinctrl-0 = <&keyboard_pins>; + + sw3 { + interrupt-parent = <&intc>; + interrupts = ; + }; + + sw_nmi { + interrupt-parent = <&intc>; + interrupts = ; + }; + }; + }; + + &pinctrl { + keyboard_pins: keyboard_pins { + sw3-pinmux { + pinmux = ; /* IRQ1 */ + input-debounce = <(PINCTRL_RZG3S_FILTER_SET(3, 3))>; + }; + + sw3-pins { + pins = "NMI"; + input-debounce = <(PINCTRL_RZG3S_FILTER_SET(1, 2))>; + }; + }; +}; diff --git a/samples/drivers/irq_keys/boards/rz_g3s_fpu.overlay b/samples/drivers/irq_keys/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..57aee36bb673a5 --- /dev/null +++ b/samples/drivers/irq_keys/boards/rz_g3s_fpu.overlay @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + + / { + keyboard { + compatible = "irq-keys"; + + pinctrl-names = "default"; + pinctrl-0 = <&keyboard_pins>; + + sw3 { + interrupt-parent = <&intc>; + interrupts = ; + }; + + sw_nmi { + interrupt-parent = <&intc>; + interrupts = ; + }; + }; + }; + + &pinctrl { + keyboard_pins: keyboard_pins { + sw3-pinmux { + pinmux = ; /* IRQ1 */ + input-debounce = <(PINCTRL_RZG3S_FILTER_SET(3, 3))>; + }; + + sw3-pins { + pins = "NMI"; + input-debounce = <(PINCTRL_RZG3S_FILTER_SET(1, 2))>; + }; + }; +}; diff --git a/samples/drivers/irq_keys/sample.yaml b/samples/drivers/irq_keys/sample.yaml index 831773c49f5cce..3438f632e8a7d8 100644 --- a/samples/drivers/irq_keys/sample.yaml +++ b/samples/drivers/irq_keys/sample.yaml @@ -3,6 +3,11 @@ sample: name: IRQ Keys sample tests: sample.drivers.rz.irq_keys: - platform_allow: rz_a2m - tags: input + platform_allow: + - rz_a2m + - rz_g3s + tags: + - drivers + - button depends_on: pinctrl + harness: button diff --git a/samples/drivers/watchdog/boards/rz_g3s.overlay b/samples/drivers/watchdog/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..c0eeac8aea71ba --- /dev/null +++ b/samples/drivers/watchdog/boards/rz_g3s.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + watchdog0 = &wdt1; + }; +}; diff --git a/samples/drivers/watchdog/boards/rz_g3s_fpu.overlay b/samples/drivers/watchdog/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..f35ee1b5324463 --- /dev/null +++ b/samples/drivers/watchdog/boards/rz_g3s_fpu.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + watchdog0 = &wdt2; + }; +}; diff --git a/samples/posix/eventfd/boards/rz_g3s.conf b/samples/posix/eventfd/boards/rz_g3s.conf new file mode 100644 index 00000000000000..ce31d5b5c75b3e --- /dev/null +++ b/samples/posix/eventfd/boards/rz_g3s.conf @@ -0,0 +1 @@ +CONFIG_NET_BUF_DATA_ALIGN=8 diff --git a/samples/sensor/bme280/boards/rz_g3s.overlay b/samples/sensor/bme280/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..023cf987dad72d --- /dev/null +++ b/samples/sensor/bme280/boards/rz_g3s.overlay @@ -0,0 +1,15 @@ +/ { + chosen { + zephyr,i2c = &i2c0; + }; +}; + +&i2c0 { + status = "okay"; + bme280: bme280@76 { + compatible = "bosch,bme280"; + reg = <0x76>; + friendly-name = "BME280"; + status = "okay"; + }; +}; diff --git a/samples/sensor/bme280/boards/rz_g3s_fpu.overlay b/samples/sensor/bme280/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..023cf987dad72d --- /dev/null +++ b/samples/sensor/bme280/boards/rz_g3s_fpu.overlay @@ -0,0 +1,15 @@ +/ { + chosen { + zephyr,i2c = &i2c0; + }; +}; + +&i2c0 { + status = "okay"; + bme280: bme280@76 { + compatible = "bosch,bme280"; + reg = <0x76>; + friendly-name = "BME280"; + status = "okay"; + }; +}; diff --git a/samples/sensor/bme280/sample.yaml b/samples/sensor/bme280/sample.yaml index 2e84cd1af03e7f..f4874870a9e464 100644 --- a/samples/sensor/bme280/sample.yaml +++ b/samples/sensor/bme280/sample.yaml @@ -7,6 +7,7 @@ tests: platform_allow: - adafruit_feather_m0_basic_proto - rpi_pico + - rz_g3s integration_platforms: - adafruit_feather_m0_basic_proto harness_config: diff --git a/samples/subsys/input/ft5316/sample.yaml b/samples/subsys/input/ft5316/sample.yaml index 04a6d97830949b..8d4abc97c1b71a 100644 --- a/samples/subsys/input/ft5316/sample.yaml +++ b/samples/subsys/input/ft5316/sample.yaml @@ -6,3 +6,5 @@ tests: build_only: true integration_platforms: - rz_a2m + platform_allow: + - rz_a2m diff --git a/samples/subsys/ipc/openamp_rsc_table_rzg3/CMakeLists.txt b/samples/subsys/ipc/openamp_rsc_table_rzg3/CMakeLists.txt new file mode 100644 index 00000000000000..c0cc1bf03b4d38 --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table_rzg3/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.20.0) +# Copyright (c) 2020 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 +# + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(openamp_rsc_table_rzg3) + +# METAL_MAX_DEVICE_REGIONS is used to give the number of memory regions shared +# between processors. By default only one region is defined for the vrings +# and rpmsg buffers. The METAL_MAX_DEVICE_REGIONS has to be redefined to add a +# second region for the resource table. +zephyr_compile_definitions(METAL_MAX_DEVICE_REGIONS=2) + +target_include_directories(app PRIVATE ${LIBMETAL_INCLUDE_DIR} ${OPENAMP_INCLUDE_DIR} ${PLATFORM_DIR}) +target_include_directories(app PRIVATE src) + +target_sources(app PRIVATE src/resource_table.c src/main_remote.c) diff --git a/samples/subsys/ipc/openamp_rsc_table_rzg3/README.rst b/samples/subsys/ipc/openamp_rsc_table_rzg3/README.rst new file mode 100644 index 00000000000000..c41abfce04ed49 --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table_rzg3/README.rst @@ -0,0 +1,79 @@ +.. zephyr:code-sample:: openamp-rsc-table-rzg3 + :name: OpenAMP using resource table for RZ/G boards + :relevant-api: ipm_interface + + Send messages between two cores using OpenAMP and a resource table. + +Overview +******** + +This is sample implementation of the client OpenAMP application. +This application demonstrates how to use OpenAMP with Zephyr based on a resource_table +with RZ/G Multi-OS Package v2.0.0. +It is designed to respond for the requests from RPMSG client sample +application provided by Renesas RZ/G BSP. + +This sample implementation is compatible with platforms that embed +a Linux kernel OS on the main processor and a Zephyr application on +the co-processor. + +Building the application +************************* + +Zephyr +------- + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/ipc/openamp_rsc_table_rzg3 + :goals: test + +Linux +------ + +Start linux system on Cortex-A55 core using BSP images provided by +Renesas BSP pack. + +Running the sample +******************* + +Zephyr console +--------------- + +Open a serial terminal (minicom, putty, etc.) and connect the board with the +following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board. + +Linux console +--------------- + +Open a Linux shell (minicom, ssh, etc.) and run the following command: + +.. code-block:: console + + root@linuxshell: rpmsg_client_sample 0 0 + +Result on Zephyr console on boot +-------------------------------- + +The following message will appear on the corresponding Zephyr console: + +.. code-block:: console + + ***** Booting Zephyr OS v#.##.#-####-g########## ***** + [00:00:00.000,000] openamp_rsc_table: Starting application threads! + + [00:00:00.000,000] openamp_rsc_table: + OpenAMP[remote] linux responder demo started + + [00:00:02.520,000] openamp_rsc_table: new_service_cb: message received0 + + [00:00:02.520,000] openamp_rsc_table: + OpenAMP[remote] Linux sample client responder started + + [00:00:03.341,000] openamp_rsc_table: OpenAMP demo ended diff --git a/samples/subsys/ipc/openamp_rsc_table_rzg3/boards/rz_g3s.overlay b/samples/subsys/ipc/openamp_rsc_table_rzg3/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..578d527028a9a2 --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table_rzg3/boards/rz_g3s.overlay @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 Epam Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + /* + * Allocating whole openamp region as reserved memroy + * to save MPU entries + */ + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + openamp_shm: memory-region@62F00000 { + compatible = "zephyr,memory-region"; + reg = <0x62F00000 0x600000>; + zephyr,memory-region = "openamp_memory"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; + }; + + chosen { + zephyr,ipc_shm = &vring_shm0; + zephyr,ipc = &mhu1; + }; + + vring_ctrl0: memory@63000000 { + compatible = "mmio-sram"; + reg = <0x63000000 0x50000>; + }; + + vring_ctrl1: memory@63050000 { + compatible = "mmio-sram"; + reg = <0x63050000 0x50000>; + }; + + vring_shm0: memory@63200000 { + compatible = "mmio-sram"; + reg = <0x63200000 0x300000>; + }; + + rsctbl: memory@62F00000 { + compatible = "mmio-sram"; + reg = <0x62F00000 0x1000>; + }; + + mhu1_shm: memory@62F01008 { + compatible = "mmio-sram"; + reg = <0x62F01008 0x8>; + }; +}; + +&mhu1 { + memory-region = <&mhu1_shm>; + status = "okay"; +}; diff --git a/samples/subsys/ipc/openamp_rsc_table_rzg3/boards/rz_g3s_fpu.overlay b/samples/subsys/ipc/openamp_rsc_table_rzg3/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..5a539a4f8ce71a --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table_rzg3/boards/rz_g3s_fpu.overlay @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 Epam Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + /* + * Allocating whole openamp region as reserved memroy + * to save MPU entries + */ + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + openamp_shm: memory-region@62F00000 { + compatible = "zephyr,memory-region"; + reg = <0x62F00000 0x600000>; + zephyr,memory-region = "openamp_memory"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; + }; + + chosen { + zephyr,ipc_shm = &vring_shm0; + zephyr,ipc = &mhu0_fpu; + }; + + vring_ctrl0: memory@63000000 { + compatible = "mmio-sram"; + reg = <0x63000000 0x50000>; + }; + + vring_ctrl1: memory@63050000 { + compatible = "mmio-sram"; + reg = <0x63050000 0x50000>; + }; + + vring_shm0: memory@63200000 { + compatible = "mmio-sram"; + reg = <0x63200000 0x300000>; + }; + + rsctbl: memory@62F00000 { + compatible = "mmio-sram"; + reg = <0x62F00000 0x1000>; + }; + + mhu0_shm: memory@62F01000 { + compatible = "mmio-sram"; + reg = <0x62F01000 0x8>; + }; +}; + +&mhu0_fpu { + memory-region = <&mhu0_shm>; + status = "okay"; +}; diff --git a/samples/subsys/ipc/openamp_rsc_table_rzg3/prj.conf b/samples/subsys/ipc/openamp_rsc_table_rzg3/prj.conf new file mode 100644 index 00000000000000..ba1053eb8633d4 --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table_rzg3/prj.conf @@ -0,0 +1,7 @@ +CONFIG_KERNEL_BIN_NAME="zephyr_openamp_rsc_table" +CONFIG_LOG=y +CONFIG_LOG_MODE_MINIMAL=y +CONFIG_IPM=y +CONFIG_HEAP_MEM_POOL_SIZE=1024 +CONFIG_OPENAMP=y +CONFIG_OPENAMP_RSC_TABLE=n diff --git a/samples/subsys/ipc/openamp_rsc_table_rzg3/sample.yaml b/samples/subsys/ipc/openamp_rsc_table_rzg3/sample.yaml new file mode 100644 index 00000000000000..2d5ef64c7bf184 --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table_rzg3/sample.yaml @@ -0,0 +1,14 @@ +sample: + description: This app provides an example of how to integrate OpenAMP + with Zephyr including a resource table for Renesas RZ/G boards. + name: OpenAMP with resource table client example +tests: + sample.subsys.ipc.openamp_rs_table_rzg3: + build_only: true + platform_allow: + - rz_g3s + - rz_g3s_fpu + integration_platforms: + - rz_g3s + - rz_g3s_fpu + tags: ipm diff --git a/samples/subsys/ipc/openamp_rsc_table_rzg3/src/main_remote.c b/samples/subsys/ipc/openamp_rsc_table_rzg3/src/main_remote.c new file mode 100644 index 00000000000000..35250af5422ce8 --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table_rzg3/src/main_remote.c @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2023, EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include "resource_table.h" + +#include +LOG_MODULE_REGISTER(openamp_rsc_table); + +#define SHM_DEVICE_NAME "shm" + +#if !DT_HAS_CHOSEN(zephyr_ipc_shm) +#error "Sample requires definition of shared memory for rpmsg" +#endif + +#define APP_EPT_ADDR 1024 + +#define SHUTDOWN_MSG (0xEF56A55A) + +/* Constants derived from device tree */ +#define SHM_NODE DT_CHOSEN(zephyr_ipc_shm) +#define SHM_START_ADDR DT_REG_ADDR(SHM_NODE) +#define SHM_SIZE DT_REG_SIZE(SHM_NODE) + +#define RSC_TABLE_ADDR DT_REG_ADDR(DT_NODELABEL(rsctbl)) + +#define APP_TASK_STACK_SIZE (1024) + +K_THREAD_STACK_DEFINE(thread_mng_stack, APP_TASK_STACK_SIZE); +K_THREAD_STACK_DEFINE(thread_rp__client_stack, APP_TASK_STACK_SIZE); + +static struct k_thread thread_mng_data; +static struct k_thread thread_rp__client_data; + +static const struct device *const ipm_handle = DEVICE_DT_GET(DT_CHOSEN(zephyr_ipc)); + +static metal_phys_addr_t shm_physmap = CM33_TO_A55_ADDR_NS(SHM_START_ADDR); +static metal_phys_addr_t rsc_physmap = RSC_TABLE_ADDR; + +struct metal_device shm_device = { + .name = SHM_DEVICE_NAME, + .num_regions = 2, + .regions = { + {.virt = NULL}, /* shared memory */ + {.virt = NULL}, /* rsc_table memory */ + }, + .node = {NULL}, + .irq_num = 0, + +}; + +struct rpmsg_rcv_msg { + void *data; + size_t len; +}; + +static struct metal_io_region *shm_io; +static struct rpmsg_virtio_shm_pool shpool; + +static struct metal_io_region *rsc_io; +static struct rpmsg_virtio_device rvdev; + +static void *rsc_table; +static struct rpmsg_device *rpdev; + +static char rx_sc_msg[512]; +static struct rpmsg_endpoint sc_ept; +static struct rpmsg_rcv_msg sc_msg = {.data = rx_sc_msg}; + +static K_SEM_DEFINE(data_sem, 0, 1); +static K_SEM_DEFINE(data_sc_sem, 0, 1); + +static volatile int finish; + +static void platform_ipm_callback(const struct device *dev, void *context, uint32_t id, + volatile void *data) +{ + k_sem_give(&data_sem); +} + +static int rpmsg_recv_cs_callback(struct rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, + void *priv) +{ + memcpy(sc_msg.data, data, len); + sc_msg.len = len; + if ((*(unsigned int *)data) == SHUTDOWN_MSG) { + finish = 1; + } + k_sem_give(&data_sc_sem); + + return RPMSG_SUCCESS; +} + +static void receive_message(unsigned char **msg, unsigned int *len) +{ + int status = k_sem_take(&data_sem, K_FOREVER); + + if (status == 0) { + rproc_virtio_notified(rvdev.vdev, VRING1_ID); + } +} + +static void new_service_cb(struct rpmsg_device *rdev, const char *name, uint32_t src) +{ + LOG_INF("%s: message received from service %s", __func__, name); +} + +int mailbox_notify(void *priv, uint32_t id) +{ + ARG_UNUSED(priv); + + ipm_send(ipm_handle, 0, id, NULL, 0); + return 0; +} + +int platform_init(void) +{ + void *rsc_tab_addr; + int rsc_size; + struct metal_device *device; + struct metal_init_params metal_params = METAL_INIT_DEFAULTS; + int status; + + status = metal_init(&metal_params); + if (status) { + LOG_ERR("metal_init: failed: %d", status); + return -1; + } + + status = metal_register_generic_device(&shm_device); + if (status) { + LOG_ERR("Couldn't register shared memory: %d", status); + return -1; + } + + status = metal_device_open("generic", SHM_DEVICE_NAME, &device); + if (status) { + LOG_ERR("metal_device_open failed: %d", status); + return -1; + } + + /* declare shared memory region */ + metal_io_init(&device->regions[0], (void *)SHM_START_ADDR, &shm_physmap, SHM_SIZE, -1, 0, + NULL); + + shm_io = metal_device_io_region(device, 0); + if (!shm_io) { + LOG_ERR("Failed to get shm_io region"); + return -1; + } + + /* declare resource table region */ + rsc_table_get(&rsc_tab_addr, &rsc_size); + memcpy((void *)RSC_TABLE_ADDR, rsc_tab_addr, rsc_size); + rsc_table = (struct st_resource_table *)RSC_TABLE_ADDR; + + metal_io_init(&device->regions[1], (void *)RSC_TABLE_ADDR, &rsc_physmap, rsc_size, -1, 0, + NULL); + + rsc_io = metal_device_io_region(device, 1); + if (!rsc_io) { + LOG_ERR("Failed to get rsc_io region"); + return -1; + } + + /* setup IPM */ + if (!device_is_ready(ipm_handle)) { + LOG_ERR("IPM device is not ready"); + return -1; + } + + ipm_register_callback(ipm_handle, platform_ipm_callback, NULL); + + status = ipm_set_enabled(ipm_handle, 1); + if (status) { + LOG_ERR("ipm_set_enabled failed"); + return -1; + } + + return 0; +} + +static void platform_deinit(void) +{ + ipm_set_enabled(ipm_handle, 0); + metal_finish(); +} + +static void cleanup_system(void) +{ + struct fw_resource_table *rsc_tbl = (struct fw_resource_table *)RSC_TABLE_ADDR; + + rpmsg_deinit_vdev(&rvdev); + rproc_virtio_remove_vdev(rvdev.vdev); + /* + * Clean vdev status in rsc_table because it may not be cleared from + * master end. This is not default work behavior. By default rsc_table + * should be provided and managed by master. + */ + rsc_tbl->vdev.status = 0; +} + +struct rpmsg_device *platform_create_rpmsg_vdev(unsigned int vdev_index, unsigned int role, + void (*rst_cb)(struct virtio_device *vdev), + rpmsg_ns_bind_cb ns_cb) +{ + struct fw_rsc_vdev_vring *vring_rsc; + struct virtio_device *vdev; + int ret; + + vdev = rproc_virtio_create_vdev(VIRTIO_DEV_DEVICE, VDEV_ID, rsc_table_to_vdev(rsc_table), + rsc_io, NULL, mailbox_notify, NULL); + + if (!vdev) { + LOG_ERR("failed to create vdev"); + return NULL; + } + + /* Set gfeatures because they should be equal to dfeatures + * when create_ept is called. As rproc_virtio_create_vdev + * doesn't set them because its VIRTIO_DEVICE not DRIVER. + * Assume the virtio driver support all remote features. + */ + virtio_set_features(vdev, 0x1); + + /* wait master rpmsg init completion */ + rproc_virtio_wait_remote_ready(vdev); + + vring_rsc = rsc_table_get_vring0(rsc_table); + + ret = rproc_virtio_init_vring(vdev, 0, vring_rsc->notifyid, (void *)VRING_TX_ADDR_CM33, + rsc_io, vring_rsc->num, vring_rsc->align); + if (ret) { + LOG_ERR("failed to init vring 0"); + goto failed; + } + + vring_rsc = rsc_table_get_vring1(rsc_table); + + ret = rproc_virtio_init_vring(vdev, 1, vring_rsc->notifyid, (void *)VRING_RX_ADDR_CM33, + rsc_io, vring_rsc->num, vring_rsc->align); + if (ret) { + LOG_ERR("failed to init vring 1"); + goto failed; + } + + rpmsg_virtio_init_shm_pool(&shpool, NULL, SHM_SIZE); + ret = rpmsg_init_vdev(&rvdev, vdev, ns_cb, shm_io, &shpool); + + if (ret) { + LOG_ERR("failed rpmsg_init_vdev"); + goto failed; + } + + return rpmsg_virtio_get_rpmsg_device(&rvdev); + +failed: + rproc_virtio_remove_vdev(vdev); + + return NULL; +} + +void app_rpmsg_client_sample(void *arg1, void *arg2, void *arg3) +{ + ARG_UNUSED(arg1); + ARG_UNUSED(arg2); + ARG_UNUSED(arg3); + unsigned int msg_cnt = 0; + int ret = 0; + + k_sem_take(&data_sc_sem, K_FOREVER); + + LOG_INF("OpenAMP[remote] Linux sample client responder started"); + + ret = rpmsg_create_ept(&sc_ept, rpdev, "rpmsg-service-0", APP_EPT_ADDR, RPMSG_ADDR_ANY, + rpmsg_recv_cs_callback, NULL); + + while (!finish) { + k_sem_take(&data_sc_sem, K_FOREVER); + msg_cnt++; + rpmsg_send(&sc_ept, sc_msg.data, sc_msg.len); + } + + rpmsg_destroy_ept(&sc_ept); + k_sem_reset(&data_sc_sem); + + LOG_INF("OpenAMP Linux sample client responder ended"); +} + +void rpmsg_mng_task(void *arg1, void *arg2, void *arg3) +{ + ARG_UNUSED(arg1); + ARG_UNUSED(arg2); + ARG_UNUSED(arg3); + unsigned char *msg; + unsigned int len; + int ret = 0; + + LOG_INF("OpenAMP[remote] linux responder demo started"); + + /* Initialize platform */ + rpdev = platform_create_rpmsg_vdev(0, VIRTIO_DEV_DEVICE, NULL, new_service_cb); + if (!rpdev) { + LOG_ERR("Failed to create rpmsg virtio device"); + ret = -1; + goto task_end; + } + + /* start the rpmsg clients */ + k_sem_give(&data_sc_sem); + + while (!finish) { + receive_message(&msg, &len); + } + +task_end: + cleanup_system(); + + LOG_INF("OpenAMP demo ended"); +} + +int main(void) +{ + LOG_INF("Starting application..!"); + + /* Initialize platform */ + int ret = platform_init(); + + if (ret) { + LOG_ERR("Failed to initialize platform"); + return -1; + } + + while (1) { + finish = 0; + + LOG_INF("Starting application threads!"); + k_thread_create(&thread_mng_data, thread_mng_stack, APP_TASK_STACK_SIZE, + (k_thread_entry_t)rpmsg_mng_task, NULL, NULL, NULL, K_PRIO_COOP(8), + 0, K_NO_WAIT); + k_thread_create(&thread_rp__client_data, thread_rp__client_stack, + APP_TASK_STACK_SIZE, (k_thread_entry_t)app_rpmsg_client_sample, + NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); + + k_thread_join(&thread_mng_data, K_FOREVER); + k_thread_join(&thread_rp__client_data, K_FOREVER); + } + + platform_deinit(); + return 0; +} diff --git a/samples/subsys/ipc/openamp_rsc_table_rzg3/src/resource_table.c b/samples/subsys/ipc/openamp_rsc_table_rzg3/src/resource_table.c new file mode 100644 index 00000000000000..b1ce613aec4f84 --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table_rzg3/src/resource_table.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Overriding Zephyr resource_table and set correct vring 0 and vring 1 addresses + * to match the work behaviour of master device. According to the commit: + * 25ec73986b (lib: open-amp: add helper to add resource table in project) + * vring RX and TX addresses should be allocated by master processor. + * Current Master Sample implementation expects slave to provide valid + * rsc_table so update vring addresses here. + * + * Dependencies: + * to be compliant with Linux kernel OS the resource table must be linked in a + * specific section named ".resource_table". + */ + +#include +#include + +#define __resource Z_GENERIC_SECTION(.resource_table) + +static struct fw_resource_table __resource resource_table = { + .ver = 1, + .num = RSC_TABLE_NUM_ENTRY, + .offset = { + offsetof(struct fw_resource_table, vdev), + }, + + /* Virtio device entry */ + .vdev = { + RSC_VDEV, + VIRTIO_ID_RPMSG, + 0, + RPMSG_IPU_C0_FEATURES, + 0, + 0, + 0, + VRING_COUNT, + {0, 0}, + }, + + /* Vring rsc entry - part of vdev rsc entry */ + .vring0 = {VRING_TX_ADDR_A55, VRING_ALIGNMENT, RSC_TABLE_NUM_RPMSG_BUFF, VRING0_ID, 0}, + .vring1 = {VRING_RX_ADDR_A55, VRING_ALIGNMENT, RSC_TABLE_NUM_RPMSG_BUFF, VRING1_ID, 0}, +}; + +void rsc_table_get(void **table_ptr, int *length) +{ + *table_ptr = (void *)&resource_table; + *length = sizeof(resource_table); +} diff --git a/samples/subsys/ipc/openamp_rsc_table_rzg3/src/resource_table.h b/samples/subsys/ipc/openamp_rsc_table_rzg3/src/resource_table.h new file mode 100644 index 00000000000000..335461e2a879d4 --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table_rzg3/src/resource_table.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef RESOURCE_TABLE_H__ +#define RESOURCE_TABLE_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define VDEV_ID 0xFF +#define VRING0_ID 0 +#define VRING1_ID 1 + +#define VRING_COUNT 2 +#define RPMSG_IPU_C0_FEATURES 1 + +#define R_VRING_TX DT_NODELABEL(vring_ctrl0) +#define R_VRING_RX DT_NODELABEL(vring_ctrl1) +#define VRING_TX_ADDR_CM33 DT_REG_ADDR(R_VRING_TX) +#define VRING_RX_ADDR_CM33 DT_REG_ADDR(R_VRING_RX) + +#define VRING_TX_ADDR_A55 CM33_TO_A55_ADDR_NS(VRING_TX_ADDR_CM33) +#define VRING_RX_ADDR_A55 CM33_TO_A55_ADDR_NS(VRING_RX_ADDR_CM33) +#define VRING_ALIGNMENT (0x100U) + +#define RSC_TABLE_NUM_RPMSG_BUFF 512 + +enum rsc_table_entries { + RSC_TABLE_VDEV_ENTRY, + RSC_TABLE_NUM_ENTRY +}; + +struct fw_resource_table { + unsigned int ver; + unsigned int num; + unsigned int reserved[2]; + unsigned int offset[RSC_TABLE_NUM_ENTRY]; + + struct fw_rsc_vdev vdev; + struct fw_rsc_vdev_vring vring0; + struct fw_rsc_vdev_vring vring1; +} METAL_PACKED_END; + +void rsc_table_get(void **table_ptr, int *length); + +static inline struct fw_rsc_vdev *rsc_table_to_vdev(void *rsc_table) +{ + return &((struct fw_resource_table *)rsc_table)->vdev; +} + +static inline struct fw_rsc_vdev_vring *rsc_table_get_vring0(void *rsc_table) +{ + return &((struct fw_resource_table *)rsc_table)->vring0; +} + +static inline struct fw_rsc_vdev_vring *rsc_table_get_vring1(void *rsc_table) +{ + return &((struct fw_resource_table *)rsc_table)->vring1; +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/scripts/build/check_init_priorities.py b/scripts/build/check_init_priorities.py index 582d7dd0e88b24..88f7f310040c9c 100755 --- a/scripts/build/check_init_priorities.py +++ b/scripts/build/check_init_priorities.py @@ -286,23 +286,12 @@ def _check_dep(self, dev_ord, dep_ord): self.log.info( f"{dev_node.path} {dev_prio} > {dep_node.path} {dep_prio}") - def _check_edt_r(self, dev_ord, dev): - """Recursively check for dependencies of a device.""" - for dep in dev.depends_on: - self._check_dep(dev_ord, dep.dep_ordinal) - if dev._binding and dev._binding.child_binding: - for child in dev.children.values(): - if "compatible" in child.props: - continue - if dev._binding.path != child._binding.path: - continue - self._check_edt_r(dev_ord, child) - def check_edt(self): """Scan through all known devices and validate the init priorities.""" for dev_ord in self._obj.devices: dev = self._ord2node[dev_ord] - self._check_edt_r(dev_ord, dev) + for dep in dev.depends_on: + self._check_dep(dev_ord, dep.dep_ordinal) def print_initlevels(self): for level, calls in self._obj.initlevels.items(): diff --git a/scripts/build/check_init_priorities_test.py b/scripts/build/check_init_priorities_test.py index 6e4042211942fd..9783e5d828e700 100755 --- a/scripts/build/check_init_priorities_test.py +++ b/scripts/build/check_init_priorities_test.py @@ -381,52 +381,32 @@ def test_check_ignored(self, mock_vinit): @mock.patch("check_init_priorities.Validator._check_dep") @mock.patch("check_init_priorities.Validator.__init__", return_value=None) - def test_check_edt_r(self, mock_vinit, mock_cd): - validator = check_init_priorities.Validator("", "", None) - + def test_check_edt(self, mock_vinit, mock_cd): d0 = mock.Mock() d0.dep_ordinal = 1 d1 = mock.Mock() d1.dep_ordinal = 2 + d2 = mock.Mock() + d2.dep_ordinal = 3 - c0 = mock.Mock() - c0.props = {"compatible": "c"} - c1 = mock.Mock() - c1.props = {} - c1._binding.path = "another-binding-path.yaml" - c2 = mock.Mock() - c2.props = {} - c2._binding.path = "binding-path.yaml" - c2._binding.child_binding = None - c2.depends_on = [d1] - - dev = mock.Mock() - dev.depends_on = [d0] - dev._binding.child_binding = "child-binding" - dev._binding.path = "binding-path.yaml" - dev.children.values.return_value = [c0, c1, c2] - - validator._check_edt_r(0, dev) - - self.assertListEqual(mock_cd.call_args_list, [ - mock.call(0, 1), - mock.call(0, 2), - ]) + dev0 = mock.Mock() + dev0.depends_on = [d0] + dev1 = mock.Mock() + dev1.depends_on = [d1] + dev2 = mock.Mock() + dev2.depends_on = [d2] - @mock.patch("check_init_priorities.Validator._check_edt_r") - @mock.patch("check_init_priorities.Validator.__init__", return_value=None) - def test_check_edt(self, mock_vinit, mock_cer): validator = check_init_priorities.Validator("", "", None) - validator._ord2node = {1: mock.Mock(), 2: mock.Mock(), 3: mock.Mock()} + validator._ord2node = {1: dev0, 2: dev1, 3: dev2} validator._obj = mock.Mock() validator._obj.devices = {1: 10, 2: 10, 3: 20} validator.check_edt() - self.assertListEqual(mock_cer.call_args_list, [ - mock.call(1, validator._ord2node[1]), - mock.call(2, validator._ord2node[2]), - mock.call(3, validator._ord2node[3]), + self.assertListEqual(mock_cd.call_args_list, [ + mock.call(1, 1), + mock.call(2, 2), + mock.call(3, 3), ]) if __name__ == "__main__": diff --git a/scripts/west_commands/runners/jlink.py b/scripts/west_commands/runners/jlink.py index 4fa717206736e6..f18949b0493b7f 100644 --- a/scripts/west_commands/runners/jlink.py +++ b/scripts/west_commands/runners/jlink.py @@ -265,6 +265,8 @@ def do_run(self, command, **kwargs): if command == 'debug': client_cmd += ['-ex', 'monitor halt', '-ex', 'monitor reset', + '-ex', 'shell sleep 1', + '-ex', 'monitor halt', '-ex', 'load'] if self.reset: client_cmd += ['-ex', 'monitor reset'] @@ -281,6 +283,8 @@ def flash(self, **kwargs): lines = [ 'ExitOnError 1', # Treat any command-error as fatal 'r', # Reset and halt the target + 'Sleep 1000', + 'h', ] if self.erase: @@ -318,7 +322,7 @@ def flash(self, **kwargs): else: flash_addr = 0 flash_file = self.bin_name - flash_cmd = f'loadfile "{self.bin_name}" 0x{flash_addr:x}' + flash_cmd = f'loadfile "{self.bin_name}" 0x{flash_addr:x} noreset' else: err = 'Cannot flash; no hex ({}) or bin ({}) files found.' raise ValueError(err.format(self.hex_name, self.bin_name)) @@ -329,7 +333,7 @@ def flash(self, **kwargs): if self.reset: lines.append('r') # Reset and halt the target - lines.append('g') # Start the CPU + lines.append('r') # Start the CPU # Reset the Debug Port CTRL/STAT register # Under normal operation this is done automatically, but if other diff --git a/snippets/rz-g3s-canfd0-test/README.rst b/snippets/rz-g3s-canfd0-test/README.rst new file mode 100644 index 00000000000000..6e87aeb6d98335 --- /dev/null +++ b/snippets/rz-g3s-canfd0-test/README.rst @@ -0,0 +1,14 @@ +.. _snippet-rz-g3s-canfd0-test: + +RZ/G3S CAN-FD CH0 Test +######################################### + +.. code-block:: bash + + west build -p always -b rz_g3s -S rz-g3s-canfd0-test tests/drivers/can/api + +Overview +******** + +This snippet enables RZ/G3S CAN-FD channel 0 functionality on RZ/G3S SMARC Evaluation Board, +so it can be used with CAN tests and samples. diff --git a/snippets/rz-g3s-canfd0-test/rz-g3s-canfd0-test.conf b/snippets/rz-g3s-canfd0-test/rz-g3s-canfd0-test.conf new file mode 100644 index 00000000000000..10bfe8aad9ae1e --- /dev/null +++ b/snippets/rz-g3s-canfd0-test/rz-g3s-canfd0-test.conf @@ -0,0 +1,8 @@ +CONFIG_LOG=y + +CONFIG_CAN=y +CONFIG_CAN_FD_MODE=y +CONFIG_CAN_AUTO_BUS_OFF_RECOVERY=n +CONFIG_STATS=y +CONFIG_CAN_STATS=y +CONFIG_CAN_RX_TIMESTAMP=y diff --git a/snippets/rz-g3s-canfd0-test/rz-g3s-canfd0-test.overlay b/snippets/rz-g3s-canfd0-test/rz-g3s-canfd0-test.overlay new file mode 100644 index 00000000000000..15df40c37918cf --- /dev/null +++ b/snippets/rz-g3s-canfd0-test/rz-g3s-canfd0-test.overlay @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + /* + * The can_led can be used by some CAN samples/test, like "samples/drivers/can/counter". + * On Renesas RZ/G3S SMARC Evaluation Board this snippets configures can_led as: + * P14_2 -> GPIO11 -> GPIO11_PMOD -> PMOD1_GPIO11 + * Use PMOD1_6A connector to connect led to pins 2 and 6 (power 3.3V) + */ + aliases { + led0 = &can_led; + }; + + leds { + compatible = "gpio-leds"; + + can_led: can_led0 { + gpios = <&port14 2 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&canfd { + status = "okay"; +}; + +&canfd0 { + status = "okay"; +}; + +&canfd1 { + status = "okay"; +}; + +&port14 { + status = "okay"; +}; diff --git a/snippets/rz-g3s-canfd0-test/snippet.yml b/snippets/rz-g3s-canfd0-test/snippet.yml new file mode 100644 index 00000000000000..6e02afb4fbd52f --- /dev/null +++ b/snippets/rz-g3s-canfd0-test/snippet.yml @@ -0,0 +1,10 @@ +name: rz-g3s-canfd0-test +boards: + rz_g3s: + append: + EXTRA_DTC_OVERLAY_FILE: rz-g3s-canfd0-test.overlay + EXTRA_CONF_FILE: rz-g3s-canfd0-test.conf + rz_g3s_fpu: + append: + EXTRA_DTC_OVERLAY_FILE: rz-g3s-canfd0-test.overlay + EXTRA_CONF_FILE: rz-g3s-canfd0-test.conf diff --git a/snippets/rz-g3s-canfd1-test/README.rst b/snippets/rz-g3s-canfd1-test/README.rst new file mode 100644 index 00000000000000..8bfc15ea5d2931 --- /dev/null +++ b/snippets/rz-g3s-canfd1-test/README.rst @@ -0,0 +1,14 @@ +.. _snippet-rz-g3s-canfd1-test: + +RZ/G3S CAN-FD CH1 Test +######################################### + +.. code-block:: bash + + west build -p always -b rz_g3s -S rz-g3s-canfd1-test tests/drivers/can/api + +Overview +******** + +This snippet enables RZ/G3S CAN-FD channel 1 functionality on RZ/G3S SMARC Evaluation Board, +so it can be used with CAN tests and samples. diff --git a/snippets/rz-g3s-canfd1-test/rz-g3s-canfd1-test.conf b/snippets/rz-g3s-canfd1-test/rz-g3s-canfd1-test.conf new file mode 100644 index 00000000000000..10bfe8aad9ae1e --- /dev/null +++ b/snippets/rz-g3s-canfd1-test/rz-g3s-canfd1-test.conf @@ -0,0 +1,8 @@ +CONFIG_LOG=y + +CONFIG_CAN=y +CONFIG_CAN_FD_MODE=y +CONFIG_CAN_AUTO_BUS_OFF_RECOVERY=n +CONFIG_STATS=y +CONFIG_CAN_STATS=y +CONFIG_CAN_RX_TIMESTAMP=y diff --git a/snippets/rz-g3s-canfd1-test/rz-g3s-canfd1-test.overlay b/snippets/rz-g3s-canfd1-test/rz-g3s-canfd1-test.overlay new file mode 100644 index 00000000000000..aa7e9e3edcb663 --- /dev/null +++ b/snippets/rz-g3s-canfd1-test/rz-g3s-canfd1-test.overlay @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,canbus = &canfd1; + }; + + /* + * The can_led can be used by some CAN samples/test, like "samples/drivers/can/counter". + * On Renesas RZ/G3S SMARC Evaluation Board this snippets configures can_led as: + * P14_2 -> GPIO11 -> GPIO11_PMOD -> PMOD1_GPIO11 + * Use PMOD1_6A connector to connect led to pins 2 and 6 (power 3.3V) + */ + aliases { + led0 = &can_led; + }; + + leds { + compatible = "gpio-leds"; + + can_led: can_led0 { + gpios = <&port14 2 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&canfd { + status = "okay"; +}; + +&canfd0 { + status = "okay"; +}; + +&canfd1 { + status = "okay"; +}; + +&port14 { + status = "okay"; +}; diff --git a/snippets/rz-g3s-canfd1-test/snippet.yml b/snippets/rz-g3s-canfd1-test/snippet.yml new file mode 100644 index 00000000000000..77ce12b0ba59a9 --- /dev/null +++ b/snippets/rz-g3s-canfd1-test/snippet.yml @@ -0,0 +1,10 @@ +name: rz-g3s-canfd1-test +boards: + rz_g3s: + append: + EXTRA_DTC_OVERLAY_FILE: rz-g3s-canfd1-test.overlay + EXTRA_CONF_FILE: rz-g3s-canfd1-test.conf + rz_g3s_fpu: + append: + EXTRA_DTC_OVERLAY_FILE: rz-g3s-canfd1-test.overlay + EXTRA_CONF_FILE: rz-g3s-canfd1-test.conf diff --git a/snippets/rz-g3s-fpu-scif1/README.rst b/snippets/rz-g3s-fpu-scif1/README.rst new file mode 100644 index 00000000000000..0e255a5ef63b93 --- /dev/null +++ b/snippets/rz-g3s-fpu-scif1/README.rst @@ -0,0 +1,21 @@ +.. _snippet-rz-g3s-fpu-scif1: + +RZ/G3S FPU via SCIF1 +#################### + +.. code-block:: bash + + west build -p always -b rz_g3s_fpu -S rz-g3s-fpu-scif1 + +Overview +******** + +This snippet configures Zephyr to use SCIF1 (PMOD1_3A) for Cortex-M33_FPU core +instead of the SCIF3 (SER1_UART). +This can be helpful for a testing purposes because the default +SCIF3 (SER1_UART) connection requires specific USBUART connector that +support 1.8v. To avoid using specific hardware - CM33_FPU core can be +switched to use SCIF1 (PMOD1_3A) console which works on more common 3.3v. + +Please note that CM33 core should be flashed with :ref:`hello_world` +to avoid side effects. diff --git a/snippets/rz-g3s-fpu-scif1/rz-g3s-fpu-scif1.overlay b/snippets/rz-g3s-fpu-scif1/rz-g3s-fpu-scif1.overlay new file mode 100644 index 00000000000000..d46b68f837f3ab --- /dev/null +++ b/snippets/rz-g3s-fpu-scif1/rz-g3s-fpu-scif1.overlay @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,console = &scif1; + zephyr,shell-uart = &scif1; + }; + +}; +&scif3 { + status = "disabled"; +}; + +&scif1 { + current-speed = <115200>; + pinctrl-0 = <&scif1_pins>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/snippets/rz-g3s-fpu-scif1/snippet.yml b/snippets/rz-g3s-fpu-scif1/snippet.yml new file mode 100644 index 00000000000000..ffe959cfa28b5c --- /dev/null +++ b/snippets/rz-g3s-fpu-scif1/snippet.yml @@ -0,0 +1,5 @@ +name: rz-g3s-fpu-scif1 +boards: + rz_g3s_fpu: + append: + EXTRA_DTC_OVERLAY_FILE: rz-g3s-fpu-scif1.overlay diff --git a/snippets/rz-g3s-gtm-timer-test/README.rst b/snippets/rz-g3s-gtm-timer-test/README.rst new file mode 100644 index 00000000000000..ddf8d93d732dd7 --- /dev/null +++ b/snippets/rz-g3s-gtm-timer-test/README.rst @@ -0,0 +1,14 @@ +.. _snippet-rz-g3s-gtm-timer-test: + +RZ/G3S GTM OS Timer Test +######################################### + +.. code-block:: bash + + west build -p always -b rz_g3s -S rz-g3s-gtm-timer-test tests/kernel/tickless/tickless_concept + +Overview +******** + +This snippet enables RZ/G3S GTM channel 0 functionality on RZ/G3S SMARC Evaluation Board, +so it can be used as Zephyr OS Timer for tests and samples. diff --git a/snippets/rz-g3s-gtm-timer-test/rz-g3s-gtm-timer-test.overlay b/snippets/rz-g3s-gtm-timer-test/rz-g3s-gtm-timer-test.overlay new file mode 100644 index 00000000000000..3b3adb9ed2f11c --- /dev/null +++ b/snippets/rz-g3s-gtm-timer-test/rz-g3s-gtm-timer-test.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +>m0 { + compatible = "renesas,ostm-r9a08g045-timer", "renesas,ostm-timer"; + status = "okay"; +}; + +&systick { + status = "disabled"; +}; diff --git a/snippets/rz-g3s-gtm-timer-test/snippet.yml b/snippets/rz-g3s-gtm-timer-test/snippet.yml new file mode 100644 index 00000000000000..1e93e3ae57a88e --- /dev/null +++ b/snippets/rz-g3s-gtm-timer-test/snippet.yml @@ -0,0 +1,8 @@ +name: rz-g3s-gtm-timer-test +boards: + rz_g3s: + append: + EXTRA_DTC_OVERLAY_FILE: rz-g3s-gtm-timer-test.overlay + rz_g3s_fpu: + append: + EXTRA_DTC_OVERLAY_FILE: rz-g3s-gtm-timer-test.overlay diff --git a/snippets/rz-g3s-i2c-dma/README.rst b/snippets/rz-g3s-i2c-dma/README.rst new file mode 100644 index 00000000000000..063f6c368dd759 --- /dev/null +++ b/snippets/rz-g3s-i2c-dma/README.rst @@ -0,0 +1,13 @@ +.. _snippet-rz-g3s-i2c-dma: + +RZ/G3S I2C DMA test with BME280 sensor(rz-g3s-i2c-dma) +###################################################### + +.. code-block:: console + + west build -p always -b rz_g3s -S rz-g3s-i2c-dma samples/sensor/bme280 + +Overview +******** + +This snippet setup I2C as DMA driven. diff --git a/snippets/rz-g3s-i2c-dma/rz-g3s-i2c-dma.conf b/snippets/rz-g3s-i2c-dma/rz-g3s-i2c-dma.conf new file mode 100644 index 00000000000000..f9ab8080522625 --- /dev/null +++ b/snippets/rz-g3s-i2c-dma/rz-g3s-i2c-dma.conf @@ -0,0 +1 @@ +CONFIG_I2C_RIIC_DMA_DRIVEN=y diff --git a/snippets/rz-g3s-i2c-dma/rz-g3s-i2c-dma.overlay b/snippets/rz-g3s-i2c-dma/rz-g3s-i2c-dma.overlay new file mode 100644 index 00000000000000..b3777827c10d1f --- /dev/null +++ b/snippets/rz-g3s-i2c-dma/rz-g3s-i2c-dma.overlay @@ -0,0 +1,15 @@ +/ { + chosen { + zephyr,i2c = &i2c0; + }; +}; + +&i2c0 { + dmas = <&dma0 6 DMA_RS_I2C_INTRIIC_RI0 0>, <&dma0 5 DMA_RS_I2C_INTRIIC_TI0 0>; + dma-names = "rx", "tx"; +}; + +&dma0 { + status = "okay"; + dma-buf-addr-alignment = <1>; +}; diff --git a/snippets/rz-g3s-i2c-dma/snippet.yml b/snippets/rz-g3s-i2c-dma/snippet.yml new file mode 100644 index 00000000000000..8070ee5b5e6e06 --- /dev/null +++ b/snippets/rz-g3s-i2c-dma/snippet.yml @@ -0,0 +1,10 @@ +name: rz-g3s-i2c-dma +boards: + rz_g3s: + append: + EXTRA_CONF_FILE: rz-g3s-i2c-dma.conf + EXTRA_DTC_OVERLAY_FILE: rz-g3s-i2c-dma.overlay + rz_g3s_fpu: + append: + EXTRA_CONF_FILE: rz-g3s-i2c-dma.conf + EXTRA_DTC_OVERLAY_FILE: rz-g3s-i2c-dma.overlay diff --git a/snippets/rz-g3s-poeg-disa-test/README.rst b/snippets/rz-g3s-poeg-disa-test/README.rst new file mode 100644 index 00000000000000..9b20edca32b374 --- /dev/null +++ b/snippets/rz-g3s-poeg-disa-test/README.rst @@ -0,0 +1,14 @@ +.. _snippet-rz-g3s-poeg-disa-test: + +RZ/G3S CAN-FD CH0 Test +######################################### + +.. code-block:: bash + + west build -p always -b rz_g3s -S rz-g3s-poeg-disa-test tests/drivers/pwm/pwm_ab + +Overview +******** + +This snippet enables RZ/G3S enables Disable request from POEG on to GPT on the +same level of output pins. diff --git a/snippets/rz-g3s-poeg-disa-test/rz-g3s-poeg-disa-test.overlay b/snippets/rz-g3s-poeg-disa-test/rz-g3s-poeg-disa-test.overlay new file mode 100644 index 00000000000000..7e2f734efb88e7 --- /dev/null +++ b/snippets/rz-g3s-poeg-disa-test/rz-g3s-poeg-disa-test.overlay @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + pwm-0 = &gpt32e0_s; + }; +}; + +&gpt32e0_s { + pinctrl-0 = <&gpt0_pins>; + pinctrl-names = "default"; + divider = <16>; + renesas,poeg = "POEGB"; + renesas,poeg-device = <&poegb>; + renesas,disable-requests = ; + status = "okay"; +}; + +&poegb { + pinctrl-0 = <&poegb_pins>; + pinctrl-names = "default"; + status = "okay"; + renesas,invert = <1>; +}; + +&port13 { + status = "okay"; +}; + +&pinctrl { + /omit-if-no-ref/ gpt0_pins: gpt0 { + gpt0-pinmux { + pinmux = , /* GTIOC0A */ + ; /* GTIOC0B */ + }; + }; + + /* P18-1 used as GTETGB */ + /omit-if-no-ref/ poegb_pins: poegb { + poegb-pinmux { + pinmux = ; /* GTETRGB */ + }; + }; +}; diff --git a/snippets/rz-g3s-poeg-disa-test/snippet.yml b/snippets/rz-g3s-poeg-disa-test/snippet.yml new file mode 100644 index 00000000000000..785ac014f56990 --- /dev/null +++ b/snippets/rz-g3s-poeg-disa-test/snippet.yml @@ -0,0 +1,8 @@ +name: rz-g3s-poeg-disa-test +boards: + rz_g3s: + append: + EXTRA_DTC_OVERLAY_FILE: rz-g3s-poeg-disa-test.overlay + rz_g3s_fpu: + append: + EXTRA_DTC_OVERLAY_FILE: rz-g3s-poeg-disa-test.overlay diff --git a/soc/arm/renesas_rz/rz_g/CMakeLists.txt b/soc/arm/renesas_rz/rz_g/CMakeLists.txt new file mode 100644 index 00000000000000..2189d3fb5958d8 --- /dev/null +++ b/soc/arm/renesas_rz/rz_g/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +zephyr_sources(soc.c) + +zephyr_sources_ifdef(CONFIG_ARM_MPU mpu_regions.c) + +zephyr_linker_sources_ifdef(CONFIG_OPENAMP + RODATA + resource_table.ld +) diff --git a/soc/arm/renesas_rz/rz_g/Kconfig.defconfig.r9r08g045 b/soc/arm/renesas_rz/rz_g/Kconfig.defconfig.r9r08g045 new file mode 100644 index 00000000000000..21c749fa0009d2 --- /dev/null +++ b/soc/arm/renesas_rz/rz_g/Kconfig.defconfig.r9r08g045 @@ -0,0 +1,9 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +if SOC_R9A08G045 + +config SOC + default "r9a08g045" + +endif # SOC_R9A08G045 diff --git a/soc/arm/renesas_rz/rz_g/Kconfig.defconfig.series b/soc/arm/renesas_rz/rz_g/Kconfig.defconfig.series new file mode 100644 index 00000000000000..9105cc6abaf78f --- /dev/null +++ b/soc/arm/renesas_rz/rz_g/Kconfig.defconfig.series @@ -0,0 +1,46 @@ +# Renesas RZ G3S SoC line + +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_RZ_G + +config SOC_SERIES + default "rz_g" + +config NUM_IRQS + default 480 if !2ND_LEVEL_INTERRUPTS + default 488 if 2ND_LEVEL_INTERRUPTS + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,/cpus/cpu@0,clock-frequency) + +config FLASH_SIZE + default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_FLASH),0,K) + +config FLASH_BASE_ADDRESS + default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_FLASH)) + +if MULTI_LEVEL_INTERRUPTS + +config 1ST_LEVEL_INTERRUPT_BITS + default 9 + +config MAX_IRQ_PER_AGGREGATOR + default 9 + +config 2ND_LEVEL_INTERRUPTS + default y + +config 2ND_LVL_ISR_TBL_OFFSET + default 480 + +config 2ND_LVL_INTR_00_OFFSET + default 0 + +config NUM_2ND_LEVEL_AGGREGATORS + default 1 + +endif # MULTI_LEVEL_INTERRUPTS + +endif # SOC_SERIES_RZ_G diff --git a/soc/arm/renesas_rz/rz_g/Kconfig.series b/soc/arm/renesas_rz/rz_g/Kconfig.series new file mode 100644 index 00000000000000..5174d7a7c1ca54 --- /dev/null +++ b/soc/arm/renesas_rz/rz_g/Kconfig.series @@ -0,0 +1,32 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_RZ_G + bool "Renesas RZ G3S series based on Cortex M33" + select ARM + select CPU_CORTEX_M33 + select CPU_HAS_ARM_MPU + select SOC_FAMILY_RZ + select CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS + select CPU_HAS_ARM_SAU + help + Enable support for Renesas RZ G SoC series based on Cortex M33 + +if SOC_SERIES_RZ_G + +config NULL_POINTER_EXCEPTION_DETECTION_MPU_RZ_G + bool "Use MPU for null pointer exception detection for RZ G3S SoC" + depends on NULL_POINTER_EXCEPTION_DETECTION_MPU + default y + help + Null pointer dereference detection implemented using MPU functionality as + defined for NULL_POINTER_EXCEPTION_DETECTION_MPU, but taking into account that for RZ G3S + the code section is not started from 0x0 address. In this case, there is no MPU section + mapped for area [0x0, CORTEX_M_NULL_POINTER_EXCEPTION_PAGE_SIZE] and + CONFIG_FLASH_BASE_ADDRESS not started from 0x0. + For RZ G3S SoC the custom section added to the SoC specific MPU regions table which + covers area [0x0, CORTEX_M_NULL_POINTER_EXCEPTION_PAGE_SIZE], then ARM MPU core adds + the same section once more to create MPU section overlap and so provide + null-pointer dereferencing mechanism. + +endif # SOC_SERIES_RZ_G diff --git a/soc/arm/renesas_rz/rz_g/Kconfig.soc b/soc/arm/renesas_rz/rz_g/Kconfig.soc new file mode 100644 index 00000000000000..0d4ede3484f9c1 --- /dev/null +++ b/soc/arm/renesas_rz/rz_g/Kconfig.soc @@ -0,0 +1,11 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +choice + prompt "Renesas RZ G3S SoC Selection" + depends on SOC_SERIES_RZ_G + +config SOC_R9A08G045 + bool "R9A08G045" + +endchoice diff --git a/soc/arm/renesas_rz/rz_g/linker.ld b/soc/arm/renesas_rz/rz_g/linker.ld new file mode 100644 index 00000000000000..d22e9ec33eeb25 --- /dev/null +++ b/soc/arm/renesas_rz/rz_g/linker.ld @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include diff --git a/soc/arm/renesas_rz/rz_g/mpu_regions.c b/soc/arm/renesas_rz/rz_g/mpu_regions.c new file mode 100644 index 00000000000000..ba13b10864ba89 --- /dev/null +++ b/soc/arm/renesas_rz/rz_g/mpu_regions.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +static const struct arm_mpu_region mpu_regions[] = { +#if defined(CONFIG_NULL_POINTER_EXCEPTION_DETECTION_MPU_RZ_G) + MPU_REGION_ENTRY("NULL", 0x0, + REGION_FLASH_ATTR(0x0, CONFIG_CORTEX_M_NULL_POINTER_EXCEPTION_PAGE_SIZE)), +#endif /* CONFIG_NULL_POINTER_EXCEPTION_DETECTION_MPU_RZ_G */ + MPU_REGION_ENTRY("vector", (uintptr_t)_vector_start, + REGION_RAM_TEXT_ATTR((uintptr_t)_vector_end)), + + MPU_REGION_ENTRY("SRAM_TEXT", (uintptr_t)__text_region_start, + REGION_RAM_TEXT_ATTR((uintptr_t)__rodata_region_start)), + + MPU_REGION_ENTRY("SRAM_RODATA", (uintptr_t)__rodata_region_start, + REGION_RAM_RO_ATTR((uintptr_t)__rodata_region_end)), + + MPU_REGION_ENTRY("SRAM_DATA", (uintptr_t)__rom_region_end, + REGION_RAM_ATTR_NO_EXEC((uintptr_t)__kernel_ram_end)), + +#if defined(CONFIG_MPU_DISABLE_BACKGROUND_MAP) +#define DEVICE_REGION_START 0x40000000UL +#define DEVICE_REGION_END 0x5FFFFFFFUL + MPU_REGION_ENTRY("DEVICE", DEVICE_REGION_START, REGION_DEVICE_ATTR(DEVICE_REGION_END)), +#endif /* CONFIG_MPU_DISABLE_BACKGROUND_MAP */ +}; + +const struct arm_mpu_config mpu_config = { + .num_regions = ARRAY_SIZE(mpu_regions), + .mpu_regions = mpu_regions, +}; diff --git a/soc/arm/renesas_rz/rz_g/pinctrl_soc.h b/soc/arm/renesas_rz/rz_g/pinctrl_soc.h new file mode 100644 index 00000000000000..13d55ed3d140af --- /dev/null +++ b/soc/arm/renesas_rz/rz_g/pinctrl_soc.h @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_ARM_RENESAS_RZG_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_RENESAS_RZG_PINCTRL_SOC_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + PINCTRL_RZG3S_TYPE_PINMUX = 0, + PINCTRL_RZG3S_TYPE_SPIN, + PINCTRL_RZG3S_TYPE_GRP, +}; + +enum { + PINCTRL_RZG3S_ETH0_GRP = 0, + PINCTRL_RZG3S_ETH1_GRP, + PINCTRL_RZG3S_SD_CH0_GRP, + PINCTRL_RZG3S_SD_CH1_GRP, + PINCTRL_RZG3S_XSPI_GRP, + PINCTRL_RZG3S_I3C_GRP, + PINCTRL_RZG3S_GRP_LAST, +}; + +enum { + PINCTRL_RZG3S_NMI_SPIN = 0, + PINCTRL_RZG3S_TMS_SWDIO_SPIN, + PINCTRL_RZG3S_TDO_SPIN, + PINCTRL_RZG3S_XSPI_SPCLK_SPIN, + PINCTRL_RZG3S_XSPI_RESET_SPIN, + PINCTRL_RZG3S_XSPI_WP_SPIN, + PINCTRL_RZG3S_XSPI_DS_SPIN, + PINCTRL_RZG3S_XSPI_CS0_SPIN, + PINCTRL_RZG3S_XSPI_CS1_SPIN, + PINCTRL_RZG3S_XSPI_IO0_SPIN, + PINCTRL_RZG3S_XSPI_IO1_SPIN, + PINCTRL_RZG3S_XSPI_IO2_SPIN, + PINCTRL_RZG3S_XSPI_IO3_SPIN, + PINCTRL_RZG3S_XSPI_IO4_SPIN, + PINCTRL_RZG3S_XSPI_IO5_SPIN, + PINCTRL_RZG3S_XSPI_IO6_SPIN, + PINCTRL_RZG3S_XSPI_IO7_SPIN, + PINCTRL_RZG3S_WDTOVF_PERROUT_SPIN, + PINCTRL_RZG3S_SD0_CLK_SPIN, + PINCTRL_RZG3S_SD0_CMD_SPIN, + PINCTRL_RZG3S_SD0_RST_SPIN, + PINCTRL_RZG3S_SD0_DATA0_SPIN, + PINCTRL_RZG3S_SD0_DATA1_SPIN, + PINCTRL_RZG3S_SD0_DATA2_SPIN, + PINCTRL_RZG3S_SD0_DATA3_SPIN, + PINCTRL_RZG3S_SD0_DATA4_SPIN, + PINCTRL_RZG3S_SD0_DATA5_SPIN, + PINCTRL_RZG3S_SD0_DATA6_SPIN, + PINCTRL_RZG3S_SD0_DATA7_SPIN, + PINCTRL_RZG3S_SD1_CLK_SPIN, + PINCTRL_RZG3S_SD1_CMD_SPIN, + PINCTRL_RZG3S_SD1_DATA0_SPIN, + PINCTRL_RZG3S_SD1_DATA1_SPIN, + PINCTRL_RZG3S_SD1_DATA2_SPIN, + PINCTRL_RZG3S_SD1_DATA3_SPIN, + PINCTRL_RZG3S_AUDIO_CLK1_SPIN, + PINCTRL_RZG3S_AUDIO_CLK2_SPIN, + PINCTRL_RZG3S_I3C_SDA_SPIN, + PINCTRL_RZG3S_I3C_SCL_SPIN, + PINCTRL_RZG3S_SD2_CMD_SPIN, + PINCTRL_RZG3S_SD2_DATA0_SPIN, + PINCTRL_RZG3S_SD2_DATA1_SPIN, + PINCTRL_RZG3S_SD2_DATA2_SPIN, + PINCTRL_RZG3S_SD2_DATA3_SPIN, + PINCTRL_RZG3S_ET0_TXC_TX_CLK_SPIN, + PINCTRL_RZG3S_ET1_TXC_TX_CLK_SPIN, + PINCTRL_RZG3S_ET0_TX_CTL_TX_EN_SPIN, + PINCTRL_RZG3S_ET1_TX_CTL_TX_EN_SPIN, + PINCTRL_RZG3S_SPIN_LAST, +}; + +#define PINCTRL_RZG3S_ETH0_GRP_PWR_3300 0 +#define PINCTRL_RZG3S_ETH0_GRP_PWR_1800 1 +#define PINCTRL_RZG3S_ETH0_GRP_PWR_2500 2 +#define PINCTRL_RZG3S_ETH1_GRP_PWR_3300 0 +#define PINCTRL_RZG3S_ETH1_GRP_PWR_1800 1 +#define PINCTRL_RZG3S_ETH1_GRP_PWR_2500 2 + +#define PINCTRL_RZG3S_SD_CH0_GRP_PWR_3300 0 +#define PINCTRL_RZG3S_SD_CH0_GRP_PWR_1800 1 +#define PINCTRL_RZG3S_SD_CH1_GRP_PWR_3300 0 +#define PINCTRL_RZG3S_SD_CH1_GRP_PWR_1800 1 + +#define PINCTRL_RZG3S_XSPI_GRP_PWR_3300 0 +#define PINCTRL_RZG3S_XSPI_GRP_PWR_1800 1 +#define PINCTRL_RZG3S_XSPI_GRP_PWR_2500 2 + +#define PINCTRL_RZG3S_I3C_GRP_PWR_1800 0 +#define PINCTRL_RZG3S_I3C_GRP_PWR_1200 1 + +/* pinmux configuration */ +struct pinctrl_soc_rzg3s_pinmux { + uint8_t port; + uint8_t pin; + uint8_t func; + uint8_t pull_down:1; + uint8_t pull_up:1; + uint8_t pull_pin_default:1; + uint8_t drive_strength:1; + uint8_t drive_strength_microamp:2; + uint8_t filonoff:1; + uint8_t filnum:2; + uint8_t filclksel:2; +}; + +/* Special Purpose pins configuration */ +struct pinctrl_soc_rzg3s_spin { + uint8_t spin; + uint8_t input_enable:1; + uint8_t input_disable:1; + uint8_t output_enable:1; + uint8_t drive_strength:1; + uint8_t drive_strength_microamp:2; + uint8_t filonoff:1; + uint8_t filnum:2; + uint8_t filclksel:2; +}; + +/* Pins group configuration */ +struct pinctrl_soc_rzg3s_grp { + uint8_t grp; + uint8_t f_power_source; + uint8_t power_source:3; + uint8_t bias_high_impedance:1; + uint8_t bias_disable:1; + uint8_t low_power_enable:1; + uint8_t low_power_disable:1; +}; + +typedef struct pinctrl_soc_pin { + uint8_t type; + union { + struct pinctrl_soc_rzg3s_pinmux pinmux; + struct pinctrl_soc_rzg3s_spin spin; + struct pinctrl_soc_rzg3s_grp grp; + }; +} pinctrl_soc_pin_t; + +/* Iterate over each pinctrl-n phandle child */ +#define Z_PINCTRL_STATE_PINS_INIT1(node_id, state_prop, idx) \ + DT_FOREACH_CHILD(DT_PHANDLE_BY_IDX(node_id, state_prop, idx), \ + Z_PINCTRL_STATE_PIN_CHILD_INIT) + +/* Iterate over each pinctrl-n phandle child */ +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + {DT_FOREACH_PROP_ELEM_SEP(node_id, prop, Z_PINCTRL_STATE_PINS_INIT1, ())}; + +/* + * If child has groups property: + * - Iterate over each pin in group and populate pinctrl_soc_pin_t + * If child has pins property: + * - Iterate over each pin in pins and populate pinctrl_soc_pin_t + */ +#define Z_PINCTRL_STATE_PIN_CHILD_INIT(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, pinmux), \ + (DT_FOREACH_PROP_ELEM(node_id, pinmux, Z_PINCTRL_STATE_PIN_CHILD_PINMUX_INIT)),\ + ()) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, groups), \ + (Z_PINCTRL_STATE_PIN_CHILD_GROUP_INIT(node_id, groups)), ()) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, pins), \ + (DT_FOREACH_PROP_ELEM(node_id, pins, Z_PINCTRL_STATE_PIN_CHILD_SPIN_INIT)), \ + ()) + +#define RZG_PIN_NUM_IN_PORT 8 + +/* + * Use 16 lower bits [15:0] for pin identifier + * Use 16 higher bits [31:16] for pin mux function + */ +#define MUX_PIN_ID_MASK GENMASK(15, 0) +#define MUX_FUNC_MASK GENMASK(31, 16) +#define MUX_FUNC_OFFS 16 +#define RZG_FUNC(prop) (((prop) & MUX_FUNC_MASK) >> MUX_FUNC_OFFS) +#define RZG_PINCODE(prop) ((prop) & MUX_PIN_ID_MASK) +#define RZG_PORT(prop) ((RZG_PINCODE(prop)) / RZG_PIN_NUM_IN_PORT) +#define RZG_PIN(prop) ((RZG_PINCODE(prop)) % RZG_PIN_NUM_IN_PORT) + +#define Z_PINCTRL_RZG3S_HAS_IOLH(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, drive_strength_microamp), (1), (0)) + +#define Z_PINCTRL_RZG3S_GET_IOLH(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, drive_strength_microamp), \ + (DT_PROP(node_id, drive_strength_microamp)), (0)) + +/* Digital Noise Filter macro */ +#define RZG_FILTER_NUM_SHIFT 0x0 +#define RZG_FILTER_NUM_MASK (0x3 << RZG_FILTER_NUM_SHIFT) +#define RZG_FILTER_NUM_GET(val) (((val) & RZG_FILTER_NUM_MASK) >> RZG_FILTER_NUM_SHIFT) + +#define RZG_FILTER_CLK_SHIFT 0x2 +#define RZG_FILTER_CLK_MASK (0x3 << RZG_FILTER_CLK_SHIFT) +#define RZG_FILTER_CLK_GET(val) (((val) & RZG_FILTER_CLK_MASK) >> RZG_FILTER_CLK_SHIFT) + +#define Z_PINCTRL_RZG3S_HAS_FILTER(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, input_debounce), (1), (0)) + +#define Z_PINCTRL_RZG3S_GET_FILTER_NUM(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, input_debounce), \ + (RZG_FILTER_NUM_GET(DT_PROP(node_id, input_debounce))), (0)) + +#define Z_PINCTRL_RZG3S_GET_FILTER_CLK(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, input_debounce), \ + (RZG_FILTER_CLK_GET(DT_PROP(node_id, input_debounce))), (0)) + +/* Process pinmux cfg */ +#define Z_PINCTRL_STATE_PIN_CHILD_PINMUX_INIT(node_id, state_prop, idx) \ + { \ + .type = PINCTRL_RZG3S_TYPE_PINMUX, \ + .pinmux = { \ + .port = RZG_PORT(DT_PROP_BY_IDX(node_id, state_prop, idx)), \ + .pin = RZG_PIN(DT_PROP_BY_IDX(node_id, state_prop, idx)), \ + .func = RZG_FUNC(DT_PROP_BY_IDX(node_id, state_prop, idx)), \ + .pull_down = DT_PROP(node_id, bias_pull_down), \ + .pull_up = DT_PROP(node_id, bias_pull_up), \ + .pull_pin_default = DT_PROP(node_id, bias_pull_pin_default), \ + .drive_strength = Z_PINCTRL_RZG3S_HAS_IOLH(node_id), \ + .drive_strength_microamp = Z_PINCTRL_RZG3S_GET_IOLH(node_id), \ + .filonoff = Z_PINCTRL_RZG3S_HAS_FILTER(node_id), \ + .filnum = Z_PINCTRL_RZG3S_GET_FILTER_NUM(node_id), \ + .filclksel = Z_PINCTRL_RZG3S_GET_FILTER_CLK(node_id), \ + }, \ + }, + +#define Z_PINCTRL_GRP_HAS_PWR(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, power_source), (1), (0)) + +#define Z_PINCTRL_PWR(node_id, prop) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, power_source), \ + (UTIL_CAT(UTIL_CAT(UTIL_CAT(PINCTRL_RZG3S_, \ + DT_STRING_UPPER_TOKEN(node_id, prop)), \ + _GRP_PWR_), \ + DT_PROP(node_id, power_source))), \ + ()) + +/* Process each group using PINCTRL_RZG3S_x_GRP macros defined above */ +#define Z_PINCTRL_STATE_PIN_CHILD_GROUP_INIT(node_id, prop) \ + { \ + .type = PINCTRL_RZG3S_TYPE_GRP, \ + .grp = { \ + .grp = UTIL_CAT(PINCTRL_RZG3S_, \ + UTIL_CAT(DT_STRING_UPPER_TOKEN(node_id, prop), _GRP)),\ + .f_power_source = Z_PINCTRL_GRP_HAS_PWR(node_id), \ + .power_source = Z_PINCTRL_PWR(node_id, prop), \ + .bias_disable = DT_PROP(node_id, bias_disable), \ + .bias_high_impedance = DT_PROP(node_id, bias_high_impedance), \ + .low_power_enable = DT_PROP(node_id, low_power_enable), \ + .low_power_disable = DT_PROP(node_id, low_power_disable), \ + }, \ + }, + +/* Process each special pin in pins using PINCTRL_RZG3S_x_SPIN macros defined above */ +#define Z_PINCTRL_STATE_PIN_CHILD_SPIN_INIT(node_id, prop, idx) \ + { \ + .type = PINCTRL_RZG3S_TYPE_SPIN, \ + .spin = { \ + .spin = UTIL_CAT(PINCTRL_RZG3S_, \ + UTIL_CAT(DT_STRING_UPPER_TOKEN_BY_IDX(node_id, prop, idx),\ + _SPIN)),\ + .input_enable = DT_PROP(node_id, input_enable), \ + .input_disable = DT_PROP(node_id, input_disable), \ + .output_enable = DT_PROP(node_id, output_enable), \ + .drive_strength = Z_PINCTRL_RZG3S_HAS_IOLH(node_id), \ + .drive_strength_microamp = Z_PINCTRL_RZG3S_GET_IOLH(node_id), \ + .filonoff = Z_PINCTRL_RZG3S_HAS_FILTER(node_id), \ + .filnum = Z_PINCTRL_RZG3S_GET_FILTER_NUM(node_id), \ + .filclksel = Z_PINCTRL_RZG3S_GET_FILTER_CLK(node_id), \ + }, \ + }, + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_ARM_RENESAS_RZG_PINCTRL_SOC_H_ */ diff --git a/soc/arm/renesas_rz/rz_g/resource_table.ld b/soc/arm/renesas_rz/rz_g/resource_table.ld new file mode 100644 index 00000000000000..60e4fd0e596073 --- /dev/null +++ b/soc/arm/renesas_rz/rz_g/resource_table.ld @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +KEEP(*(.resource_table*)) diff --git a/soc/arm/renesas_rz/rz_g/soc.c b/soc/arm/renesas_rz/rz_g/soc.c new file mode 100644 index 00000000000000..3a75488226eada --- /dev/null +++ b/soc/arm/renesas_rz/rz_g/soc.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2024 EPAM Systems + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include "soc.h" + +#ifdef CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER + +#define NUM_IRQS_PER_REG 32 +#define REG_FROM_IRQ(irq) ((irq) / NUM_IRQS_PER_REG) +#define BIT_FROM_IRQ(irq) ((irq) % NUM_IRQS_PER_REG) + +void z_soc_irq_enable(unsigned int irq) +{ + const struct device *lvl2_intc; + + switch (irq_get_level(irq)) { + case 1: + NVIC_EnableIRQ((IRQn_Type)irq); + break; + case 2: + lvl2_intc = DEVICE_DT_GET(DT_INST(0, renesas_r9a08g045_intc)); + irq_enable_next_level(lvl2_intc, irq); + break; + default: + break; + } +} + +void z_soc_irq_disable(unsigned int irq) +{ + const struct device *lvl2_intc; + + switch (irq_get_level(irq)) { + case 1: + NVIC_DisableIRQ((IRQn_Type)irq); + break; + case 2: + lvl2_intc = DEVICE_DT_GET(DT_INST(0, renesas_r9a08g045_intc)); + irq_disable_next_level(lvl2_intc, irq); + break; + default: + break; + } +} + +int z_soc_irq_is_enabled(unsigned int irq) +{ + const struct device *lvl2_intc; + + switch (irq_get_level(irq)) { + case 1: + return NVIC->ISER[REG_FROM_IRQ(irq)] & BIT(BIT_FROM_IRQ(irq)); + case 2: + lvl2_intc = DEVICE_DT_GET(DT_INST(0, renesas_r9a08g045_intc)); + return irq_line_is_enabled_next_level(lvl2_intc, irq); + default: + break; + } + + return 0; +} + +static void z_arm_nvic_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) +{ + /* The kernel may reserve some of the highest priority levels. + * So we offset the requested priority level with the number + * of priority levels reserved by the kernel. + */ + + /* If we have zero latency interrupts, those interrupts will + * run at a priority level which is not masked by irq_lock(). + * Our policy is to express priority levels with special properties + * via flags + */ + if (IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) && (flags & IRQ_ZERO_LATENCY)) { + if (ZERO_LATENCY_LEVELS == 1) { + prio = _EXC_ZERO_LATENCY_IRQS_PRIO; + } else { + /* Use caller supplied prio level as-is */ + } + } else { + prio += _IRQ_PRIO_OFFSET; + } + + /* The last priority level is also used by PendSV exception, but + * allow other interrupts to use the same level, even if it ends up + * affecting performance (can still be useful on systems with a + * reduced set of priorities, like Cortex-M0/M0+). + */ + __ASSERT(prio <= (BIT(NUM_IRQ_PRIO_BITS) - 1), + "invalid priority %d for %d irq! values must be less than %lu\n", + prio - _IRQ_PRIO_OFFSET, irq, + BIT(NUM_IRQ_PRIO_BITS) - (_IRQ_PRIO_OFFSET)); + NVIC_SetPriority((IRQn_Type)irq, prio); +} + +void z_soc_irq_priority_set(unsigned int irq, unsigned int prio, unsigned int flags) +{ + const struct device *lvl2_intc; + + switch (irq_get_level(irq)) { + case 1: + z_arm_nvic_irq_priority_set(irq, prio, flags); + break; + case 2: + lvl2_intc = DEVICE_DT_GET(DT_INST(0, renesas_r9a08g045_intc)); + irq_set_priority_next_level(lvl2_intc, irq, prio, flags); + break; + default: + break; + } +} + +#endif /* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + +static int soc_rz_init(void) +{ + return 0; +} + +SYS_INIT(soc_rz_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); + +/* Platform-specific early initialization */ +void z_arm_platform_init(void) {} diff --git a/soc/arm/renesas_rz/rz_g/soc.h b/soc/arm/renesas_rz/rz_g/soc.h new file mode 100644 index 00000000000000..c989fe36a47df2 --- /dev/null +++ b/soc/arm/renesas_rz/rz_g/soc.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#ifndef _SOC__H_ +#define _SOC__H_ + +#ifndef _ASMLANGUAGE + +/* __CM33_REV 0x0004U Core revision r0p4 + * M33 core0 - no FPU, M33 core1 - with FPU + */ +#define __SAUREGION_PRESENT CONFIG_CPU_HAS_ARM_SAU +#define __VTOR_PRESENT CONFIG_CPU_CORTEX_M_HAS_VTOR +#define __MPU_PRESENT CONFIG_CPU_HAS_ARM_MPU +#define __FPU_PRESENT CONFIG_CPU_HAS_FPU /* FPU present */ +#define __DSP_PRESENT CONFIG_ARMV8_M_DSP /* DSP ext present - no */ +#define __DCACHE_PRESENT CONFIG_CPU_HAS_DCACHE /* DCACHE present - no */ +#define __ICACHE_PRESENT CONFIG_CPU_HAS_ICACHE /* ICACHE present - no */ + +/* + * Macro to convert across CM33/CM33_FPU and A55 address spaces + * This macro are designed to convert CM33 addresses to A55 addresses + * in secure and non-secure space. According to Table 5.2 of HW Manual. + */ +#define CM33_ADDRESS_OFFSET_SECURE (0x30000000) +#define CM33_ADDRESS_OFFSET_NONSECURE (0x20000000) +#define CM33_TO_A55_ADDR_S(x) ((x)-CM33_ADDRESS_OFFSET_SECURE) +#define CM33_TO_A55_ADDR_NS(x) ((x)-CM33_ADDRESS_OFFSET_NONSECURE) + +#endif /* !_ASMLANGUAGE */ + +#endif /* _SOC__H_ */ diff --git a/tests/drivers/adc/adc_api/boards/rz_g3s.overlay b/tests/drivers/adc/adc_api/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..dd2770d9c6e312 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/rz_g3s.overlay @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + io-channels = <&adc 0>, <&adc 1>, <&adc 8>; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + /* ADC_CH0 */ + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + /* ADC_CH1 */ + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + /* TSU */ + channel@8 { + reg = <8>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/tests/drivers/adc/adc_api/boards/rz_g3s_fpu.overlay b/tests/drivers/adc/adc_api/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..dd2770d9c6e312 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/rz_g3s_fpu.overlay @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + io-channels = <&adc 0>, <&adc 1>, <&adc 8>; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + /* ADC_CH0 */ + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + /* ADC_CH1 */ + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + /* TSU */ + channel@8 { + reg = <8>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/tests/drivers/can/api/src/canfd.c b/tests/drivers/can/api/src/canfd.c index 4fde63a36ae8eb..3b69b0454c86c8 100644 --- a/tests/drivers/can/api/src/canfd.c +++ b/tests/drivers/can/api/src/canfd.c @@ -393,7 +393,7 @@ ZTEST_USER(canfd, test_set_timing_data_while_started) int err; err = can_calc_timing_data(can_dev, &timing, TEST_BITRATE_3, TEST_SAMPLE_POINT); - zassert_ok(err, "failed to calculate data timing (err %d)", err); + zassert_true(err >= 0, "failed to calculate data timing (err %d)", err); err = can_set_timing_data(can_dev, &timing); zassert_not_equal(err, 0, "changed data timing while started"); diff --git a/tests/drivers/can/api/testcase.yaml b/tests/drivers/can/api/testcase.yaml index f24a25c15a379d..205a0dcde98f16 100644 --- a/tests/drivers/can/api/testcase.yaml +++ b/tests/drivers/can/api/testcase.yaml @@ -18,3 +18,11 @@ tests: - esp32s2_saola - esp32s3_devkitm - xiao_esp32s3 + drivers.can.api.rz_g3s: + tags: + - drivers + - can + depends_on: can + extra_args: SNIPPET="rz-g3s-canfd0-test" + platform_allow: + - rz_g3s diff --git a/tests/drivers/can/timing/testcase.yaml b/tests/drivers/can/timing/testcase.yaml index 84706b1298c911..041b25408d4a95 100644 --- a/tests/drivers/can/timing/testcase.yaml +++ b/tests/drivers/can/timing/testcase.yaml @@ -5,3 +5,11 @@ tests: - can depends_on: can filter: dt_chosen_enabled("zephyr,canbus") + drivers.can.timing.rz_g3s: + tags: + - drivers + - can + depends_on: can + extra_args: SNIPPET="rz-g3s-canfd0-test" + platform_allow: + - rz_g3s diff --git a/tests/drivers/counter/counter_basic_api/boards/rz_a2m.overlay b/tests/drivers/counter/counter_basic_api/boards/rz_a2m.overlay new file mode 100644 index 00000000000000..5304903dbb5dd0 --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/rz_a2m.overlay @@ -0,0 +1,3 @@ +&ostm2 { + status = "okay"; +}; diff --git a/tests/drivers/counter/counter_basic_api/boards/rz_g3s.overlay b/tests/drivers/counter/counter_basic_api/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..c7df0565539fc5 --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/rz_g3s.overlay @@ -0,0 +1,31 @@ +>m0 { + status = "okay"; +}; + +>m1 { + status = "okay"; +}; + +>m2 { + status = "okay"; +}; + +>m3 { + status = "okay"; +}; + +>m4 { + status = "okay"; +}; + +>m5 { + status = "okay"; +}; + +>m6 { + status = "okay"; +}; + +>m7 { + status = "okay"; +}; diff --git a/tests/drivers/counter/counter_basic_api/boards/rz_g3s_fpu.overlay b/tests/drivers/counter/counter_basic_api/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..c7df0565539fc5 --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/rz_g3s_fpu.overlay @@ -0,0 +1,31 @@ +>m0 { + status = "okay"; +}; + +>m1 { + status = "okay"; +}; + +>m2 { + status = "okay"; +}; + +>m3 { + status = "okay"; +}; + +>m4 { + status = "okay"; +}; + +>m5 { + status = "okay"; +}; + +>m6 { + status = "okay"; +}; + +>m7 { + status = "okay"; +}; diff --git a/tests/drivers/counter/counter_basic_api/src/test_counter.c b/tests/drivers/counter/counter_basic_api/src/test_counter.c index 462de26d03750c..f5e5e71fe24f06 100644 --- a/tests/drivers/counter/counter_basic_api/src/test_counter.c +++ b/tests/drivers/counter/counter_basic_api/src/test_counter.c @@ -96,6 +96,7 @@ static const struct device *const devices[] = { #ifdef CONFIG_COUNTER_TIMER_RPI_PICO DEVS_FOR_DT_COMPAT(raspberrypi_pico_timer) #endif + DEVS_FOR_DT_COMPAT(renesas_ostm) }; static const struct device *const period_devs[] = { @@ -112,6 +113,10 @@ typedef void (*counter_test_func_t)(const struct device *dev); typedef bool (*counter_capability_func_t)(const struct device *dev); +static void alarm_handler(const struct device *dev, uint8_t chan_id, + uint32_t counter, + void *user_data); + static inline uint32_t get_counter_period_us(const struct device *dev) { for (int i = 0; i < ARRAY_SIZE(period_devs); i++) { @@ -265,6 +270,163 @@ ZTEST(counter_basic, test_set_top_value_with_alarm) set_top_value_capable); } +static void test_set_top_before_start_with_callback(const struct device *dev) +{ + int err; + uint32_t counter_period_us; + uint32_t top_handler_cnt; + struct counter_top_cfg top_cfg = { + .callback = top_handler, .user_data = exp_user_data, .flags = 0}; + + k_sem_reset(&top_cnt_sem); + top_cnt = 0; + + counter_period_us = get_counter_period_us(dev); + top_cfg.ticks = counter_us_to_ticks(dev, counter_period_us); + + err = counter_set_top_value(dev, &top_cfg); + zassert_equal(0, err, "%s: Counter failed to set top value (err: %d)", dev->name, err); + + err = counter_start(dev); + zassert_equal(0, err, "%s: Counter failed to start", dev->name); + + k_busy_wait(5.2 * counter_period_us); + + top_handler_cnt = + IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ? top_cnt : k_sem_count_get(&top_cnt_sem); + zassert_true(top_handler_cnt == 5U, "%s: Unexpected number of turnarounds (%d).", dev->name, + top_handler_cnt); +} + +ZTEST(counter_basic, test_set_top_before_start_with_callback) +{ + test_all_instances(test_set_top_before_start_with_callback, + set_top_value_capable); +} + +static void test_set_top_before_start_switch_freerun(const struct device *dev) +{ + int err; + uint32_t cnt; + uint32_t ticks; + uint32_t counter_period_us; + uint32_t top_handler_cnt; + struct counter_top_cfg top_cfg = { + .callback = top_handler, .user_data = exp_user_data, .flags = 0}; + + cntr_alarm_cfg.flags = 0; + cntr_alarm_cfg.callback = alarm_handler; + cntr_alarm_cfg.user_data = &cntr_alarm_cfg; + cntr_alarm_cfg.ticks = 0; + k_sem_reset(&top_cnt_sem); + top_cnt = 0; + k_sem_reset(&alarm_cnt_sem); + alarm_cnt = 0; + + counter_period_us = get_counter_period_us(dev); + ticks = counter_us_to_ticks(dev, counter_period_us); + top_cfg.ticks = ticks; + + err = counter_set_top_value(dev, &top_cfg); + zassert_equal(0, err, "%s: Counter failed to set top value (err: %d)", dev->name, err); + + err = counter_start(dev); + zassert_equal(0, err, "%s: Counter failed to start", dev->name); + + err = counter_set_channel_alarm(dev, 0, &cntr_alarm_cfg); + zassert_equal(-ENOTSUP, err, "%s: Counter alarm can't be set (err: %d)", dev->name, err); + + k_busy_wait(5.2 * counter_period_us); + + top_handler_cnt = + IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ? top_cnt : k_sem_count_get(&top_cnt_sem); + zassert_true(top_handler_cnt == 5U, "%s: Unexpected number of turnarounds (%d).", dev->name, + top_handler_cnt); + + top_cfg.ticks = counter_get_max_top_value(dev); + top_cfg.callback = NULL; + top_cfg.user_data = NULL; + err = counter_set_top_value(dev, &top_cfg); + zassert_true((err == 0) || (err == -ENOTSUP), "%s: Setting top value to default failed", + dev->name); + + if (counter_get_num_of_channels(dev) < 1U) { + /* Counter does not support any alarm */ + return; + } + + cntr_alarm_cfg.ticks = ticks; + err = counter_set_channel_alarm(dev, 0, &cntr_alarm_cfg); + zassert_equal(0, err, "%s: Counter set alarm failed (err: %d)", dev->name, err); + + k_busy_wait(2 * (uint32_t)counter_ticks_to_us(dev, ticks)); + + cnt = IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ? alarm_cnt : k_sem_count_get(&alarm_cnt_sem); + zassert_equal(1, cnt, "%s: Expecting alarm callback", dev->name); +} + +ZTEST(counter_basic, test_set_top_before_start_with_alarm) +{ + test_all_instances(test_set_top_before_start_switch_freerun, + set_top_value_capable); +} + +static void test_set_top_with_callback_two_times(const struct device *dev) +{ + int err; + uint32_t counter_period_us; + uint32_t top_handler_cnt; + struct counter_top_cfg top_cfg = { + .callback = top_handler, .user_data = exp_user_data, .flags = 0}; + + k_sem_reset(&top_cnt_sem); + top_cnt = 0; + + counter_period_us = get_counter_period_us(dev); + top_cfg.ticks = counter_us_to_ticks(dev, counter_period_us); + + err = counter_set_top_value(dev, &top_cfg); + zassert_equal(0, err, "%s: Counter failed to set top value:%u (err: %d)", top_cfg.ticks, + dev->name, err); + + err = counter_start(dev); + zassert_equal(0, err, "%s: Counter failed to start", dev->name); + + k_busy_wait(5.2 * counter_period_us); + + top_handler_cnt = + IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ? top_cnt : k_sem_count_get(&top_cnt_sem); + zassert_true(top_handler_cnt == 5U, "%s: Unexpected number of turnarounds (%d).", dev->name, + top_handler_cnt); + + top_cfg.ticks = top_cfg.ticks * 2; + err = counter_set_top_value(dev, &top_cfg); + zassert_equal(0, err, "%s: Counter failed to set top value:%u (err: %d)", top_cfg.ticks, + dev->name, err); + + k_busy_wait(6.2 * counter_period_us); + top_handler_cnt = + IS_ENABLED(CONFIG_ZERO_LATENCY_IRQS) ? top_cnt : k_sem_count_get(&top_cnt_sem); + zassert_true(top_handler_cnt == 8U, "%s: Unexpected number of turnarounds (%d).", dev->name, + top_handler_cnt); + + top_cfg.callback = NULL; + err = counter_set_top_value(dev, &top_cfg); + zassert_equal(0, err, "%s: Counter failed to set top value:%u (err: %d)", top_cfg.ticks, + dev->name, err); + top_cfg.ticks = top_cfg.ticks / 2; + top_cfg.flags = COUNTER_TOP_CFG_RESET_WHEN_LATE | COUNTER_TOP_CFG_DONT_RESET; + err = counter_set_top_value(dev, &top_cfg); + zassert_equal(-ETIME, err, "%s: Counter failed to set top value:%u (err: %d)", + top_cfg.ticks, dev->name, err); +} + +ZTEST(counter_basic, test_set_top_with_callback_two_times) +{ + test_all_instances(test_set_top_with_callback_two_times, + set_top_value_capable); +} + static void test_set_top_value_without_alarm_instance(const struct device *dev) { int err; @@ -454,8 +616,13 @@ static bool single_channel_alarm_capable(const struct device *dev) static bool single_channel_alarm_and_custom_top_capable(const struct device *dev) { +#ifdef CONFIG_COUNTER_RZ_GTM_COUNTER + /* both top change and alarm is not supported */ + return false; +#else return single_channel_alarm_capable(dev) && set_top_value_capable(dev); +#endif } ZTEST(counter_basic, test_single_shot_alarm_notop) @@ -662,6 +829,9 @@ static void test_late_alarm_instance(const struct device *dev) .user_data = NULL }; + tick_us = tick_us == 0 ? 1 : tick_us; + counter_stop(dev); + err = counter_set_guard_period(dev, guard, COUNTER_GUARD_PERIOD_LATE_TO_SET); zassert_equal(0, err, "%s: Unexpected error", dev->name); @@ -713,6 +883,9 @@ static void test_late_alarm_error_instance(const struct device *dev) .user_data = NULL }; + tick_us = tick_us == 0 ? 1 : tick_us; + counter_stop(dev); + err = counter_set_guard_period(dev, guard, COUNTER_GUARD_PERIOD_LATE_TO_SET); zassert_equal(0, err, "%s: Unexpected error", dev->name); @@ -953,6 +1126,11 @@ static bool reliable_cancel_capable(const struct device *dev) if (single_channel_alarm_capable(dev)) { return true; } +#endif +#ifdef CONFIG_COUNTER_RZ_GTM_COUNTER + if (single_channel_alarm_capable(dev)) { + return true; + } #endif return false; } diff --git a/tests/drivers/dma/chan_blen_transfer/boards/rz_g3s.overlay b/tests/drivers/dma/chan_blen_transfer/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..b2fac9cb5b4d60 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/rz_g3s.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +test_dma0: &dma0 { + status = "okay"; + dma-buf-addr-alignment = <1>; +}; diff --git a/tests/drivers/dma/chan_blen_transfer/boards/rz_g3s_fpu.overlay b/tests/drivers/dma/chan_blen_transfer/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..b2fac9cb5b4d60 --- /dev/null +++ b/tests/drivers/dma/chan_blen_transfer/boards/rz_g3s_fpu.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +test_dma0: &dma0 { + status = "okay"; + dma-buf-addr-alignment = <1>; +}; diff --git a/tests/drivers/dma/loop_transfer/boards/rz_g3s.overlay b/tests/drivers/dma/loop_transfer/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..b2fac9cb5b4d60 --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/rz_g3s.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +test_dma0: &dma0 { + status = "okay"; + dma-buf-addr-alignment = <1>; +}; diff --git a/tests/drivers/dma/loop_transfer/boards/rz_g3s_fpu.overlay b/tests/drivers/dma/loop_transfer/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..b2fac9cb5b4d60 --- /dev/null +++ b/tests/drivers/dma/loop_transfer/boards/rz_g3s_fpu.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +test_dma0: &dma0 { + status = "okay"; + dma-buf-addr-alignment = <1>; +}; diff --git a/tests/drivers/dma/scatter_gather/boards/rz_g3s.overlay b/tests/drivers/dma/scatter_gather/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..1d230024943e7a --- /dev/null +++ b/tests/drivers/dma/scatter_gather/boards/rz_g3s.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + dma0 = &dma0; + }; +}; + +&dma0 { + status = "okay"; +}; diff --git a/tests/drivers/dma/scatter_gather/boards/rz_g3s_fpu.overlay b/tests/drivers/dma/scatter_gather/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..1d230024943e7a --- /dev/null +++ b/tests/drivers/dma/scatter_gather/boards/rz_g3s_fpu.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + dma0 = &dma0; + }; +}; + +&dma0 { + status = "okay"; +}; diff --git a/tests/drivers/dma/scatter_gather/testcase.yaml b/tests/drivers/dma/scatter_gather/testcase.yaml index 880f09267b7590..0c6a452edd78b3 100644 --- a/tests/drivers/dma/scatter_gather/testcase.yaml +++ b/tests/drivers/dma/scatter_gather/testcase.yaml @@ -9,6 +9,7 @@ tests: - frdm_k64f - mimxrt1060_evk - lpcxpresso55s36 + - rz_g3s filter: dt_alias_exists("dma0") integration_platforms: - intel_adsp_cavs25 diff --git a/tests/drivers/gpio/gpio_basic_api/boards/rz_g3s.conf b/tests/drivers/gpio/gpio_basic_api/boards/rz_g3s.conf new file mode 100644 index 00000000000000..b9d02cf11d5d4f --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/rz_g3s.conf @@ -0,0 +1 @@ +CONFIG_SKIP_PULL_TEST=y diff --git a/tests/drivers/gpio/gpio_basic_api/boards/rz_g3s.overlay b/tests/drivers/gpio/gpio_basic_api/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..18ec97d216dc21 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/rz_g3s.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&port8 2 0>; + in-gpios = <&port8 3 0>; + }; +}; + +&port8 { + status = "okay"; +}; diff --git a/tests/drivers/gpio/gpio_basic_api/boards/rz_g3s_fpu.conf b/tests/drivers/gpio/gpio_basic_api/boards/rz_g3s_fpu.conf new file mode 100644 index 00000000000000..b9d02cf11d5d4f --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/rz_g3s_fpu.conf @@ -0,0 +1 @@ +CONFIG_SKIP_PULL_TEST=y diff --git a/tests/drivers/gpio/gpio_basic_api/boards/rz_g3s_fpu.overlay b/tests/drivers/gpio/gpio_basic_api/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..18ec97d216dc21 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/rz_g3s_fpu.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&port8 2 0>; + in-gpios = <&port8 3 0>; + }; +}; + +&port8 { + status = "okay"; +}; diff --git a/tests/drivers/pwm/poeg_api/CMakeLists.txt b/tests/drivers/pwm/poeg_api/CMakeLists.txt new file mode 100644 index 00000000000000..a1586d8c7558ad --- /dev/null +++ b/tests/drivers/pwm/poeg_api/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(poeg_api) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/pwm/poeg_api/boards/rz_g3s.overlay b/tests/drivers/pwm/poeg_api/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..482465db05d36d --- /dev/null +++ b/tests/drivers/pwm/poeg_api/boards/rz_g3s.overlay @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + pwm-0 = &gpt32e3; + }; + + buttons { + n: node { + gpios = <&port13 4 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + }; +}; + +&gpt32e3 { + pinctrl-0 = <&gpt3_pins>; + pinctrl-names = "default"; + renesas,poeg = "POEGB"; + renesas,poeg-device = <&poegb>; + status = "okay"; +}; + +&port13 { + status = "okay"; +}; + +&poegb { + pinctrl-0 = <&poegb_pins>; + pinctrl-names = "default"; + status = "okay"; + renesas,invert = <1>; +}; + +&pinctrl { + /omit-if-no-ref/ gpt3_pins: gpt3 { + gpt3-pinmux { + pinmux = ; /* GTIOC3A */ + }; + }; + + /* P18_1 used as GTETGB */ + /omit-if-no-ref/ poegb_pins: poegb { + poegb-pinmux { + pinmux = ; /* GTETRGB */ + }; + }; +}; diff --git a/tests/drivers/pwm/poeg_api/boards/rz_g3s_fpu.overlay b/tests/drivers/pwm/poeg_api/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..b6583b9d0f2686 --- /dev/null +++ b/tests/drivers/pwm/poeg_api/boards/rz_g3s_fpu.overlay @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + pwm-0 = &gpt32e0_s; + }; + + buttons { + n: node { + gpios = <&port13 4 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + }; +}; + +&gpt32e0_s { + pinctrl-0 = <&gpt0_pins>; + pinctrl-names = "default"; + renesas,poeg = "POEGB"; + renesas,poeg-device = <&poegb>; + status = "okay"; +}; + +&port13 { + status = "okay"; +}; + +&poegb { + pinctrl-0 = <&poegb_pins>; + pinctrl-names = "default"; + status = "okay"; + renesas,invert = <1>; +}; + +&pinctrl { + /omit-if-no-ref/ gpt0_pins: gpt3 { + gpt0-pinmux { + pinmux = ; /* GTIOC0A */ + }; + }; + + /* P18_1 used as GTETGB */ + /omit-if-no-ref/ poegb_pins: poegb { + poegb-pinmux { + pinmux = ; /* GTETRGB */ + }; + }; +}; diff --git a/tests/drivers/pwm/poeg_api/prj.conf b/tests/drivers/pwm/poeg_api/prj.conf new file mode 100644 index 00000000000000..e9b4d06e35b1cf --- /dev/null +++ b/tests/drivers/pwm/poeg_api/prj.conf @@ -0,0 +1,3 @@ +CONFIG_PWM=y +CONFIG_ZTEST=y +CONFIG_ZTEST_NEW_API=y diff --git a/tests/drivers/pwm/poeg_api/src/main.c b/tests/drivers/pwm/poeg_api/src/main.c new file mode 100644 index 00000000000000..4cc5de52585657 --- /dev/null +++ b/tests/drivers/pwm/poeg_api/src/main.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Verify POEG can work in cooperation with PWM. + * It controls PWM output using GPIO pin level to + * enable or disable PWM output. + * + * @details + * - Test Steps + * -# Bind PWM_3 port 3. + * -# Use logic analyzer or other instruments to measure the output + * from PWM_OUT_0 and GPIO pin. + * - Expected Results + * Logic analizer should show the following scheme: + * PWM_3: _______|||||__||||| + * __ ______ ____ + * GPIO: |__| |__| + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#if !DT_NODE_HAS_STATUS(DT_ALIAS(pwm_0), okay) +#error "Define a PWM device" +#endif + +#define POEG_NODE DT_INST(0, renesas_rzg3s_poeg) + +#if !DT_NODE_HAS_STATUS(POEG_NODE, okay) +#error "Define a PWM device" +#endif + +#define PWM_DEV_NODE DT_ALIAS(pwm_0) + +#define DEFAULT_PERIOD_CYCLE 64000 +#define DEFAULT_PULSE_CYCLE 32000 +#define DEFAULT_PERIOD_NSEC 2000000 +#define DEFAULT_PULSE_NSEC 1000000 + +#if defined CONFIG_BOARD_RZ_G3S +/* Default port should be adapted per board to fit the channel + * associated to the PWM pin. For instance, for following device, + * aliases { + * pwm-0 = &gpt32e3; + * }; + * the following should be used: + * #define DEFAULT_PWM_PORT 3 + */ +#define DEFAULT_PWM_PORT 3 +#else +#define DEFAULT_PWM_PORT 0 +#endif + +#define UNIT_NSECS 1 + +#define SW_NODE DT_NODELABEL(n) + +static const struct gpio_dt_spec gpio = GPIO_DT_SPEC_GET(SW_NODE, gpios); + +const struct device *get_pwm_device(void) +{ + return DEVICE_DT_GET(PWM_DEV_NODE); +} + +const struct device *get_poeg_device(void) +{ + return DEVICE_DT_GET(POEG_NODE); +} + +static int start_pwm(uint32_t port, uint32_t period, uint32_t pulse, uint8_t unit) +{ + TC_PRINT("[PWM]: %" PRIu8 ", [period]: %" PRIu32 ", [pulse]: %" PRIu32 "\n", port, period, + pulse); + + const struct device *pwm_dev = get_pwm_device(); + + if (!device_is_ready(pwm_dev)) { + TC_PRINT("PWM device is not ready\n"); + return TC_FAIL; + } + + if (pwm_set(pwm_dev, port, period, pulse, 0)) { + TC_PRINT("Fail to set the period and pulse width\n"); + return TC_FAIL; + } + + return TC_PASS; +} + +static void cb(void *par) +{ + const struct device *poeg_dev = get_poeg_device(); + uint32_t status = poeg_status(poeg_dev); + + TC_PRINT("Got POEG status %x\n", status); + k_busy_wait(1000000); + + gpio_pin_toggle_dt(&gpio); + + poeg_reset(poeg_dev); +} + +ZTEST_USER(poeg_basic, test_poeg_trigger) +{ + int ret; + const struct device *poeg_dev = get_poeg_device(); + + ret = gpio_pin_configure_dt(&gpio, GPIO_OUTPUT_ACTIVE); + + poeg_cb_set(poeg_dev, cb, NULL); + zassert_equal(ret, 0, "Failed to configure the pin"); + k_sleep(K_MSEC(1000)); + + zassert_true(start_pwm(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, DEFAULT_PULSE_NSEC, + UNIT_NSECS) == TC_PASS, + NULL); + k_sleep(K_MSEC(1000)); + ret = gpio_pin_toggle_dt(&gpio); + zassert_equal(ret, 0, "Failed to toggle pin value"); +} + +ZTEST_SUITE(poeg_basic, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/drivers/pwm/poeg_api/testcase.yaml b/tests/drivers/pwm/poeg_api/testcase.yaml new file mode 100644 index 00000000000000..2f3552e973e434 --- /dev/null +++ b/tests/drivers/pwm/poeg_api/testcase.yaml @@ -0,0 +1,7 @@ +tests: + drivers.poeg: + tags: + - drivers + - pwm + filter: dt_alias_exists("pwm-0") + depends_on: pwm diff --git a/tests/drivers/pwm/pwm_ab/CMakeLists.txt b/tests/drivers/pwm/pwm_ab/CMakeLists.txt new file mode 100644 index 00000000000000..c4b64557117ddb --- /dev/null +++ b/tests/drivers/pwm/pwm_ab/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(pwm_ab) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/pwm/pwm_ab/boards/rz_g3s.overlay b/tests/drivers/pwm/pwm_ab/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..0e6478ffede139 --- /dev/null +++ b/tests/drivers/pwm/pwm_ab/boards/rz_g3s.overlay @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + pwm-0 = &gpt32e0_s; + }; +}; + +&gpt32e0_s { + pinctrl-0 = <&gpt0_pins>; + pinctrl-names = "default"; + divider = <16>; + status = "okay"; +}; + +&pinctrl { + /omit-if-no-ref/ gpt0_pins: gpt0 { + gpt0-pinmux { + pinmux = , /* GTIOC0A */ + ; /* GTIOC0B */ + }; + }; +}; diff --git a/tests/drivers/pwm/pwm_ab/boards/rz_g3s_fpu.overlay b/tests/drivers/pwm/pwm_ab/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..0e6478ffede139 --- /dev/null +++ b/tests/drivers/pwm/pwm_ab/boards/rz_g3s_fpu.overlay @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + pwm-0 = &gpt32e0_s; + }; +}; + +&gpt32e0_s { + pinctrl-0 = <&gpt0_pins>; + pinctrl-names = "default"; + divider = <16>; + status = "okay"; +}; + +&pinctrl { + /omit-if-no-ref/ gpt0_pins: gpt0 { + gpt0-pinmux { + pinmux = , /* GTIOC0A */ + ; /* GTIOC0B */ + }; + }; +}; diff --git a/tests/drivers/pwm/pwm_ab/prj.conf b/tests/drivers/pwm/pwm_ab/prj.conf new file mode 100644 index 00000000000000..7375a2bd0b4325 --- /dev/null +++ b/tests/drivers/pwm/pwm_ab/prj.conf @@ -0,0 +1,4 @@ +CONFIG_PWM=y +CONFIG_ZTEST=y +CONFIG_ZTEST_NEW_API=y +CONFIG_TEST_USERSPACE=y diff --git a/tests/drivers/pwm/pwm_ab/src/main.c b/tests/drivers/pwm/pwm_ab/src/main.c new file mode 100644 index 00000000000000..a9696753531bda --- /dev/null +++ b/tests/drivers/pwm/pwm_ab/src/main.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include +#include +#include + +const struct device *get_pwm_device(void); + +static void *pwm_ab_setup(void) +{ + const struct device *dev = get_pwm_device(); + + zassert_true(device_is_ready(dev), "PWM device is not ready"); + k_object_access_grant(dev, k_current_get()); + + return NULL; +} + +ZTEST_SUITE(pwm_ab, NULL, pwm_ab_setup, NULL, NULL, NULL); diff --git a/tests/drivers/pwm/pwm_ab/src/test_pwm.c b/tests/drivers/pwm/pwm_ab/src/test_pwm.c new file mode 100644 index 00000000000000..537cb98792972d --- /dev/null +++ b/tests/drivers/pwm/pwm_ab/src/test_pwm.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Verify PWM channels A and B work. + * Includes 3 test steps * + * @details + * - Test Steps + * -# Bind PWM ch A a and PWM ch B to port 0. + * -# Set PWM period and pulse using pwm_set_cycles() or pwm_set(). + * -# Use multimeter or other instruments to measure the output + * from PWM_OUT_0_A and PWM_OUT_0_B. + * - Expected Results + * -# The output of PWM_OUT_0_A and PWM_OUT_0_B will differ according to the value + * of period and pulse. + * 1) OUT_0_A -> Half on -> Period : Pulse (2 : 1) -> 1.65V + * OUT_O_B -> Always off + * 2) OUT_0_A -> Half on -> Period : Pulse (2 : 1) -> 1.65V + * OUT_O_B -> Always off + * 1) OUT_0_A -> Half on -> Period : Pulse (2 : 1) -> 1.65V + * OUT_O_B -> Half on -> Period : Pulse (2 : 1) -> 1.65V + * 2) OUT_0_A -> Half on -> Period : Pulse (2 : 1) -> 1.65V + * OUT_O_B -> Half on -> Period : Pulse (2 : 1) -> 1.65V + * 3) OUT_0_B -> Half on -> Period : Pulse (2 : 1) -> 1.65V + * OUT_O_A -> Always off + * 4) OUT_0_B -> Half on -> Period : Pulse (2 : 1) -> 1.65V + * OUT_O_A -> Always off + * 5) Always on -> Period : Pulse (1 : 1) -> 3.3V + * 6) Half on -> Period : Pulse (2 : 1) -> 1.65V + * 7) Always off -> Period : Pulse (1 : 0) -> 0V + */ + +#include +#include +#include +#include +#include +#include + +#if DT_NODE_HAS_STATUS(DT_ALIAS(pwm_0), okay) +#define PWM_DEV_NODE DT_ALIAS(pwm_0) +#else +#error "Define a PWM device" +#endif + +#define DEFAULT_PERIOD_CYCLE 64000 +#define DEFAULT_PULSE_CYCLE 32000 +#define DEFAULT_PERIOD_NSEC 2000000 +#define DEFAULT_PULSE_NSEC 1000000 + +#define DEFAULT_PWM_PORT 0 +#define PWM_PORT_B PWM_PROTECTED(DEFAULT_PWM_PORT | PWM_CHANNEL_INPUT_B) + +#define UNIT_CYCLES 0 +#define UNIT_NSECS 1 + +const struct device *get_pwm_device(void) +{ + return DEVICE_DT_GET(PWM_DEV_NODE); +} + +static int test_task(uint32_t port, uint32_t period, uint32_t pulse, uint8_t unit) +{ + TC_PRINT("[PWM]: %x, [period]: %" PRIu32 ", [pulse]: %" PRIu32 "\n", + port, period, pulse); + + const struct device *pwm_dev = get_pwm_device(); + + if (!device_is_ready(pwm_dev)) { + TC_PRINT("PWM device is not ready\n"); + return TC_FAIL; + } + + if (unit == UNIT_CYCLES) { + /* Verify pwm_set_cycles() */ + if (pwm_set_cycles(pwm_dev, port, period, pulse, 0)) { + TC_PRINT("Fail to set the period and pulse width\n"); + return TC_FAIL; + } + } else { /* unit == UNIT_NSECS */ + /* Verify pwm_set() */ + if (pwm_set(pwm_dev, port, period, pulse, 0)) { + TC_PRINT("Fail to set the period and pulse width\n"); + return TC_FAIL; + } + } + + return TC_PASS; +} + +ZTEST_USER(pwm_ab, test_pwm_nsec) +{ + /* Period : Pulse (2000000 : 1000000), unit (nsec). Voltage : 1.65V */ + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, + DEFAULT_PULSE_NSEC, UNIT_NSECS) == TC_PASS, NULL); + k_sleep(K_MSEC(1000)); + + /* Period : Pulse (2000000 : 2000000), unit (nsec). Voltage : 3.3V */ + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, + DEFAULT_PERIOD_NSEC, UNIT_NSECS) == TC_PASS, NULL); + k_sleep(K_MSEC(1000)); + + /* Period : Pulse (2000000 : 0), unit (nsec). Voltage : 0V */ + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, + 0, UNIT_NSECS) == TC_PASS, NULL); + k_sleep(K_MSEC(1000)); +} + +ZTEST_USER(pwm_ab, test_pwm_a) +{ + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, + DEFAULT_PULSE_NSEC, UNIT_NSECS) == TC_PASS, NULL); + + k_sleep(K_MSEC(1000)); + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, + 0, UNIT_NSECS) == TC_PASS, NULL); + + k_sleep(K_MSEC(1000)); + + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, + DEFAULT_PULSE_NSEC, UNIT_NSECS) == TC_PASS, NULL); + + k_sleep(K_MSEC(1000)); + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, + 0, UNIT_NSECS) == TC_PASS, NULL); +} + +ZTEST_USER(pwm_ab, test_pwm_b) +{ + /* Period : Pulse (2000000 : 1000000), unit (nsec). Voltage : 1.65V */ + zassert_true(test_task(PWM_PORT_B, DEFAULT_PERIOD_NSEC, + DEFAULT_PULSE_NSEC, UNIT_NSECS) == TC_PASS, NULL); + + k_sleep(K_MSEC(1000)); + zassert_true(test_task(PWM_PORT_B, DEFAULT_PERIOD_NSEC, + 0, UNIT_NSECS) == TC_PASS, NULL); + + k_sleep(K_MSEC(1000)); + + zassert_true(test_task(PWM_PORT_B, DEFAULT_PERIOD_NSEC, + DEFAULT_PULSE_NSEC, UNIT_NSECS) == TC_PASS, NULL); + + k_sleep(K_MSEC(1000)); + zassert_true(test_task(PWM_PORT_B, DEFAULT_PERIOD_NSEC, + 0, UNIT_NSECS) == TC_PASS, NULL); +} + +ZTEST_USER(pwm_ab, test_pwm_ab) +{ + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, + DEFAULT_PULSE_NSEC, UNIT_NSECS) == TC_PASS, NULL); + zassert_true(test_task(PWM_PORT_B, DEFAULT_PERIOD_NSEC, + DEFAULT_PULSE_NSEC, UNIT_NSECS) == TC_PASS, NULL); + + k_sleep(K_MSEC(1000)); + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, + 0, UNIT_NSECS) == TC_PASS, NULL); + zassert_true(test_task(PWM_PORT_B, DEFAULT_PERIOD_NSEC, + 0, UNIT_NSECS) == TC_PASS, NULL); + + k_sleep(K_MSEC(1000)); + + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, + DEFAULT_PULSE_NSEC, UNIT_NSECS) == TC_PASS, NULL); + zassert_true(test_task(PWM_PORT_B, DEFAULT_PERIOD_NSEC, + DEFAULT_PULSE_NSEC, UNIT_NSECS) == TC_PASS, NULL); + + k_sleep(K_MSEC(1000)); + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_NSEC, + 0, UNIT_NSECS) == TC_PASS, NULL); + zassert_true(test_task(PWM_PORT_B, DEFAULT_PERIOD_NSEC, + 0, UNIT_NSECS) == TC_PASS, NULL); +} + +ZTEST_USER(pwm_ab, test_pwm_cycle) +{ + /* Period : Pulse (64000 : 32000), unit (cycle). Voltage : 1.65V */ + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_CYCLE, + DEFAULT_PULSE_CYCLE, UNIT_CYCLES) == TC_PASS, NULL); + k_sleep(K_MSEC(1000)); + + /* Period : Pulse (64000 : 64000), unit (cycle). Voltage : 3.3V */ + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_CYCLE, + DEFAULT_PERIOD_CYCLE, UNIT_CYCLES) == TC_PASS, NULL); + k_sleep(K_MSEC(1000)); + + /* Period : Pulse (64000 : 0), unit (cycle). Voltage : 0V */ + zassert_true(test_task(DEFAULT_PWM_PORT, DEFAULT_PERIOD_CYCLE, + 0, UNIT_CYCLES) == TC_PASS, NULL); + k_sleep(K_MSEC(1000)); +} diff --git a/tests/drivers/pwm/pwm_ab/testcase.yaml b/tests/drivers/pwm/pwm_ab/testcase.yaml new file mode 100644 index 00000000000000..c3dc119054783f --- /dev/null +++ b/tests/drivers/pwm/pwm_ab/testcase.yaml @@ -0,0 +1,8 @@ +tests: + drivers.pwm_ab: + tags: + - drivers + - pwm + - userspace + filter: dt_alias_exists("pwm-0") + depends_on: pwm diff --git a/tests/drivers/pwm/pwm_api/boards/rz_g3s.overlay b/tests/drivers/pwm/pwm_api/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..02d84ca396499b --- /dev/null +++ b/tests/drivers/pwm/pwm_api/boards/rz_g3s.overlay @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + pwm-0 = &gpt32e0; + }; +}; + +&gpt32e0 { + pinctrl-0 = <&gpt0_pins>; + pinctrl-names = "default"; + divider = <16>; + status = "okay"; +}; + +&pinctrl { + /omit-if-no-ref/ gpt0_pins: gpt0 { + gpt0-pinmux { + pinmux = , /* GTIOC0A */ + ; /* GTIOC0B */ + }; + }; +}; diff --git a/tests/drivers/pwm/pwm_api/boards/rz_g3s_fpu.overlay b/tests/drivers/pwm/pwm_api/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..02d84ca396499b --- /dev/null +++ b/tests/drivers/pwm/pwm_api/boards/rz_g3s_fpu.overlay @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + pwm-0 = &gpt32e0; + }; +}; + +&gpt32e0 { + pinctrl-0 = <&gpt0_pins>; + pinctrl-names = "default"; + divider = <16>; + status = "okay"; +}; + +&pinctrl { + /omit-if-no-ref/ gpt0_pins: gpt0 { + gpt0-pinmux { + pinmux = , /* GTIOC0A */ + ; /* GTIOC0B */ + }; + }; +}; diff --git a/tests/drivers/pwm/pwm_loopback/boards/rz_g3s.overlay b/tests/drivers/pwm/pwm_loopback/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..7b7ac3f71a211d --- /dev/null +++ b/tests/drivers/pwm/pwm_loopback/boards/rz_g3s.overlay @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + pwm-0 = &gpt32e0; + pwm-1 = &gpt32e3; + }; + + pwm_loopback_0 { + compatible = "test-pwm-loopback"; + pwms = <&gpt32e0 0 0 PWM_POLARITY_NORMAL>, + <&gpt32e3 3 0 PWM_POLARITY_NORMAL>; + }; +}; + +&gpt32e0 { + pinctrl-0 = <&gpt0_pins>; + pinctrl-names = "default"; + divider = <16>; + status = "okay"; +}; + +&gpt32e3 { + pinctrl-0 = <&gpt3_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&pinctrl { + /omit-if-no-ref/ gpt0_pins: gpt0 { + gpt0-pinmux { + pinmux = , /* GTIOC0A */ + ; /* GTIOC0B */ + }; + }; + + /omit-if-no-ref/ gpt3_pins: gpt3 { + gpt3-pinmux { + pinmux = , /* GTIOC3A */ + ; /* GTIOC3B */ + }; + }; +}; diff --git a/tests/drivers/pwm/pwm_loopback/boards/rz_g3s_fpu.overlay b/tests/drivers/pwm/pwm_loopback/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..7b7ac3f71a211d --- /dev/null +++ b/tests/drivers/pwm/pwm_loopback/boards/rz_g3s_fpu.overlay @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + pwm-0 = &gpt32e0; + pwm-1 = &gpt32e3; + }; + + pwm_loopback_0 { + compatible = "test-pwm-loopback"; + pwms = <&gpt32e0 0 0 PWM_POLARITY_NORMAL>, + <&gpt32e3 3 0 PWM_POLARITY_NORMAL>; + }; +}; + +&gpt32e0 { + pinctrl-0 = <&gpt0_pins>; + pinctrl-names = "default"; + divider = <16>; + status = "okay"; +}; + +&gpt32e3 { + pinctrl-0 = <&gpt3_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&pinctrl { + /omit-if-no-ref/ gpt0_pins: gpt0 { + gpt0-pinmux { + pinmux = , /* GTIOC0A */ + ; /* GTIOC0B */ + }; + }; + + /omit-if-no-ref/ gpt3_pins: gpt3 { + gpt3-pinmux { + pinmux = , /* GTIOC3A */ + ; /* GTIOC3B */ + }; + }; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/rz_g3s.conf b/tests/drivers/spi/spi_loopback/boards/rz_g3s.conf new file mode 100644 index 00000000000000..27b608a7d0da3e --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/rz_g3s.conf @@ -0,0 +1,5 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SPI_LOOPBACK_MODE_LOOP=y +CONFIG_SPI_ASYNC=y diff --git a/tests/drivers/spi/spi_loopback/boards/rz_g3s.overlay b/tests/drivers/spi/spi_loopback/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..be180b0348ef67 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/rz_g3s.overlay @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 EPAM Systems + * SPDX-License-Identifier: Apache-2.0 + */ + +&spi0 { + status = "okay"; + dmas = <&dma0 1 DMA_RS_RSPI_SPTI0 0>, <&dma0 0 DMA_RS_RSPI_SPRI0 0>; + dma-names = "tx", "rx"; + + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <500000>; + }; + + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <16000000>; + }; +}; + +&dma0 { + status = "okay"; + dma-buf-addr-alignment = <1>; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/rz_g3s_fpu.conf b/tests/drivers/spi/spi_loopback/boards/rz_g3s_fpu.conf new file mode 100644 index 00000000000000..27b608a7d0da3e --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/rz_g3s_fpu.conf @@ -0,0 +1,5 @@ +# Copyright (c) 2024 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SPI_LOOPBACK_MODE_LOOP=y +CONFIG_SPI_ASYNC=y diff --git a/tests/drivers/spi/spi_loopback/boards/rz_g3s_fpu.overlay b/tests/drivers/spi/spi_loopback/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..591c980104f479 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/rz_g3s_fpu.overlay @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2024 EPAM Systems + * SPDX-License-Identifier: Apache-2.0 + */ + +&spi0 { + status = "okay"; + dmas = <&dma0 1 DMA_RS_RSPI_SPTI0 0>, <&dma0 0 DMA_RS_RSPI_SPRI0 0>; + dma-names = "tx", "rx"; + pinctrl-0 = <&spi0_pins>; + pinctrl-names = "default"; + + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <500000>; + }; + + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <16000000>; + }; +}; + +&dma0 { + status = "okay"; + dma-buf-addr-alignment = <1>; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/rz_g3s.conf b/tests/drivers/uart/uart_async_api/boards/rz_g3s.conf new file mode 100644 index 00000000000000..86df0aff3e6242 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/rz_g3s.conf @@ -0,0 +1 @@ +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/tests/drivers/uart/uart_async_api/boards/rz_g3s.overlay b/tests/drivers/uart/uart_async_api/boards/rz_g3s.overlay new file mode 100644 index 00000000000000..908a8ff3066d2a --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/rz_g3s.overlay @@ -0,0 +1,20 @@ +/{ + aliases { + dut = &scif3; + }; +}; + +&scif3 { + dmas = <&dma0 6 DMA_RS_SCIF_RXI3 0>, <&dma0 5 DMA_RS_SCIF_TXI3 0>; + dma-names = "rx", "tx"; + current-speed = <115200>; + pinctrl-0 = <&scif3_pins>; + pinctrl-names = "default"; + status = "okay"; + renesas,loopback; +}; + +&dma0 { + status = "okay"; + dma-buf-addr-alignment = <1>; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/rz_g3s_fpu.conf b/tests/drivers/uart/uart_async_api/boards/rz_g3s_fpu.conf new file mode 100644 index 00000000000000..86df0aff3e6242 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/rz_g3s_fpu.conf @@ -0,0 +1 @@ +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/tests/drivers/uart/uart_async_api/boards/rz_g3s_fpu.overlay b/tests/drivers/uart/uart_async_api/boards/rz_g3s_fpu.overlay new file mode 100644 index 00000000000000..b151ab57804efa --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/rz_g3s_fpu.overlay @@ -0,0 +1,20 @@ +/{ + aliases { + dut = &scif1; + }; +}; + +&scif1 { + dmas = <&dma0 6 DMA_RS_SCIF_RXI1 0>, <&dma0 5 DMA_RS_SCIF_TXI1 0>; + dma-names = "rx", "tx"; + current-speed = <115200>; + pinctrl-0 = <&scif1_pins>; + pinctrl-names = "default"; + status = "okay"; + renesas,loopback; +}; + +&dma0 { + status = "okay"; + dma-buf-addr-alignment = <1>; +}; diff --git a/tests/drivers/uart/uart_async_api/src/test_uart_async.c b/tests/drivers/uart/uart_async_api/src/test_uart_async.c index 040da520f2b24c..165e1cf2f1a3ee 100644 --- a/tests/drivers/uart/uart_async_api/src/test_uart_async.c +++ b/tests/drivers/uart/uart_async_api/src/test_uart_async.c @@ -212,7 +212,7 @@ static void *multiple_rx_enable_setup(void) ZTEST_USER(uart_async_multi_rx, test_multiple_rx_enable) { -#if defined(CONFIG_BOARD_RZ_A2M) +#if defined(CONFIG_BOARD_RZ_A2M) || defined(CONFIG_SOC_SERIES_RZ_G) ztest_test_skip(); #endif /* Check also if sending from read only memory (e.g. flash) works. */ @@ -344,7 +344,7 @@ static void *chained_read_setup(void) ZTEST_USER(uart_async_chain_read, test_chained_read) { -#if defined(CONFIG_BOARD_RZ_A2M) +#if defined(CONFIG_BOARD_RZ_A2M) || defined(CONFIG_SOC_SERIES_RZ_G) ztest_test_skip(); #endif uint8_t tx_buf[10]; @@ -420,7 +420,7 @@ static void *double_buffer_setup(void) ZTEST_USER(uart_async_double_buf, test_double_buffer) { -#if defined(CONFIG_BOARD_RZ_A2M) +#if defined(CONFIG_BOARD_RZ_A2M) || defined(CONFIG_SOC_SERIES_RZ_G) ztest_test_skip(); #endif uint8_t tx_buf[4]; @@ -605,7 +605,7 @@ static void *write_abort_setup(void) ZTEST_USER(uart_async_write_abort, test_write_abort) { -#if defined(CONFIG_BOARD_RZ_A2M) +#if defined(CONFIG_BOARD_RZ_A2M) || defined(CONFIG_SOC_SERIES_RZ_G) ztest_test_skip(); #endif uint8_t tx_buf[100]; @@ -833,7 +833,7 @@ static void *long_buffers_setup(void) ZTEST_USER(uart_async_long_buf, test_long_buffers) { -#if defined(CONFIG_BOARD_RZ_A2M) +#if defined(CONFIG_BOARD_RZ_A2M) || defined(CONFIG_SOC_SERIES_RZ_G) ztest_test_skip(); #endif memset(long_rx_buf, 0, sizeof(long_rx_buf)); diff --git a/tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c b/tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c index 76199a27d63514..a6e90f6dd0a278 100644 --- a/tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c +++ b/tests/drivers/watchdog/wdt_basic_api/src/test_wdt.c @@ -102,6 +102,8 @@ #define WDT_NODE DT_INST(0, andestech_atcwdt200) #define TIMEOUTS 0 #define WDT_TEST_MAX_WINDOW 200U +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_rzg_wdt) +#define WDT_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(renesas_rzg_wdt) #endif #if DT_HAS_COMPAT_STATUS_OKAY(raspberrypi_pico_watchdog) #define WDT_TEST_MAX_WINDOW 20000U @@ -204,7 +206,7 @@ static int test_wdt_no_callback(void) } m_cfg_wdt0.callback = NULL; - m_cfg_wdt0.flags = WDT_FLAG_RESET_SOC; + m_cfg_wdt0.flags = WDT_FLAG_RESET_CPU_CORE; m_cfg_wdt0.window.max = WDT_TEST_MAX_WINDOW; err = wdt_install_timeout(wdt, &m_cfg_wdt0); if (err < 0) { @@ -249,7 +251,7 @@ static int test_wdt_callback_1(void) } m_testvalue = 0U; - m_cfg_wdt0.flags = WDT_FLAG_RESET_SOC; + m_cfg_wdt0.flags = WDT_FLAG_RESET_CPU_CORE; m_cfg_wdt0.callback = wdt_int_cb0; m_cfg_wdt0.window.max = WDT_TEST_MAX_WINDOW; err = wdt_install_timeout(wdt, &m_cfg_wdt0); @@ -271,7 +273,6 @@ static int test_wdt_callback_1(void) } TC_PRINT("Waiting to restart MCU\n"); - m_testvalue = 0U; m_state = WDT_TEST_STATE_CHECK_RESET; while (1) { k_yield(); @@ -306,7 +307,7 @@ static int test_wdt_callback_2(void) m_testvalue = 0U; m_cfg_wdt0.callback = wdt_int_cb0; - m_cfg_wdt0.flags = WDT_FLAG_RESET_SOC; + m_cfg_wdt0.flags = WDT_FLAG_RESET_CPU_CORE; m_cfg_wdt0.window.max = WDT_TEST_MAX_WINDOW; err = wdt_install_timeout(wdt, &m_cfg_wdt0); @@ -316,7 +317,7 @@ static int test_wdt_callback_2(void) } m_cfg_wdt1.callback = wdt_int_cb1; - m_cfg_wdt1.flags = WDT_FLAG_RESET_SOC; + m_cfg_wdt1.flags = WDT_FLAG_RESET_CPU_CORE; m_cfg_wdt1.window.max = WDT_TEST_MAX_WINDOW; err = wdt_install_timeout(wdt, &m_cfg_wdt1); if (err < 0) { @@ -354,7 +355,7 @@ static int test_wdt_bad_window_max(void) TC_PRINT("Testcase: %s\n", __func__); m_cfg_wdt0.callback = NULL; - m_cfg_wdt0.flags = WDT_FLAG_RESET_SOC; + m_cfg_wdt0.flags = WDT_FLAG_RESET_CPU_CORE; m_cfg_wdt0.window.max = 0U; err = wdt_install_timeout(wdt, &m_cfg_wdt0); if (err == -EINVAL) { diff --git a/tests/posix/eventfd/boards/rz_g3s.conf b/tests/posix/eventfd/boards/rz_g3s.conf new file mode 100644 index 00000000000000..ce31d5b5c75b3e --- /dev/null +++ b/tests/posix/eventfd/boards/rz_g3s.conf @@ -0,0 +1 @@ +CONFIG_NET_BUF_DATA_ALIGN=8