xref: /qemu/rust/hw/char/pl011/src/device_class.rs (revision a1ab4eed8d37e4afb78367d766edeadfdb489027)
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::{
9*a1ab4eedSPaolo Bonzini     bindings::*, c_str, prelude::*, vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct,
1049bfe63fSPaolo Bonzini     vmstate_subsections, vmstate_unused, zeroable::Zeroable,
1193243319SManos Pitsidianakis };
1237fdb2f5SManos Pitsidianakis 
1349bfe63fSPaolo Bonzini use crate::device::{PL011Registers, PL011State};
1437fdb2f5SManos Pitsidianakis 
157d052039SPaolo Bonzini #[allow(clippy::missing_const_for_fn)]
1693243319SManos Pitsidianakis extern "C" fn pl011_clock_needed(opaque: *mut c_void) -> bool {
177d052039SPaolo Bonzini     let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
187d052039SPaolo Bonzini     unsafe { state.as_ref().migrate_clock }
1993243319SManos Pitsidianakis }
2093243319SManos Pitsidianakis 
2193243319SManos Pitsidianakis /// Migration subsection for [`PL011State`] clock.
22d1f27ae9SPaolo Bonzini static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription {
23718e255fSPaolo Bonzini     name: c_str!("pl011/clock").as_ptr(),
2493243319SManos Pitsidianakis     version_id: 1,
2593243319SManos Pitsidianakis     minimum_version_id: 1,
2693243319SManos Pitsidianakis     needed: Some(pl011_clock_needed),
2793243319SManos Pitsidianakis     fields: vmstate_fields! {
2824f0e8d8SPaolo Bonzini         vmstate_clock!(PL011State, clock),
2993243319SManos Pitsidianakis     },
3093243319SManos Pitsidianakis     ..Zeroable::ZERO
3193243319SManos Pitsidianakis };
3293243319SManos Pitsidianakis 
3393243319SManos Pitsidianakis extern "C" fn pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int {
34*a1ab4eedSPaolo Bonzini     let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
35*a1ab4eedSPaolo Bonzini     let result = unsafe { state.as_ref().post_load(version_id as u32) };
3693243319SManos Pitsidianakis     if result.is_err() {
3793243319SManos Pitsidianakis         -1
3893243319SManos Pitsidianakis     } else {
3993243319SManos Pitsidianakis         0
4093243319SManos Pitsidianakis     }
4193243319SManos Pitsidianakis }
4293243319SManos Pitsidianakis 
4349bfe63fSPaolo Bonzini static VMSTATE_PL011_REGS: VMStateDescription = VMStateDescription {
4449bfe63fSPaolo Bonzini     name: c_str!("pl011/regs").as_ptr(),
4549bfe63fSPaolo Bonzini     version_id: 2,
4649bfe63fSPaolo Bonzini     minimum_version_id: 2,
4749bfe63fSPaolo Bonzini     fields: vmstate_fields! {
4849bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, flags),
4949bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, line_control),
5049bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, receive_status_error_clear),
5149bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, control),
5249bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, dmacr),
5349bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, int_enabled),
5449bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, int_level),
5549bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, read_fifo),
5649bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, ilpr),
5749bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, ibrd),
5849bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, fbrd),
5949bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, ifl),
6049bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, read_pos),
6149bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, read_count),
6249bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, read_trigger),
6349bfe63fSPaolo Bonzini     },
6449bfe63fSPaolo Bonzini     ..Zeroable::ZERO
6549bfe63fSPaolo Bonzini };
6649bfe63fSPaolo Bonzini 
6737fdb2f5SManos Pitsidianakis pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
68718e255fSPaolo Bonzini     name: c_str!("pl011").as_ptr(),
6993243319SManos Pitsidianakis     version_id: 2,
7093243319SManos Pitsidianakis     minimum_version_id: 2,
7193243319SManos Pitsidianakis     post_load: Some(pl011_post_load),
7293243319SManos Pitsidianakis     fields: vmstate_fields! {
7393243319SManos Pitsidianakis         vmstate_unused!(core::mem::size_of::<u32>()),
74*a1ab4eedSPaolo Bonzini         vmstate_struct!(PL011State, regs, &VMSTATE_PL011_REGS, BqlRefCell<PL011Registers>),
7593243319SManos Pitsidianakis     },
7693243319SManos Pitsidianakis     subsections: vmstate_subsections! {
7793243319SManos Pitsidianakis         VMSTATE_PL011_CLOCK
7893243319SManos Pitsidianakis     },
796e50bde1SPaolo Bonzini     ..Zeroable::ZERO
8037fdb2f5SManos Pitsidianakis };
8137fdb2f5SManos Pitsidianakis 
8237fdb2f5SManos Pitsidianakis qemu_api::declare_properties! {
8337fdb2f5SManos Pitsidianakis     PL011_PROPERTIES,
8437fdb2f5SManos Pitsidianakis     qemu_api::define_property!(
85718e255fSPaolo Bonzini         c_str!("chardev"),
8637fdb2f5SManos Pitsidianakis         PL011State,
8737fdb2f5SManos Pitsidianakis         char_backend,
8837fdb2f5SManos Pitsidianakis         unsafe { &qdev_prop_chr },
8937fdb2f5SManos Pitsidianakis         CharBackend
9037fdb2f5SManos Pitsidianakis     ),
9137fdb2f5SManos Pitsidianakis     qemu_api::define_property!(
92718e255fSPaolo Bonzini         c_str!("migrate-clk"),
9337fdb2f5SManos Pitsidianakis         PL011State,
9437fdb2f5SManos Pitsidianakis         migrate_clock,
9537fdb2f5SManos Pitsidianakis         unsafe { &qdev_prop_bool },
96113c6688SPaolo Bonzini         bool,
97113c6688SPaolo Bonzini         default = true
9837fdb2f5SManos Pitsidianakis     ),
9937fdb2f5SManos Pitsidianakis }
100