Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions apps/system/cpucontrol/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#
# For a description of the syntax of this configuration file,
# see kconfig-language at https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt
#

config SYSTEM_CPUCONTROL
bool "CPU Control commands"
default n
depends on SMP
---help---
Enable support for CPU control commands in TASH. This provides commands
for managing CPU power management and status functionality on multi-core
systems. Commands include cpu1on, cpu1off, cpustatus.
23 changes: 23 additions & 0 deletions apps/system/cpucontrol/Make.defs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
###########################################################################
#
# Copyright 2025 Samsung Electronics All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied.
# See the License for the specific
# language governing permissions and limitations under the License.
#
###########################################################################


ifeq ($(CONFIG_SYSTEM_CPUCONTROL),y)
CONFIGURED_APPS += system/cpucontrol
endif
102 changes: 102 additions & 0 deletions apps/system/cpucontrol/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
############################################################################
#
# Copyright (c) 2025 Samsung Electronics Co., Ltd All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied.
# See the License for the specific
# language governing permissions and limitations under the License.
#
###########################################################################

-include $(TOPDIR)/.config
-include $(TOPDIR)/Make.defs
include $(APPDIR)/Make.defs

ifeq ($(WINTOOL),y)
INCDIROPT = -w
endif

# CPU Control System Utility

ASRCS =
CSRCS =
MAINSRC = cpucontrol.c

AOBJS = $(ASRCS:.S=$(OBJEXT))
COBJS = $(CSRCS:.c=$(OBJEXT))
MAINOBJ = $(MAINSRC:.c=$(OBJEXT))

SRCS = $(ASRCS) $(CSRCS) $(MAINSRC)
OBJS = $(AOBJS) $(COBJS)

ifneq ($(CONFIG_BUILD_KERNEL),y)
OBJS += $(MAINOBJ)
endif

ifeq ($(CONFIG_WINDOWS_NATIVE),y)
BIN = ..\..\libapps$(LIBEXT)
else
ifeq ($(WINTOOL),y)
BIN = ..\\..\\libapps$(LIBEXT)
else
BIN = ../../libapps$(LIBEXT)
endif
endif

ifeq ($(WINTOOL),y)
INSTALL_DIR = "${shell cygpath -w $(BIN_DIR)}"
else
INSTALL_DIR = $(BIN_DIR)
endif

ROOTDEPPATH = --dep-path .

# Common build

VPATH =

all: .built
.PHONY: context depend clean distclean

$(AOBJS): %$(OBJEXT): %.S
$(call ASSEMBLE, $<, $@)

$(COBJS) $(MAINOBJ): %$(OBJEXT): %.c
$(call COMPILE, $<, $@)

.built: $(OBJS)
$(call ARCHIVE, $(BIN), $(OBJS))
$(Q) touch .built

install:

context:

# Create dependencies

.depend: Makefile $(SRCS)
$(Q) $(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
$(Q) touch $@

depend: .depend

clean:
$(call DELFILE, .built)
$(call CLEAN)

distclean: clean
$(call DELFILE, Make.dep)
$(call DELFILE, .depend)

-include Make.dep
.PHONY: preconfig
preconfig:
225 changes: 225 additions & 0 deletions apps/system/cpucontrol/cpucontrol.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
/****************************************************************************
*
* Copyright 2025 Samsung Electronics All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied.
* See the License for the specific
* language governing permissions and limitations under the License.
*
****************************************************************************/

/****************************************************************************
* Included Files
****************************************************************************/

#include <tinyara/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <unistd.h>
#include <tinyara/cpu_driver.h>
#include <apps/shell/tash.h>

/****************************************************************************
* Preprocessor Definitions
****************************************************************************/

const char *cpu_states[] = {
"running", //0
"stop", //1
};

/****************************************************************************
* Private Function Prototypes
****************************************************************************/


static int cpucontrol_cpu_on(int argc, char *argv[]);
static int cpucontrol_cpu_off(int argc, char *argv[]);
static int cpucontrol_cpu_status(int argc, char *argv[]);
static int cpucontrol_help(int argc, char *argv[]);
static int cpucontrol_main(int argc, char *argv[]);

/****************************************************************************
* Private Functions
****************************************************************************/

static int cpucontrol_cpu_on(int argc, char *argv[])
{
int fd, state, cpu_num;
char devname[16];

if (argc < 3) {
printf("Usage: cpuctrl on <cpu_id>\n");
printf("Example: cpuctrl on 1\n");
return -EINVAL;
}

cpu_num = atoi(argv[2]);
if (cpu_num <= 0 || cpu_num >= CONFIG_SMP_NCPUS) {
printf("Invalid CPU ID %d. Valid range: 1-%d\n", cpu_num, CONFIG_SMP_NCPUS - 1);
return -EINVAL;
}

if (sched_getcpu() > 0) {
printf("can only powerup cpu%d from cpu0!\n", cpu_num);
return -EPERM;
}

printf("powering up cpu%d!\n", cpu_num);

snprintf(devname, sizeof(devname), "/dev/cpu%d", cpu_num);
fd = open(devname, O_RDWR);
if (fd < 0) {
printf("Cannot open %s: errno = %d\n", devname, get_errno());
return -get_errno();
}

if (ioctl(fd, IOC_CPU_ENABLE, 1) < 0) {
printf("IOC_CPU_ENABLE ioctl failed for %s : errno = %d\n", devname, get_errno());
close(fd);
return -get_errno();
}
printf("cpu%d successfully enabled\n", cpu_num);

if (ioctl(fd, IOC_CPU_GET_STATE, &state) < 0) {
printf("IOC_CPU_GET_STATE ioctl failed for %s : errno = %d\n", devname, get_errno());
close(fd);
return -get_errno();
}

printf("state: %d (%s)\n", state, cpu_states[state]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In current master branch, cpu_state_t has 3 states.
Do we have plan to reduce it to two states? If not we need to update cpu_states to 3 states array.

typedef enum {
	CPU_RUNNING = 0, /* CPU is in task scheduer or boot from reset */
	CPU_HOTPLUG = 1, /* CPU is offline */
	CPU_WAKE_FROM_SLEEP = 2, /* CPU just wake from sleep but not in task scheduler */
} cpu_state_t;

When hotplug manager is implemented, we have to check here too.

close(fd);
return 0;
}

static int cpucontrol_cpu_off(int argc, char *argv[])
{
int fd, state, cpu_num;
char devname[16];

if (argc < 3) {
printf("Usage: cpuctrl off <cpu_id>\n");
printf("Example: cpuctrl off 1\n");
return -EINVAL;
}

cpu_num = atoi(argv[2]);
if (cpu_num <= 0 || cpu_num >= CONFIG_SMP_NCPUS) {
printf("Invalid CPU ID %d. Valid range: 1-%d\n", cpu_num, CONFIG_SMP_NCPUS - 1);
return -EINVAL;
}

if (sched_getcpu() > 0) {
printf("can only powerdown cpu%d from cpu0!\n", cpu_num);
return -EPERM;
}

printf("powering down cpu%d!\n", cpu_num);

snprintf(devname, sizeof(devname), "/dev/cpu%d", cpu_num);
fd = open(devname, O_RDWR);
if (fd < 0) {
printf("Cannot open %s: errno = %d\n", devname, get_errno());
return -get_errno();
}

if (ioctl(fd, IOC_CPU_DISABLE, 1) < 0) {
printf("IOC_CPU_DISABLE ioctl failed for %s : errno = %d\n", devname, get_errno());
close(fd);
return -get_errno();
}
printf("cpu%d successfully disabled\n", cpu_num);

if (ioctl(fd, IOC_CPU_GET_STATE, &state) < 0) {
printf("IOC_CPU_GET_STATE ioctl failed for %s : errno = %d\n", devname, get_errno());
close(fd);
return -get_errno();
}
printf("state: %d (%s)\n", state, cpu_states[state]);
close(fd);
return 0;
}

static int cpucontrol_cpu_status(int argc, char *argv[])
{
int fd, state;
char devname[16];

for (u8 i = 1; i < CONFIG_SMP_NCPUS; i++) {
snprintf(devname, sizeof(devname), "/dev/cpu%d", i);

fd = open(devname, O_RDWR);
if (fd < 0) {
printf("Cannot open %s: errno = %d\n", devname, get_errno());
continue;
}

if (ioctl(fd, IOC_CPU_GET_STATE, &state) < 0) {
printf("IOC_CPU_GET_STATE ioctl failed for %s : errno = %d\n", devname, get_errno());
close(fd);
continue;
}

printf("cpu state for cpu%d: %d (%s)\n", i, state, cpu_states[state]);
close(fd);
}
return 0;
}

static int cpucontrol_help(int argc, char *argv[])
{
printf("CPU Control Commands:\n");
printf(" cpuctrl on <cpu_id> - Power on specified CPU\n");
printf(" cpuctrl off <cpu_id> - Power off specified CPU\n");
printf(" cpuctrl status - Show status of all secondary CPUs\n");
printf(" cpuctrl help - Show this help message\n");
printf("\nExamples:\n");
printf(" cpuctrl on 1 - Power on CPU1\n");
printf(" cpuctrl off 1 - Power off CPU1\n");
printf(" cpuctrl status - Show all CPU states\n");
printf("\nNote: CPU control operations can only be performed from CPU0\n");
return 0;
}

static int cpucontrol_main(int argc, char *argv[])
{
if (argc < 2) {
return cpucontrol_help(argc, argv);
}

if (strcmp(argv[1], "on") == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using strncmp is better for safety.

return cpucontrol_cpu_on(argc, argv);
} else if (strcmp(argv[1], "off") == 0) {
return cpucontrol_cpu_off(argc, argv);
} else if (strcmp(argv[1], "help") == 0) {
return cpucontrol_help(argc, argv);
} else if (strcmp(argv[1], "status") == 0) {
return cpucontrol_cpu_status(argc, argv);
} else {
printf("Unknown subcommand: %s\n", argv[1]);
return cpucontrol_help(argc, argv);
}
}

/****************************************************************************
* Public Functions
****************************************************************************/

void cpucontrol_register_cmds(void)
{
/* Register the CPU control command during system initialization */
tash_cmd_install("cpuctrl", cpucontrol_main, TASH_EXECMD_ASYNC);
}
8 changes: 8 additions & 0 deletions apps/system/init/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@
extern void iotjs_register_cmds(void);
#endif

#ifdef CONFIG_SYSTEM_CPUCONTROL
extern void cpucontrol_register_cmds(void);
#endif

/****************************************************************************
* Pravite Functions
****************************************************************************/
Expand Down Expand Up @@ -107,6 +111,10 @@ static void tash_register_cmds(void)
#ifdef CONFIG_DEBUG_SYSTEM_APP
sysdbgapp_init();
#endif

#ifdef CONFIG_SYSTEM_CPUCONTROL
cpucontrol_register_cmds();
#endif
}
#endif /* CONFIG_TASH */

Expand Down
2 changes: 2 additions & 0 deletions build/configs/rtl8730e/flat_dev_ddr/defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,8 @@ CONFIG_AUDIO_KEYWORD_DETECT=y
# LCD Driver Support
#
# CONFIG_LCD is not set
CONFIG_CPU_DRIVER=y
CONFIG_SYSTEM_CPUCONTROL=y
CONFIG_BCH=y
CONFIG_RTC=y
# CONFIG_RTC_DATETIME is not set
Expand Down
Loading