blob: 27d51ef7891451d058af702a96c5229e62366de6 [file] [log] [blame]
Ramon Fried36adb7c2018-07-31 12:29:57 +03001// SPDX-License-Identifier: GPL-2.0+
2/*
Caleb Connolly3de41f92023-11-07 14:58:23 +00003 * Miscellaneous Snapdragon functionality
Ramon Fried36adb7c2018-07-31 12:29:57 +03004 *
5 * (C) Copyright 2018 Ramon Fried <ramon.fried@gmail.com>
6 *
7 */
8
9#include <common.h>
10#include <dm.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060011#include <log.h>
Caleb Connolly3de41f92023-11-07 14:58:23 +000012#include <mmc.h>
Simon Glasse6f6f9e2020-05-10 11:39:58 -060013#include <part.h>
Ramon Fried36adb7c2018-07-31 12:29:57 +030014#include <smem.h>
15#include <fdt_support.h>
Caleb Connolly3de41f92023-11-07 14:58:23 +000016#include <asm/unaligned.h>
17
18#include "misc.h"
19
20/* UNSTUFF_BITS macro taken from Linux Kernel: drivers/mmc/core/sd.c */
21#define UNSTUFF_BITS(resp, start, size) \
22 ({ \
23 const int __size = size; \
24 const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
25 const int __off = 3 - ((start) / 32); \
26 const int __shft = (start) & 31; \
27 u32 __res; \
28 \
29 __res = resp[__off] >> __shft; \
30 if (__size + __shft > 32) \
31 __res |= resp[__off - 1] << ((32 - __shft) % 32); \
32 __res & __mask; \
33 })
34
35u32 msm_board_serial(void)
36{
37 struct mmc *mmc_dev;
38
39 mmc_dev = find_mmc_device(0);
40 if (!mmc_dev)
41 return 0;
42
43 if (mmc_init(mmc_dev))
44 return 0;
45
46 return UNSTUFF_BITS(mmc_dev->cid, 16, 32);
47}
48
49void msm_generate_mac_addr(u8 *mac)
50{
51 /* use locally adminstrated pool */
52 mac[0] = 0x02;
53 mac[1] = 0x00;
54
55 /*
56 * Put the 32-bit serial number in the last 32-bit of the MAC address.
57 * Use big endian order so it is consistent with the serial number
58 * written as a hexadecimal string, e.g. 0x1234abcd -> 02:00:12:34:ab:cd
59 */
60 put_unaligned_be32(msm_board_serial(), &mac[2]);
61}
Ramon Fried36adb7c2018-07-31 12:29:57 +030062
63#define SMEM_USABLE_RAM_PARTITION_TABLE 402
64#define RAM_PART_NAME_LENGTH 16
65#define RAM_NUM_PART_ENTRIES 32
66#define CATEGORY_SDRAM 0x0E
67#define TYPE_SYSMEM 0x01
68
69struct smem_ram_ptable_hdr {
70 u32 magic[2];
71 u32 version;
72 u32 reserved;
73 u32 len;
74} __attribute__ ((__packed__));
75
76struct smem_ram_ptn {
77 char name[RAM_PART_NAME_LENGTH];
78 u64 start;
79 u64 size;
80 u32 attr;
81 u32 category;
82 u32 domain;
83 u32 type;
84 u32 num_partitions;
85 u32 reserved[3];
86} __attribute__ ((__packed__));
87
88struct smem_ram_ptable {
89 struct smem_ram_ptable_hdr hdr;
90 u32 reserved; /* Added for 8 bytes alignment of header */
91 struct smem_ram_ptn parts[RAM_NUM_PART_ENTRIES];
92} __attribute__ ((__packed__));
93
94#ifndef MEMORY_BANKS_MAX
95#define MEMORY_BANKS_MAX 4
96#endif
97
98int msm_fixup_memory(void *blob)
99{
100 u64 bank_start[MEMORY_BANKS_MAX];
101 u64 bank_size[MEMORY_BANKS_MAX];
102 size_t size;
103 int i;
104 int count = 0;
105 struct udevice *smem;
106 int ret;
107 struct smem_ram_ptable *ram_ptable;
108 struct smem_ram_ptn *p;
109
110 ret = uclass_get_device_by_name(UCLASS_SMEM, "smem", &smem);
111 if (ret < 0) {
112 printf("Failed to find SMEM node. Check device tree\n");
113 return 0;
114 }
115
116 ram_ptable = smem_get(smem, -1, SMEM_USABLE_RAM_PARTITION_TABLE, &size);
117
118 if (!ram_ptable) {
119 printf("Failed to find SMEM partition.\n");
120 return -ENODEV;
121 }
122
123 /* Check validy of RAM */
124 for (i = 0; i < RAM_NUM_PART_ENTRIES; i++) {
125 p = &ram_ptable->parts[i];
126 if (p->category == CATEGORY_SDRAM && p->type == TYPE_SYSMEM) {
127 bank_start[count] = p->start;
128 bank_size[count] = p->size;
129 debug("Detected memory bank %u: start: 0x%llx size: 0x%llx\n",
130 count, p->start, p->size);
131 count++;
132 }
133 }
134
135 if (!count) {
136 printf("Failed to detect any memory bank\n");
137 return -ENODEV;
138 }
139
140 ret = fdt_fixup_memory_banks(blob, bank_start, bank_size, count);
141 if (ret)
142 return ret;
143
144 return 0;
145}
Caleb Connolly3de41f92023-11-07 14:58:23 +0000146