xref: /linux/drivers/gpu/nova-core/gsp/boot.rs (revision e64b9cc293ae710c815c2de1ec9dcaa0784a8017)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 use kernel::{
4     device,
5     dma::Coherent,
6     io::poll::read_poll_timeout,
7     pci,
8     prelude::*,
9     time::Delta, //
10 };
11 
12 use crate::{
13     driver::Bar0,
14     falcon::{
15         gsp::Gsp,
16         sec2::Sec2,
17         Falcon, //
18     },
19     fb::FbLayout,
20     firmware::{
21         booter::{
22             BooterFirmware,
23             BooterKind, //
24         },
25         fwsec::{
26             bootloader::FwsecFirmwareWithBl,
27             FwsecCommand,
28             FwsecFirmware, //
29         },
30         gsp::GspFirmware,
31         FIRMWARE_VERSION, //
32     },
33     gpu::Chipset,
34     gsp::{
35         commands,
36         sequencer::{
37             GspSequencer,
38             GspSequencerParams, //
39         },
40         GspFwWprMeta, //
41     },
42     regs,
43     vbios::Vbios,
44 };
45 
46 impl super::Gsp {
47     /// Helper function to load and run the FWSEC-FRTS firmware and confirm that it has properly
48     /// created the WPR2 region.
49     fn run_fwsec_frts(
50         dev: &device::Device<device::Bound>,
51         chipset: Chipset,
52         falcon: &Falcon<Gsp>,
53         bar: &Bar0,
54         bios: &Vbios,
55         fb_layout: &FbLayout,
56     ) -> Result<()> {
57         // Check that the WPR2 region does not already exists - if it does, we cannot run
58         // FWSEC-FRTS until the GPU is reset.
59         if regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI::read(bar).higher_bound() != 0 {
60             dev_err!(
61                 dev,
62                 "WPR2 region already exists - GPU needs to be reset to proceed\n"
63             );
64             return Err(EBUSY);
65         }
66 
67         // FWSEC-FRTS will create the WPR2 region.
68         let fwsec_frts = FwsecFirmware::new(
69             dev,
70             falcon,
71             bar,
72             bios,
73             FwsecCommand::Frts {
74                 frts_addr: fb_layout.frts.start,
75                 frts_size: fb_layout.frts.len(),
76             },
77         )?;
78 
79         if chipset.needs_fwsec_bootloader() {
80             let fwsec_frts_bl = FwsecFirmwareWithBl::new(fwsec_frts, dev, chipset)?;
81             // Load and run the bootloader, which will load FWSEC-FRTS and run it.
82             fwsec_frts_bl.run(dev, falcon, bar)?;
83         } else {
84             // Load and run FWSEC-FRTS directly.
85             fwsec_frts.run(dev, falcon, bar)?;
86         }
87 
88         // SCRATCH_E contains the error code for FWSEC-FRTS.
89         let frts_status = regs::NV_PBUS_SW_SCRATCH_0E_FRTS_ERR::read(bar).frts_err_code();
90         if frts_status != 0 {
91             dev_err!(
92                 dev,
93                 "FWSEC-FRTS returned with error code {:#x}\n",
94                 frts_status
95             );
96 
97             return Err(EIO);
98         }
99 
100         // Check that the WPR2 region has been created as we requested.
101         let (wpr2_lo, wpr2_hi) = (
102             regs::NV_PFB_PRI_MMU_WPR2_ADDR_LO::read(bar).lower_bound(),
103             regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI::read(bar).higher_bound(),
104         );
105 
106         match (wpr2_lo, wpr2_hi) {
107             (_, 0) => {
108                 dev_err!(dev, "WPR2 region not created after running FWSEC-FRTS\n");
109 
110                 Err(EIO)
111             }
112             (wpr2_lo, _) if wpr2_lo != fb_layout.frts.start => {
113                 dev_err!(
114                     dev,
115                     "WPR2 region created at unexpected address {:#x}; expected {:#x}\n",
116                     wpr2_lo,
117                     fb_layout.frts.start,
118                 );
119 
120                 Err(EIO)
121             }
122             (wpr2_lo, wpr2_hi) => {
123                 dev_dbg!(dev, "WPR2: {:#x}-{:#x}\n", wpr2_lo, wpr2_hi);
124                 dev_dbg!(dev, "GPU instance built\n");
125 
126                 Ok(())
127             }
128         }
129     }
130 
131     /// Attempt to boot the GSP.
132     ///
133     /// This is a GPU-dependent and complex procedure that involves loading firmware files from
134     /// user-space, patching them with signatures, and building firmware-specific intricate data
135     /// structures that the GSP will use at runtime.
136     ///
137     /// Upon return, the GSP is up and running, and its runtime object given as return value.
138     pub(crate) fn boot(
139         self: Pin<&mut Self>,
140         pdev: &pci::Device<device::Bound>,
141         bar: &Bar0,
142         chipset: Chipset,
143         gsp_falcon: &Falcon<Gsp>,
144         sec2_falcon: &Falcon<Sec2>,
145     ) -> Result {
146         let dev = pdev.as_ref();
147 
148         let bios = Vbios::new(dev, bar)?;
149 
150         let gsp_fw = KBox::pin_init(GspFirmware::new(dev, chipset, FIRMWARE_VERSION), GFP_KERNEL)?;
151 
152         let fb_layout = FbLayout::new(chipset, bar, &gsp_fw)?;
153         dev_dbg!(dev, "{:#x?}\n", fb_layout);
154 
155         Self::run_fwsec_frts(dev, chipset, gsp_falcon, bar, &bios, &fb_layout)?;
156 
157         let booter_loader = BooterFirmware::new(
158             dev,
159             BooterKind::Loader,
160             chipset,
161             FIRMWARE_VERSION,
162             sec2_falcon,
163             bar,
164         )?;
165 
166         let wpr_meta = Coherent::init(dev, GFP_KERNEL, GspFwWprMeta::new(&gsp_fw, &fb_layout))?;
167 
168         self.cmdq
169             .send_command_no_wait(bar, commands::SetSystemInfo::new(pdev))?;
170         self.cmdq
171             .send_command_no_wait(bar, commands::SetRegistry::new())?;
172 
173         gsp_falcon.reset(bar)?;
174         let libos_handle = self.libos.dma_handle();
175         let (mbox0, mbox1) = gsp_falcon.boot(
176             bar,
177             Some(libos_handle as u32),
178             Some((libos_handle >> 32) as u32),
179         )?;
180         dev_dbg!(pdev, "GSP MBOX0: {:#x}, MBOX1: {:#x}\n", mbox0, mbox1);
181 
182         dev_dbg!(
183             pdev,
184             "Using SEC2 to load and run the booter_load firmware...\n"
185         );
186 
187         sec2_falcon.reset(bar)?;
188         sec2_falcon.load(dev, bar, &booter_loader)?;
189         let wpr_handle = wpr_meta.dma_handle();
190         let (mbox0, mbox1) = sec2_falcon.boot(
191             bar,
192             Some(wpr_handle as u32),
193             Some((wpr_handle >> 32) as u32),
194         )?;
195         dev_dbg!(pdev, "SEC2 MBOX0: {:#x}, MBOX1{:#x}\n", mbox0, mbox1);
196 
197         if mbox0 != 0 {
198             dev_err!(pdev, "Booter-load failed with error {:#x}\n", mbox0);
199             return Err(ENODEV);
200         }
201 
202         gsp_falcon.write_os_version(bar, gsp_fw.bootloader.app_version);
203 
204         // Poll for RISC-V to become active before running sequencer
205         read_poll_timeout(
206             || Ok(gsp_falcon.is_riscv_active(bar)),
207             |val: &bool| *val,
208             Delta::from_millis(10),
209             Delta::from_secs(5),
210         )?;
211 
212         dev_dbg!(pdev, "RISC-V active? {}\n", gsp_falcon.is_riscv_active(bar),);
213 
214         // Create and run the GSP sequencer.
215         let seq_params = GspSequencerParams {
216             bootloader_app_version: gsp_fw.bootloader.app_version,
217             libos_dma_handle: libos_handle,
218             gsp_falcon,
219             sec2_falcon,
220             dev: pdev.as_ref().into(),
221             bar,
222         };
223         GspSequencer::run(&self.cmdq, seq_params)?;
224 
225         // Wait until GSP is fully initialized.
226         commands::wait_gsp_init_done(&self.cmdq)?;
227 
228         // Obtain and display basic GPU information.
229         let info = commands::get_gsp_info(&self.cmdq, bar)?;
230         match info.gpu_name() {
231             Ok(name) => dev_info!(pdev, "GPU name: {}\n", name),
232             Err(e) => dev_warn!(pdev, "GPU name unavailable: {:?}\n", e),
233         }
234 
235         Ok(())
236     }
237 }
238