xref: /qemu/rust/hw/char/pl011/src/device_class.rs (revision 513823e7521a09ed7ad1e32e6454bac3b2cbf52d)
1 // Copyright 2024, Linaro Limited
2 // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
3 // SPDX-License-Identifier: GPL-2.0-or-later
4 
5 use core::ptr::NonNull;
6 use std::os::raw::{c_int, c_void};
7 
8 use qemu_api::{
9     bindings::*, c_str, prelude::*, vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct,
10     vmstate_subsections, vmstate_unused, zeroable::Zeroable,
11 };
12 
13 use crate::device::{PL011Registers, PL011State};
14 
15 extern "C" fn pl011_clock_needed(opaque: *mut c_void) -> bool {
16     let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
17     unsafe { state.as_ref().migrate_clock }
18 }
19 
20 /// Migration subsection for [`PL011State`] clock.
21 static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription {
22     name: c_str!("pl011/clock").as_ptr(),
23     version_id: 1,
24     minimum_version_id: 1,
25     needed: Some(pl011_clock_needed),
26     fields: vmstate_fields! {
27         vmstate_clock!(PL011State, clock),
28     },
29     ..Zeroable::ZERO
30 };
31 
32 extern "C" fn pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int {
33     let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
34     let result = unsafe { state.as_ref().post_load(version_id as u32) };
35     if result.is_err() {
36         -1
37     } else {
38         0
39     }
40 }
41 
42 static VMSTATE_PL011_REGS: VMStateDescription = VMStateDescription {
43     name: c_str!("pl011/regs").as_ptr(),
44     version_id: 2,
45     minimum_version_id: 2,
46     fields: vmstate_fields! {
47         vmstate_of!(PL011Registers, flags),
48         vmstate_of!(PL011Registers, line_control),
49         vmstate_of!(PL011Registers, receive_status_error_clear),
50         vmstate_of!(PL011Registers, control),
51         vmstate_of!(PL011Registers, dmacr),
52         vmstate_of!(PL011Registers, int_enabled),
53         vmstate_of!(PL011Registers, int_level),
54         vmstate_of!(PL011Registers, read_fifo),
55         vmstate_of!(PL011Registers, ilpr),
56         vmstate_of!(PL011Registers, ibrd),
57         vmstate_of!(PL011Registers, fbrd),
58         vmstate_of!(PL011Registers, ifl),
59         vmstate_of!(PL011Registers, read_pos),
60         vmstate_of!(PL011Registers, read_count),
61         vmstate_of!(PL011Registers, read_trigger),
62     },
63     ..Zeroable::ZERO
64 };
65 
66 pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
67     name: c_str!("pl011").as_ptr(),
68     version_id: 2,
69     minimum_version_id: 2,
70     post_load: Some(pl011_post_load),
71     fields: vmstate_fields! {
72         vmstate_unused!(core::mem::size_of::<u32>()),
73         vmstate_struct!(PL011State, regs, &VMSTATE_PL011_REGS, BqlRefCell<PL011Registers>),
74     },
75     subsections: vmstate_subsections! {
76         VMSTATE_PL011_CLOCK
77     },
78     ..Zeroable::ZERO
79 };
80 
81 qemu_api::declare_properties! {
82     PL011_PROPERTIES,
83     qemu_api::define_property!(
84         c_str!("chardev"),
85         PL011State,
86         char_backend,
87         unsafe { &qdev_prop_chr },
88         CharBackend
89     ),
90     qemu_api::define_property!(
91         c_str!("migrate-clk"),
92         PL011State,
93         migrate_clock,
94         unsafe { &qdev_prop_bool },
95         bool,
96         default = true
97     ),
98 }
99