x86: Move qemu CPU fixup function into its own file
[oweals/u-boot.git] / arch / x86 / cpu / qfw_cpu.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2015 Google, Inc
4  */
5
6 #include <common.h>
7 #include <cpu.h>
8 #include <dm.h>
9 #include <qfw.h>
10 #include <dm/lists.h>
11 #include <dm/uclass-internal.h>
12 #include <dm/root.h>
13
14 int qemu_cpu_fixup(void)
15 {
16         int ret;
17         int cpu_num;
18         int cpu_online;
19         struct udevice *dev, *pdev;
20         struct cpu_platdata *plat;
21         char *cpu;
22
23         /* first we need to find '/cpus' */
24         for (device_find_first_child(dm_root(), &pdev);
25              pdev;
26              device_find_next_child(&pdev)) {
27                 if (!strcmp(pdev->name, "cpus"))
28                         break;
29         }
30         if (!pdev) {
31                 printf("unable to find cpus device\n");
32                 return -ENODEV;
33         }
34
35         /* calculate cpus that are already bound */
36         cpu_num = 0;
37         for (uclass_find_first_device(UCLASS_CPU, &dev);
38              dev;
39              uclass_find_next_device(&dev)) {
40                 cpu_num++;
41         }
42
43         /* get actual cpu number */
44         cpu_online = qemu_fwcfg_online_cpus();
45         if (cpu_online < 0) {
46                 printf("unable to get online cpu number: %d\n", cpu_online);
47                 return cpu_online;
48         }
49
50         /* bind addtional cpus */
51         dev = NULL;
52         for (; cpu_num < cpu_online; cpu_num++) {
53                 /*
54                  * allocate device name here as device_bind_driver() does
55                  * not copy device name, 8 bytes are enough for
56                  * sizeof("cpu@") + 3 digits cpu number + '\0'
57                  */
58                 cpu = malloc(8);
59                 if (!cpu) {
60                         printf("unable to allocate device name\n");
61                         return -ENOMEM;
62                 }
63                 sprintf(cpu, "cpu@%d", cpu_num);
64                 ret = device_bind_driver(pdev, "cpu_qemu", cpu, &dev);
65                 if (ret) {
66                         printf("binding cpu@%d failed: %d\n", cpu_num, ret);
67                         return ret;
68                 }
69                 plat = dev_get_parent_platdata(dev);
70                 plat->cpu_id = cpu_num;
71         }
72         return 0;
73 }