1 // Copyright 2023, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! High-level FDT functions.
16 
17 use core::ops::Range;
18 use cstr::cstr;
19 use libfdt::{self, Fdt, FdtError};
20 
21 /// Represents information about a SWIOTLB buffer.
22 #[derive(Debug)]
23 pub struct SwiotlbInfo {
24     /// The address of the SWIOTLB buffer, if available.
25     pub addr: Option<usize>,
26     /// The size of the SWIOTLB buffer.
27     pub size: usize,
28     /// The alignment of the SWIOTLB buffer, if available.
29     pub align: Option<usize>,
30 }
31 
32 impl SwiotlbInfo {
33     /// Creates a `SwiotlbInfo` struct from the given device tree.
new_from_fdt(fdt: &Fdt) -> libfdt::Result<SwiotlbInfo>34     pub fn new_from_fdt(fdt: &Fdt) -> libfdt::Result<SwiotlbInfo> {
35         let node =
36             fdt.compatible_nodes(cstr!("restricted-dma-pool"))?.next().ok_or(FdtError::NotFound)?;
37 
38         let (addr, size, align) = if let Some(mut reg) = node.reg()? {
39             let reg = reg.next().ok_or(FdtError::NotFound)?;
40             let size = reg.size.ok_or(FdtError::NotFound)?;
41             (Some(reg.addr.try_into().unwrap()), size.try_into().unwrap(), None)
42         } else {
43             let size = node.getprop_u64(cstr!("size"))?.ok_or(FdtError::NotFound)?;
44             let align = node.getprop_u64(cstr!("alignment"))?.ok_or(FdtError::NotFound)?;
45             (None, size.try_into().unwrap(), Some(align.try_into().unwrap()))
46         };
47         Ok(Self { addr, size, align })
48     }
49 
50     /// Returns the fixed range of memory mapped by the SWIOTLB buffer, if available.
fixed_range(&self) -> Option<Range<usize>>51     pub fn fixed_range(&self) -> Option<Range<usize>> {
52         self.addr.map(|addr| addr..addr + self.size)
53     }
54 }
55