1*36adb7c9SRamon Fried // SPDX-License-Identifier: GPL-2.0+
2*36adb7c9SRamon Fried /*
3*36adb7c9SRamon Fried * Onboard memory detection for Snapdragon boards
4*36adb7c9SRamon Fried *
5*36adb7c9SRamon Fried * (C) Copyright 2018 Ramon Fried <ramon.fried@gmail.com>
6*36adb7c9SRamon Fried *
7*36adb7c9SRamon Fried */
8*36adb7c9SRamon Fried
9*36adb7c9SRamon Fried #include <common.h>
10*36adb7c9SRamon Fried #include <dm.h>
11*36adb7c9SRamon Fried #include <smem.h>
12*36adb7c9SRamon Fried #include <fdt_support.h>
13*36adb7c9SRamon Fried #include <asm/arch/dram.h>
14*36adb7c9SRamon Fried
15*36adb7c9SRamon Fried #define SMEM_USABLE_RAM_PARTITION_TABLE 402
16*36adb7c9SRamon Fried #define RAM_PART_NAME_LENGTH 16
17*36adb7c9SRamon Fried #define RAM_NUM_PART_ENTRIES 32
18*36adb7c9SRamon Fried #define CATEGORY_SDRAM 0x0E
19*36adb7c9SRamon Fried #define TYPE_SYSMEM 0x01
20*36adb7c9SRamon Fried
21*36adb7c9SRamon Fried struct smem_ram_ptable_hdr {
22*36adb7c9SRamon Fried u32 magic[2];
23*36adb7c9SRamon Fried u32 version;
24*36adb7c9SRamon Fried u32 reserved;
25*36adb7c9SRamon Fried u32 len;
26*36adb7c9SRamon Fried } __attribute__ ((__packed__));
27*36adb7c9SRamon Fried
28*36adb7c9SRamon Fried struct smem_ram_ptn {
29*36adb7c9SRamon Fried char name[RAM_PART_NAME_LENGTH];
30*36adb7c9SRamon Fried u64 start;
31*36adb7c9SRamon Fried u64 size;
32*36adb7c9SRamon Fried u32 attr;
33*36adb7c9SRamon Fried u32 category;
34*36adb7c9SRamon Fried u32 domain;
35*36adb7c9SRamon Fried u32 type;
36*36adb7c9SRamon Fried u32 num_partitions;
37*36adb7c9SRamon Fried u32 reserved[3];
38*36adb7c9SRamon Fried } __attribute__ ((__packed__));
39*36adb7c9SRamon Fried
40*36adb7c9SRamon Fried struct smem_ram_ptable {
41*36adb7c9SRamon Fried struct smem_ram_ptable_hdr hdr;
42*36adb7c9SRamon Fried u32 reserved; /* Added for 8 bytes alignment of header */
43*36adb7c9SRamon Fried struct smem_ram_ptn parts[RAM_NUM_PART_ENTRIES];
44*36adb7c9SRamon Fried } __attribute__ ((__packed__));
45*36adb7c9SRamon Fried
46*36adb7c9SRamon Fried #ifndef MEMORY_BANKS_MAX
47*36adb7c9SRamon Fried #define MEMORY_BANKS_MAX 4
48*36adb7c9SRamon Fried #endif
49*36adb7c9SRamon Fried
msm_fixup_memory(void * blob)50*36adb7c9SRamon Fried int msm_fixup_memory(void *blob)
51*36adb7c9SRamon Fried {
52*36adb7c9SRamon Fried u64 bank_start[MEMORY_BANKS_MAX];
53*36adb7c9SRamon Fried u64 bank_size[MEMORY_BANKS_MAX];
54*36adb7c9SRamon Fried size_t size;
55*36adb7c9SRamon Fried int i;
56*36adb7c9SRamon Fried int count = 0;
57*36adb7c9SRamon Fried struct udevice *smem;
58*36adb7c9SRamon Fried int ret;
59*36adb7c9SRamon Fried struct smem_ram_ptable *ram_ptable;
60*36adb7c9SRamon Fried struct smem_ram_ptn *p;
61*36adb7c9SRamon Fried
62*36adb7c9SRamon Fried ret = uclass_get_device_by_name(UCLASS_SMEM, "smem", &smem);
63*36adb7c9SRamon Fried if (ret < 0) {
64*36adb7c9SRamon Fried printf("Failed to find SMEM node. Check device tree\n");
65*36adb7c9SRamon Fried return 0;
66*36adb7c9SRamon Fried }
67*36adb7c9SRamon Fried
68*36adb7c9SRamon Fried ram_ptable = smem_get(smem, -1, SMEM_USABLE_RAM_PARTITION_TABLE, &size);
69*36adb7c9SRamon Fried
70*36adb7c9SRamon Fried if (!ram_ptable) {
71*36adb7c9SRamon Fried printf("Failed to find SMEM partition.\n");
72*36adb7c9SRamon Fried return -ENODEV;
73*36adb7c9SRamon Fried }
74*36adb7c9SRamon Fried
75*36adb7c9SRamon Fried /* Check validy of RAM */
76*36adb7c9SRamon Fried for (i = 0; i < RAM_NUM_PART_ENTRIES; i++) {
77*36adb7c9SRamon Fried p = &ram_ptable->parts[i];
78*36adb7c9SRamon Fried if (p->category == CATEGORY_SDRAM && p->type == TYPE_SYSMEM) {
79*36adb7c9SRamon Fried bank_start[count] = p->start;
80*36adb7c9SRamon Fried bank_size[count] = p->size;
81*36adb7c9SRamon Fried debug("Detected memory bank %u: start: 0x%llx size: 0x%llx\n",
82*36adb7c9SRamon Fried count, p->start, p->size);
83*36adb7c9SRamon Fried count++;
84*36adb7c9SRamon Fried }
85*36adb7c9SRamon Fried }
86*36adb7c9SRamon Fried
87*36adb7c9SRamon Fried if (!count) {
88*36adb7c9SRamon Fried printf("Failed to detect any memory bank\n");
89*36adb7c9SRamon Fried return -ENODEV;
90*36adb7c9SRamon Fried }
91*36adb7c9SRamon Fried
92*36adb7c9SRamon Fried ret = fdt_fixup_memory_banks(blob, bank_start, bank_size, count);
93*36adb7c9SRamon Fried if (ret)
94*36adb7c9SRamon Fried return ret;
95*36adb7c9SRamon Fried
96*36adb7c9SRamon Fried return 0;
97*36adb7c9SRamon Fried }
98*36adb7c9SRamon Fried
99