mailbox.zig (4225B)
1 const std = @import("std"); 2 3 const mem = @import("../mem.zig"); 4 5 const BOX_STATUS = mem.BASE_ADDRESS + 0xB898; 6 const BOX_READ = mem.BASE_ADDRESS + 0xB880; 7 const BOX_WRITE = mem.BASE_ADDRESS + 0xB8A0; 8 9 const BOX_FULL: u32 = 1 << 31; 10 const BOX_EMPTY: u32 = 1 << 30; 11 const BOX_CHANNEL: u32 = 8; 12 13 const Error = error{ 14 Invalidresponse, 15 }; 16 17 fn Message(comptime T: type) type { 18 return packed struct { 19 message_size: u32, // msg[0] 20 request_code: u32, // msg[1] 21 message_tag: u32, // msg[2] 22 bytes_available: u32, // msg[3] 23 response_code: u32, // msg[4] 24 data: T, // msg[5..] 25 end_tag: u32, // msg[..] 26 27 const Self = @This(); 28 29 pub fn new(tag: u32) Self { 30 return .{ 31 .message_size = @sizeOf(Self), 32 .request_code = 0, 33 .message_tag = tag, 34 .bytes_available = @sizeOf(T), 35 .response_code = 0, 36 .data = std.mem.zeroes(T), 37 .end_tag = 0, 38 }; 39 } 40 41 pub fn send(self: *align(16) Self) !u32 { 42 mem.barrier(.Write); 43 44 while ((mem.get_u32(@ptrFromInt(BOX_STATUS)) & BOX_FULL) != 0) {} 45 46 mem.put_u32_barrier(@ptrFromInt(BOX_WRITE), @intFromPtr(self) | BOX_CHANNEL); 47 48 while ((mem.get_u32(@ptrFromInt(BOX_STATUS)) & BOX_EMPTY) != 0) {} 49 50 const value = mem.get_u32_barrier(@ptrFromInt(BOX_READ)); 51 52 if ((value & 0xf) != BOX_CHANNEL) return Error.Invalidresponse; 53 54 return value; 55 } 56 }; 57 } 58 59 const SERIAL_TAG = 0x00010004; 60 pub fn get_serial_number() !u64 { 61 var message: Message(u64) align(16) = .new(SERIAL_TAG); 62 _ = try message.send(); 63 64 return message.data; 65 } 66 67 const ARM_MEMORY_INFO_TAG = 0x00010005; 68 const VC_MEMORY_INFO_TAG = 0x00010006; 69 const MemoryInfo = packed struct(u64) { 70 base_address: u32, 71 memory_size: u32, 72 }; 73 74 pub fn get_arm_memory_info() !MemoryInfo { 75 var message: Message(MemoryInfo) align(16) = .new(ARM_MEMORY_INFO_TAG); 76 _ = try message.send(); 77 78 return message.data; 79 } 80 81 pub fn get_vc_memory_info() !MemoryInfo { 82 var message: Message(MemoryInfo) align(16) = .new(VC_MEMORY_INFO_TAG); 83 _ = try message.send(); 84 85 return message.data; 86 } 87 88 const MODEL_TAG = 0x00010001; 89 pub fn get_board_model() !u32 { 90 var message: Message(u32) align(16) = .new(MODEL_TAG); 91 _ = try message.send(); 92 93 return message.data; 94 } 95 96 const REVISION_TAG = 0x00010002; 97 pub fn get_board_revision() !u32 { 98 var message: Message(u32) align(16) = .new(REVISION_TAG); 99 _ = try message.send(); 100 101 return message.data; 102 } 103 104 const TEMP_TAG = 0x00030006; 105 pub const TemperatureId = enum(u32) { 106 SoC = 0, 107 ARM = 1, 108 }; 109 pub fn get_temperature(id: TemperatureId) !u32 { 110 const TemperatureRequest = packed struct(u64) { 111 id: u32, 112 value: u32, 113 }; 114 var message: Message(TemperatureRequest) align(16) = .new(TEMP_TAG); 115 message.data.id = @intFromEnum(id); 116 _ = try message.send(); 117 118 return message.data.value; 119 } 120 121 pub const ClockId = enum(u32) { 122 EMMC = 1, 123 UART = 2, 124 ARM = 3, 125 Core = 4, 126 V3D = 5, 127 H254 = 6, 128 ISP = 7, 129 SDRAM = 8, 130 Pixel = 9, 131 PWM = 10, 132 HEVC = 11, 133 EMMC2 = 12, 134 M2MC = 13, 135 PixelBvB = 14, 136 }; 137 138 pub const ClockRate = enum(u32) { 139 Current = 0x00030002, 140 Real = 0x00030047, 141 Max = 0x00030004, 142 Min = 0x00030007, 143 }; 144 145 pub fn get_clock_rate(id: ClockId, rate: ClockRate) !u32 { 146 const GetClockRateRequest = packed struct(u64) { 147 id: u32, 148 rate: u32, 149 }; 150 var message: Message(GetClockRateRequest) align(16) = .new(@intFromEnum(rate)); 151 message.data.id = @intFromEnum(id); 152 _ = try message.send(); 153 154 return message.data.rate; 155 } 156 157 const CLOCK_HZ_SET = 0x00038002; 158 pub fn set_clock_rate(id: ClockId, rate: u32, skip_turbo: bool) !u32 { 159 const SetClockRateRequest = packed struct(u96) { id: u32, rate: u32, skip_turbo: u32 }; 160 var message: Message(SetClockRateRequest) align(16) = .new(CLOCK_HZ_SET); 161 message.data.id = @intFromEnum(id); 162 message.data.skip_turbo = if (skip_turbo) 1 else 0; 163 message.data.rate = rate; 164 _ = try message.send(); 165 166 return message.data.rate; 167 }