xref: /qemu/rust/hw/char/pl011/src/device_class.rs (revision 24f0e8d818b931758b6dc47f973a6b1b80ecee1f)
137fdb2f5SManos Pitsidianakis // Copyright 2024, Linaro Limited
237fdb2f5SManos Pitsidianakis // Author(s): Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
337fdb2f5SManos Pitsidianakis // SPDX-License-Identifier: GPL-2.0-or-later
437fdb2f5SManos Pitsidianakis 
5718e255fSPaolo Bonzini use core::ptr::NonNull;
6718e255fSPaolo Bonzini use std::os::raw::{c_int, c_void};
737fdb2f5SManos Pitsidianakis 
893243319SManos Pitsidianakis use qemu_api::{
9b800a313SPaolo Bonzini     bindings::*, c_str, vmstate_clock, vmstate_fields, vmstate_of, vmstate_subsections,
10b800a313SPaolo Bonzini     vmstate_unused, zeroable::Zeroable,
1193243319SManos Pitsidianakis };
1237fdb2f5SManos Pitsidianakis 
13b800a313SPaolo Bonzini use crate::device::PL011State;
1437fdb2f5SManos Pitsidianakis 
1593243319SManos Pitsidianakis extern "C" fn pl011_clock_needed(opaque: *mut c_void) -> bool {
1693243319SManos Pitsidianakis     unsafe {
1793243319SManos Pitsidianakis         debug_assert!(!opaque.is_null());
1893243319SManos Pitsidianakis         let state = NonNull::new_unchecked(opaque.cast::<PL011State>());
1993243319SManos Pitsidianakis         state.as_ref().migrate_clock
2093243319SManos Pitsidianakis     }
2193243319SManos Pitsidianakis }
2293243319SManos Pitsidianakis 
2393243319SManos Pitsidianakis /// Migration subsection for [`PL011State`] clock.
2493243319SManos Pitsidianakis pub static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription {
25718e255fSPaolo Bonzini     name: c_str!("pl011/clock").as_ptr(),
2693243319SManos Pitsidianakis     version_id: 1,
2793243319SManos Pitsidianakis     minimum_version_id: 1,
2893243319SManos Pitsidianakis     needed: Some(pl011_clock_needed),
2993243319SManos Pitsidianakis     fields: vmstate_fields! {
30*24f0e8d8SPaolo Bonzini         vmstate_clock!(PL011State, clock),
3193243319SManos Pitsidianakis     },
3293243319SManos Pitsidianakis     ..Zeroable::ZERO
3393243319SManos Pitsidianakis };
3493243319SManos Pitsidianakis 
3593243319SManos Pitsidianakis extern "C" fn pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int {
3693243319SManos Pitsidianakis     unsafe {
3793243319SManos Pitsidianakis         debug_assert!(!opaque.is_null());
3893243319SManos Pitsidianakis         let mut state = NonNull::new_unchecked(opaque.cast::<PL011State>());
3993243319SManos Pitsidianakis         let result = state.as_mut().post_load(version_id as u32);
4093243319SManos Pitsidianakis         if result.is_err() {
4193243319SManos Pitsidianakis             -1
4293243319SManos Pitsidianakis         } else {
4393243319SManos Pitsidianakis             0
4493243319SManos Pitsidianakis         }
4593243319SManos Pitsidianakis     }
4693243319SManos Pitsidianakis }
4793243319SManos Pitsidianakis 
4837fdb2f5SManos Pitsidianakis pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
49718e255fSPaolo Bonzini     name: c_str!("pl011").as_ptr(),
5093243319SManos Pitsidianakis     version_id: 2,
5193243319SManos Pitsidianakis     minimum_version_id: 2,
5293243319SManos Pitsidianakis     post_load: Some(pl011_post_load),
5393243319SManos Pitsidianakis     fields: vmstate_fields! {
5493243319SManos Pitsidianakis         vmstate_unused!(core::mem::size_of::<u32>()),
55b800a313SPaolo Bonzini         vmstate_of!(PL011State, flags),
56b800a313SPaolo Bonzini         vmstate_of!(PL011State, line_control),
57b800a313SPaolo Bonzini         vmstate_of!(PL011State, receive_status_error_clear),
58b800a313SPaolo Bonzini         vmstate_of!(PL011State, control),
59b800a313SPaolo Bonzini         vmstate_of!(PL011State, dmacr),
60b800a313SPaolo Bonzini         vmstate_of!(PL011State, int_enabled),
61b800a313SPaolo Bonzini         vmstate_of!(PL011State, int_level),
62b800a313SPaolo Bonzini         vmstate_of!(PL011State, read_fifo),
63b800a313SPaolo Bonzini         vmstate_of!(PL011State, ilpr),
64b800a313SPaolo Bonzini         vmstate_of!(PL011State, ibrd),
65b800a313SPaolo Bonzini         vmstate_of!(PL011State, fbrd),
66b800a313SPaolo Bonzini         vmstate_of!(PL011State, ifl),
67b800a313SPaolo Bonzini         vmstate_of!(PL011State, read_pos),
68b800a313SPaolo Bonzini         vmstate_of!(PL011State, read_count),
69b800a313SPaolo Bonzini         vmstate_of!(PL011State, read_trigger),
7093243319SManos Pitsidianakis     },
7193243319SManos Pitsidianakis     subsections: vmstate_subsections! {
7293243319SManos Pitsidianakis         VMSTATE_PL011_CLOCK
7393243319SManos Pitsidianakis     },
746e50bde1SPaolo Bonzini     ..Zeroable::ZERO
7537fdb2f5SManos Pitsidianakis };
7637fdb2f5SManos Pitsidianakis 
7737fdb2f5SManos Pitsidianakis qemu_api::declare_properties! {
7837fdb2f5SManos Pitsidianakis     PL011_PROPERTIES,
7937fdb2f5SManos Pitsidianakis     qemu_api::define_property!(
80718e255fSPaolo Bonzini         c_str!("chardev"),
8137fdb2f5SManos Pitsidianakis         PL011State,
8237fdb2f5SManos Pitsidianakis         char_backend,
8337fdb2f5SManos Pitsidianakis         unsafe { &qdev_prop_chr },
8437fdb2f5SManos Pitsidianakis         CharBackend
8537fdb2f5SManos Pitsidianakis     ),
8637fdb2f5SManos Pitsidianakis     qemu_api::define_property!(
87718e255fSPaolo Bonzini         c_str!("migrate-clk"),
8837fdb2f5SManos Pitsidianakis         PL011State,
8937fdb2f5SManos Pitsidianakis         migrate_clock,
9037fdb2f5SManos Pitsidianakis         unsafe { &qdev_prop_bool },
91113c6688SPaolo Bonzini         bool,
92113c6688SPaolo Bonzini         default = true
9337fdb2f5SManos Pitsidianakis     ),
9437fdb2f5SManos Pitsidianakis }
95