Skip to content

Commit ec167d3

Browse files
committed
implement a reg iterator on property value
1 parent e386b7e commit ec167d3

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

src/Property.zig

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,88 @@ pub const Value = struct {
444444
try shared.customExpectEqual(iter.next(), 0xFFFFFFFFFFFFFFFF);
445445
try shared.customExpectEqual(iter.next(), null);
446446
}
447+
448+
pub const RegValue = struct {
449+
address: u64,
450+
size: u64,
451+
};
452+
453+
/// Iterate over the value as a list of `RegValue`s.
454+
///
455+
/// `address_cells` and `size_cells` must be less than or equal to 2.
456+
pub fn regIterator(self: Value, address_cells: u32, size_cells: u32) ListIteratorError!RegIterator {
457+
const size_of_one_element = (address_cells + size_cells) * @sizeOf(u32);
458+
if (self._raw.len % size_of_one_element != 0) {
459+
@branchHint(.cold);
460+
return error.SizeNotMultiple;
461+
}
462+
463+
// TODO: support address_cells and size_cells greater than two
464+
if (address_cells > 2 or size_cells > 2) {
465+
@panic("address_cells or size_cells greater than two is not supported");
466+
}
467+
468+
return .{
469+
.cells = std.mem.bytesAsSlice(u32, self._raw),
470+
.address_cells = address_cells,
471+
.size_cells = size_cells,
472+
};
473+
}
474+
475+
test regIterator {
476+
const dt: DeviceTree = try .fromSlice(shared.test_dtb);
477+
478+
const flash_node = (try dt.firstMatchingNode(.{ .name = "flash" })).?.node;
479+
480+
const reg_property = (try flash_node.firstMatchingProperty(dt, .{
481+
.name = "reg",
482+
})).?;
483+
484+
var iter = try reg_property.value.regIterator(2, 2);
485+
try shared.customExpectEqual(iter.next(), .{
486+
.address = 0x20000000,
487+
.size = 0x2000000,
488+
});
489+
try shared.customExpectEqual(iter.next(), .{
490+
.address = 0x22000000,
491+
.size = 0x2000000,
492+
});
493+
try shared.customExpectEqual(iter.next(), null);
494+
}
495+
496+
pub const RegIterator = struct {
497+
cells: []align(1) const u32,
498+
499+
address_cells: u32,
500+
size_cells: u32,
501+
502+
pub fn next(self: *RegIterator) ?RegValue {
503+
if (self.cells.len == 0) return null;
504+
505+
// TODO: support address_cells and size_cells greater than two
506+
std.debug.assert(self.address_cells <= 2);
507+
std.debug.assert(self.size_cells <= 2);
508+
509+
var address: u64 = 0;
510+
for (0..self.address_cells) |i| {
511+
const value: u64 = shared.bigToNative(u32, self.cells[i]);
512+
address |= value << @intCast((self.address_cells - i - 1) * 32);
513+
}
514+
self.cells = self.cells[self.address_cells..];
515+
516+
var size: u64 = 0;
517+
for (0..self.size_cells) |i| {
518+
const value: u64 = shared.bigToNative(u32, self.cells[i]);
519+
size |= value << @intCast((self.size_cells - i - 1) * 32);
520+
}
521+
self.cells = self.cells[self.size_cells..];
522+
523+
return .{
524+
.address = address,
525+
.size = size,
526+
};
527+
}
528+
};
447529
};
448530

449531
pub const Match = union(enum) {

0 commit comments

Comments
 (0)