dm: Implement a CPU uclass

It is useful to be able to keep track of the available CPUs in a multi-CPU
system. This uclass is mostly intended for use with SMP systems.

The uclass provides methods for getting basic information about each CPU.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
master
Simon Glass 9 years ago
parent 33eac2dc25
commit 11f4dc1583
  1. 2
      drivers/Kconfig
  2. 1
      drivers/Makefile
  3. 8
      drivers/cpu/Kconfig
  4. 7
      drivers/cpu/Makefile
  5. 61
      drivers/cpu/cpu-uclass.c
  6. 84
      include/cpu.h
  7. 1
      include/dm/uclass-id.h

@ -2,6 +2,8 @@ menu "Device Drivers"
source "drivers/core/Kconfig"
source "drivers/cpu/Kconfig"
source "drivers/demo/Kconfig"
source "drivers/pci/Kconfig"

@ -3,6 +3,7 @@ obj-$(CONFIG_DM_DEMO) += demo/
obj-$(CONFIG_BIOSEMU) += bios_emulator/
obj-y += block/
obj-$(CONFIG_BOOTCOUNT_LIMIT) += bootcount/
obj-$(CONFIG_CPU) += cpu/
obj-y += crypto/
obj-$(CONFIG_FPGA) += fpga/
obj-y += hwmon/

@ -0,0 +1,8 @@
config CPU
bool "Enable CPU drivers using Driver Model"
help
This allows drivers to be provided for CPUs and their type to be
specified in the board's device tree. For boards which support
multiple CPUs, then normally have to be set up in U-Boot so that
they can work correctly in the OS. This provides a framework for
finding out information about available CPUs and making changes.

@ -0,0 +1,7 @@
#
# Copyright (c) 2015 Google, Inc
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-$(CONFIG_CPU) += cpu-uclass.o

@ -0,0 +1,61 @@
/*
* Copyright (C) 2015 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <cpu.h>
#include <dm.h>
#include <dm/lists.h>
#include <dm/root.h>
int cpu_get_desc(struct udevice *dev, char *buf, int size)
{
struct cpu_ops *ops = cpu_get_ops(dev);
if (!ops->get_desc)
return -ENOSYS;
return ops->get_desc(dev, buf, size);
}
int cpu_get_info(struct udevice *dev, struct cpu_info *info)
{
struct cpu_ops *ops = cpu_get_ops(dev);
if (!ops->get_desc)
return -ENOSYS;
return ops->get_info(dev, info);
}
U_BOOT_DRIVER(cpu_bus) = {
.name = "cpu_bus",
.id = UCLASS_SIMPLE_BUS,
.per_child_platdata_auto_alloc_size = sizeof(struct cpu_platdata),
};
static int uclass_cpu_init(struct uclass *uc)
{
struct udevice *dev;
int node;
int ret;
node = fdt_path_offset(gd->fdt_blob, "/cpus");
if (node < 0)
return 0;
ret = device_bind_driver_to_node(dm_root(), "cpu_bus", "cpus", node,
&dev);
return ret;
}
UCLASS_DRIVER(cpu) = {
.id = UCLASS_CPU,
.name = "cpu",
.flags = DM_UC_FLAG_SEQ_ALIAS,
.init = uclass_cpu_init,
};

@ -0,0 +1,84 @@
/*
* Copyright (c) 2015 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __CPU_H
#define __CPU_H
/**
* struct cpu_platdata - platform data for a CPU
*
* This can be accessed with dev_get_parent_platdata() for any UCLASS_CPU
* device.
*
* @cpu_id: Platform-specific way of identifying the CPU.
*/
struct cpu_platdata {
int cpu_id;
};
/* CPU features - mostly just a placeholder for now */
enum {
CPU_FEAT_L1_CACHE = 0, /* Supports level 1 cache */
CPU_FEAT_MMU = 1, /* Supports virtual memory */
CPU_FEAT_COUNT,
};
/**
* struct cpu_info - Information about a CPU
*
* @cpu_freq: Current CPU frequency in Hz
* @features: Flags for supported CPU features
*/
struct cpu_info {
ulong cpu_freq;
ulong features;
};
struct cpu_ops {
/**
* get_desc() - Get a description string for a CPU
*
* @dev: Device to check (UCLASS_CPU)
* @buf: Buffer to place string
* @size: Size of string space
* @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
*/
int (*get_desc)(struct udevice *dev, char *buf, int size);
/**
* get_info() - Get information about a CPU
*
* @dev: Device to check (UCLASS_CPU)
* @info: Returns CPU info
* @return 0 if OK, -ve on error
*/
int (*get_info)(struct udevice *dev, struct cpu_info *info);
};
#define cpu_get_ops(dev) ((struct cpu_ops *)(dev)->driver->ops)
/**
* cpu_get_desc() - Get a description string for a CPU
*
* @dev: Device to check (UCLASS_CPU)
* @buf: Buffer to place string
* @size: Size of string space
* @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
*/
int cpu_get_desc(struct udevice *dev, char *buf, int size);
/**
* cpu_get_info() - Get information about a CPU
*
* @dev: Device to check (UCLASS_CPU)
* @info: Returns CPU info
* @return 0 if OK, -ve on error
*/
int cpu_get_info(struct udevice *dev, struct cpu_info *info);
#endif

@ -45,6 +45,7 @@ enum uclass_id {
UCLASS_USB_HUB, /* USB hub */
UCLASS_USB_DEV_GENERIC, /* USB generic device */
UCLASS_MASS_STORAGE, /* Mass storage device */
UCLASS_CPU, /* CPU, typically part of an SoC */
UCLASS_COUNT,
UCLASS_INVALID = -1,

Loading…
Cancel
Save