blob: 468df5a36e61ae98823a1c2d7f65165867c8bc0b [file] [log] [blame]
Simon Glass4c8243d2019-12-06 21:42:55 -07001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2015 Google, Inc
4 */
5
Simon Glass4c8243d2019-12-06 21:42:55 -07006#include <cpu.h>
7#include <dm.h>
Simon Glass9bc15642020-02-03 07:36:16 -07008#include <malloc.h>
Simon Glass4c8243d2019-12-06 21:42:55 -07009#include <qfw.h>
10#include <dm/lists.h>
11#include <dm/uclass-internal.h>
12#include <dm/root.h>
13
14int qemu_cpu_fixup(void)
15{
16 int ret;
17 int cpu_num;
18 int cpu_online;
Bin Meng99c6f3e2021-02-02 15:04:47 +080019 struct uclass *uc;
Asherah Connor4ffa95d2021-03-19 18:21:40 +110020 struct udevice *dev, *pdev, *qfwdev;
Simon Glassb75b15b2020-12-03 16:55:23 -070021 struct cpu_plat *plat;
Simon Glass4c8243d2019-12-06 21:42:55 -070022 char *cpu;
23
Bin Meng99c6f3e2021-02-02 15:04:47 +080024 /* This will cause the CPUs devices to be bound */
25 ret = uclass_get(UCLASS_CPU, &uc);
26 if (ret)
27 return ret;
28
Simon Glass4c8243d2019-12-06 21:42:55 -070029 /* first we need to find '/cpus' */
30 for (device_find_first_child(dm_root(), &pdev);
31 pdev;
32 device_find_next_child(&pdev)) {
33 if (!strcmp(pdev->name, "cpus"))
34 break;
35 }
36 if (!pdev) {
37 printf("unable to find cpus device\n");
38 return -ENODEV;
39 }
40
Asherah Connor4ffa95d2021-03-19 18:21:40 +110041 /* get qfw dev */
42 ret = qfw_get_dev(&qfwdev);
43 if (ret) {
44 printf("unable to find qfw device\n");
45 return ret;
46 }
47
Simon Glass4c8243d2019-12-06 21:42:55 -070048 /* calculate cpus that are already bound */
49 cpu_num = 0;
50 for (uclass_find_first_device(UCLASS_CPU, &dev);
51 dev;
52 uclass_find_next_device(&dev)) {
53 cpu_num++;
54 }
55
56 /* get actual cpu number */
Asherah Connor4ffa95d2021-03-19 18:21:40 +110057 cpu_online = qfw_online_cpus(qfwdev);
Simon Glass4c8243d2019-12-06 21:42:55 -070058 if (cpu_online < 0) {
59 printf("unable to get online cpu number: %d\n", cpu_online);
60 return cpu_online;
61 }
62
63 /* bind addtional cpus */
64 dev = NULL;
65 for (; cpu_num < cpu_online; cpu_num++) {
66 /*
67 * allocate device name here as device_bind_driver() does
68 * not copy device name, 8 bytes are enough for
69 * sizeof("cpu@") + 3 digits cpu number + '\0'
70 */
71 cpu = malloc(8);
72 if (!cpu) {
73 printf("unable to allocate device name\n");
74 return -ENOMEM;
75 }
76 sprintf(cpu, "cpu@%d", cpu_num);
77 ret = device_bind_driver(pdev, "cpu_qemu", cpu, &dev);
78 if (ret) {
79 printf("binding cpu@%d failed: %d\n", cpu_num, ret);
80 return ret;
81 }
Simon Glass71fa5b42020-12-03 16:55:18 -070082 plat = dev_get_parent_plat(dev);
Simon Glass4c8243d2019-12-06 21:42:55 -070083 plat->cpu_id = cpu_num;
84 }
85 return 0;
86}