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