1use crate::{PhysAddr, TpuError, registers::CPU_ENGINE_DESCRIPTOR_NUM};
4use crate::platform::TPU_DMABUF_HEADER_M;
5
6#[repr(C)]
8#[derive(Debug, Clone, Copy, Default)]
9pub struct DmaHeader {
10 pub dmabuf_magic_m: u16,
11 pub dmabuf_magic_s: u16,
12 pub dmabuf_size: u32,
13 pub cpu_desc_count: u32,
14 pub bd_desc_count: u32,
15 pub tdma_desc_count: u32,
16 pub tpu_clk_rate: u32,
17 pub pmubuf_size: u32,
18 pub pmubuf_offset: u32,
19 pub arraybase_0_l: u32,
20 pub arraybase_0_h: u32,
21 pub arraybase_1_l: u32,
22 pub arraybase_1_h: u32,
23 pub arraybase_2_l: u32,
24 pub arraybase_2_h: u32,
25 pub arraybase_3_l: u32,
26 pub arraybase_3_h: u32,
27 pub arraybase_4_l: u32,
28 pub arraybase_4_h: u32,
29 pub arraybase_5_l: u32,
30 pub arraybase_5_h: u32,
31 pub arraybase_6_l: u32,
32 pub arraybase_6_h: u32,
33 pub arraybase_7_l: u32,
34 pub arraybase_7_h: u32,
35 pub reserve: [u32; 8],
36}
37
38impl DmaHeader {
39 pub const MAGIC: u16 = TPU_DMABUF_HEADER_M;
40
41 pub fn is_valid(&self) -> bool {
42 self.dmabuf_magic_m == Self::MAGIC
44 }
45
46 pub fn arraybase(&self, idx: usize) -> u64 {
47 let (lo, hi) = match idx {
48 0 => (self.arraybase_0_l, self.arraybase_0_h),
49 1 => (self.arraybase_1_l, self.arraybase_1_h),
50 2 => (self.arraybase_2_l, self.arraybase_2_h),
51 3 => (self.arraybase_3_l, self.arraybase_3_h),
52 4 => (self.arraybase_4_l, self.arraybase_4_h),
53 5 => (self.arraybase_5_l, self.arraybase_5_h),
54 6 => (self.arraybase_6_l, self.arraybase_6_h),
55 7 => (self.arraybase_7_l, self.arraybase_7_h),
56 _ => (0, 0),
57 };
58 (lo as u64) | ((hi as u64) << 32)
59 }
60
61 pub fn arraybase_l(&self) -> [u32; 8] {
62 [
63 self.arraybase_0_l, self.arraybase_1_l, self.arraybase_2_l, self.arraybase_3_l,
64 self.arraybase_4_l, self.arraybase_5_l, self.arraybase_6_l, self.arraybase_7_l,
65 ]
66 }
67}
68
69#[derive(Debug, Clone, Copy)]
71pub struct DmabufView<'a> {
72 pub header: &'a DmaHeader,
73 pub descs: &'a [CpuSyncDesc],
74}
75
76pub unsafe fn parse_dmabuf_view<'a>(dmabuf_vaddr: *const u8, dmabuf_len: usize) -> Result<DmabufView<'a>, TpuError> {
83 if dmabuf_vaddr.is_null() {
84 return Err(TpuError::InvalidParameter);
85 }
86
87 let header_size = core::mem::size_of::<DmaHeader>();
88 if dmabuf_len < header_size {
89 return Err(TpuError::InvalidParameter);
90 }
91
92 let header = unsafe { &*(dmabuf_vaddr as *const DmaHeader) };
93 let desc_count = header.cpu_desc_count as usize;
94 let desc_bytes = desc_count
95 .checked_mul(core::mem::size_of::<CpuSyncDesc>())
96 .ok_or(TpuError::InvalidParameter)?;
97 let required = header_size
98 .checked_add(desc_bytes)
99 .ok_or(TpuError::InvalidParameter)?;
100 if required > dmabuf_len {
101 return Err(TpuError::InvalidParameter);
102 }
103
104 let desc_ptr = unsafe { dmabuf_vaddr.add(header_size) as *const CpuSyncDesc };
105 let descs = unsafe { core::slice::from_raw_parts(desc_ptr, desc_count) };
106
107 Ok(DmabufView { header, descs })
108}
109
110#[repr(C)]
112#[derive(Debug, Clone, Copy)]
113pub struct CpuSyncDesc {
114 pub op_type: u32,
115 pub num_bd: u32,
116 pub num_gdma: u32,
117 pub offset_bd: u32,
118 pub offset_gdma: u32,
119 pub reserved: [u32; 2],
120 pub str_data: [u8; (CPU_ENGINE_DESCRIPTOR_NUM - 7) * core::mem::size_of::<u32>()],
121}
122
123impl Default for CpuSyncDesc {
124 fn default() -> Self {
125 Self {
126 op_type: 0,
127 num_bd: 0,
128 num_gdma: 0,
129 offset_bd: 0,
130 offset_gdma: 0,
131 reserved: [0; 2],
132 str_data: [0; (CPU_ENGINE_DESCRIPTOR_NUM - 7) * core::mem::size_of::<u32>()],
133 }
134 }
135}
136
137impl CpuSyncDesc {
138 pub fn bd_count(&self) -> u32 { self.num_bd & 0xFFFF }
139 pub fn tdma_count(&self) -> u32 { self.num_gdma & 0xFFFF }
140}
141
142#[derive(Debug, Clone, Copy, Default)]
144pub struct TpuConfig {
145 pub pmu_buf_size: u32,
146 pub pmu_buf_paddr: PhysAddr,
147}
148
149#[repr(C)]
151#[derive(Debug, Clone, Copy, Default)]
152pub struct TpuTdmaPioInfo {
153 pub paddr_src: u64,
154 pub paddr_dst: u64,
155 pub h: u32,
156 pub w_bytes: u32,
157 pub stride_bytes_src: u32,
158 pub stride_bytes_dst: u32,
159 pub enable_2d: u32,
160 pub leng_bytes: u32,
161}
162
163impl TpuTdmaPioInfo {
164 pub fn is_2d(&self) -> bool { self.enable_2d != 0 }
165}