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