summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nova/gsp.rs
blob: 53367aba221072c2615e452f5048a83a5c94cdbb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use kernel::{
    error::Result,
    c_str,
    firmware::{Firmware},
    pci,
    dma::{CoherentAllocation, CoherentAllocator,try_alloc_coherent},
};

use alloc::vec::Vec;
use crate::driver::align;

const GSP_PAGE_SHIFT: u32 = 12;
const GSP_PAGE_SIZE: u32 = 1 << GSP_PAGE_SHIFT;

#[derive(Default)]
pub(crate) struct GspRadix3 {
    pub(crate) mem: Vec<CoherentAllocation<u64, CoherentAllocator>>,
}

impl GspRadix3 {

    pub (crate) fn try_new(size: usize, dev: &mut pci::Device) -> Result<GspRadix3>
    {
        let mut gsp_radix3: GspRadix3 = Default::default();
        let mut lvl_size = size;
        let addr = 0;
        for i in (0..2).rev() {
            let tbl_size: usize = align::<usize>((lvl_size as usize / 4096) * 8 as usize, GSP_PAGE_SIZE as usize);

            gsp_radix3.mem.try_push(try_alloc_coherent(dev, tbl_size as usize, false)?)?;

            if i == 2 {
		// TODO this is the main piece
            } else {
                for j in 0..size / GSP_PAGE_SIZE as usize {
                    let entry: u64 = (addr + GSP_PAGE_SIZE as usize * j) as u64;
                    gsp_radix3.mem[i].write(j, &entry);
                }
            }

            lvl_size = tbl_size;
        }
        Ok(gsp_radix3)
    }

}

pub(crate) struct Gsp {
    booter_load_fw: Firmware,
    booter_unload_fw: Firmware,
    gsp_fw: Firmware,
    radix3: Option<GspRadix3>,
}

impl Gsp {
    pub(crate) fn new() -> Self
    {
        Self {
            booter_load_fw: Firmware::new(),
            booter_unload_fw: Firmware::new(),
            gsp_fw: Firmware::new(),
            radix3: None,
        }
    }

    pub(crate) fn init(&mut self, dev: &mut pci::Device) -> Result {
        match self.booter_load_fw.request(c_str!("nvidia/ad102/gsp/booter_load-535.113.01.bin"), dev) {
            Err(e) => return Err(e),
            Ok(_) => ()
        }

        match self.booter_unload_fw.request(c_str!("nvidia/ad102/gsp/booter_unload-535.113.01.bin"), dev) {
            Err(e) => return Err(e),
            Ok(_) => ()
        }

        match self.gsp_fw.request(c_str!("nvidia/ad102/gsp/gsp-535.113.01.bin"), dev) {
            Err(e) => return Err(e),
            Ok(_) => (),
        }

        self.radix3 = Some(GspRadix3::try_new(1024, dev)?);
        Ok(())
    }
}