1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> 4 */ 5 6 #include <common.h> 7 #include <cpu.h> 8 #include <dm.h> 9 #include <errno.h> 10 #include <dm/device-internal.h> 11 #include <dm/lists.h> 12 13 DECLARE_GLOBAL_DATA_PTR; 14 15 static int riscv_cpu_get_desc(struct udevice *dev, char *buf, int size) 16 { 17 const char *isa; 18 19 isa = dev_read_string(dev, "riscv,isa"); 20 if (size < (strlen(isa) + 1)) 21 return -ENOSPC; 22 23 strcpy(buf, isa); 24 25 return 0; 26 } 27 28 static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info) 29 { 30 const char *mmu; 31 32 dev_read_u32(dev, "clock-frequency", (u32 *)&info->cpu_freq); 33 34 mmu = dev_read_string(dev, "mmu-type"); 35 if (!mmu) 36 info->features |= BIT(CPU_FEAT_MMU); 37 38 return 0; 39 } 40 41 static int riscv_cpu_get_count(struct udevice *dev) 42 { 43 ofnode node; 44 int num = 0; 45 46 ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) { 47 const char *device_type; 48 49 device_type = ofnode_read_string(node, "device_type"); 50 if (!device_type) 51 continue; 52 if (strcmp(device_type, "cpu") == 0) 53 num++; 54 } 55 56 return num; 57 } 58 59 static int riscv_cpu_bind(struct udevice *dev) 60 { 61 struct cpu_platdata *plat = dev_get_parent_platdata(dev); 62 struct driver *drv; 63 int ret; 64 65 /* save the hart id */ 66 plat->cpu_id = dev_read_addr(dev); 67 /* first examine the property in current cpu node */ 68 ret = dev_read_u32(dev, "timebase-frequency", &plat->timebase_freq); 69 /* if not found, then look at the parent /cpus node */ 70 if (ret) 71 dev_read_u32(dev->parent, "timebase-frequency", 72 &plat->timebase_freq); 73 74 /* 75 * Bind riscv-timer driver on boot hart. 76 * 77 * We only instantiate one timer device which is enough for U-Boot. 78 * Pass the "timebase-frequency" value as the driver data for the 79 * timer device. 80 * 81 * Return value is not checked since it's possible that the timer 82 * driver is not included. 83 */ 84 if (plat->cpu_id == gd->arch.boot_hart && plat->timebase_freq) { 85 drv = lists_driver_lookup_name("riscv_timer"); 86 if (!drv) { 87 debug("Cannot find the timer driver, not included?\n"); 88 return 0; 89 } 90 91 device_bind_with_driver_data(dev, drv, "riscv_timer", 92 plat->timebase_freq, ofnode_null(), 93 NULL); 94 } 95 96 return 0; 97 } 98 99 static const struct cpu_ops riscv_cpu_ops = { 100 .get_desc = riscv_cpu_get_desc, 101 .get_info = riscv_cpu_get_info, 102 .get_count = riscv_cpu_get_count, 103 }; 104 105 static const struct udevice_id riscv_cpu_ids[] = { 106 { .compatible = "riscv" }, 107 { } 108 }; 109 110 U_BOOT_DRIVER(riscv_cpu) = { 111 .name = "riscv_cpu", 112 .id = UCLASS_CPU, 113 .of_match = riscv_cpu_ids, 114 .bind = riscv_cpu_bind, 115 .ops = &riscv_cpu_ops, 116 .flags = DM_FLAG_PRE_RELOC, 117 }; 118