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
5c48700e8SZhao Liu use std::{
6e4fb0be1SPaolo Bonzini ffi::{c_int, c_void},
7c48700e8SZhao Liu ptr::NonNull,
8c48700e8SZhao Liu };
937fdb2f5SManos Pitsidianakis
1093243319SManos Pitsidianakis use qemu_api::{
11f7b87e46SZhao Liu bindings::{qdev_prop_bool, qdev_prop_chr},
12f7b87e46SZhao Liu prelude::*,
13f7b87e46SZhao Liu vmstate::VMStateDescription,
14f7b87e46SZhao Liu vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmstate_unused,
15f7b87e46SZhao Liu zeroable::Zeroable,
1693243319SManos Pitsidianakis };
1737fdb2f5SManos Pitsidianakis
1849bfe63fSPaolo Bonzini use crate::device::{PL011Registers, PL011State};
1937fdb2f5SManos Pitsidianakis
pl011_clock_needed(opaque: *mut c_void) -> bool2093243319SManos Pitsidianakis extern "C" fn pl011_clock_needed(opaque: *mut c_void) -> bool {
217d052039SPaolo Bonzini let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
227d052039SPaolo Bonzini unsafe { state.as_ref().migrate_clock }
2393243319SManos Pitsidianakis }
2493243319SManos Pitsidianakis
2593243319SManos Pitsidianakis /// Migration subsection for [`PL011State`] clock.
26d1f27ae9SPaolo Bonzini static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription {
27*f117857bSPaolo Bonzini name: c"pl011/clock".as_ptr(),
2893243319SManos Pitsidianakis version_id: 1,
2993243319SManos Pitsidianakis minimum_version_id: 1,
3093243319SManos Pitsidianakis needed: Some(pl011_clock_needed),
3193243319SManos Pitsidianakis fields: vmstate_fields! {
3224f0e8d8SPaolo Bonzini vmstate_clock!(PL011State, clock),
3393243319SManos Pitsidianakis },
3493243319SManos Pitsidianakis ..Zeroable::ZERO
3593243319SManos Pitsidianakis };
3693243319SManos Pitsidianakis
pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int3793243319SManos Pitsidianakis extern "C" fn pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int {
38a1ab4eedSPaolo Bonzini let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
39a1ab4eedSPaolo Bonzini let result = unsafe { state.as_ref().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
4749bfe63fSPaolo Bonzini static VMSTATE_PL011_REGS: VMStateDescription = VMStateDescription {
48*f117857bSPaolo Bonzini name: c"pl011/regs".as_ptr(),
4949bfe63fSPaolo Bonzini version_id: 2,
5049bfe63fSPaolo Bonzini minimum_version_id: 2,
5149bfe63fSPaolo Bonzini fields: vmstate_fields! {
5249bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, flags),
5349bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, line_control),
5449bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, receive_status_error_clear),
5549bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, control),
5649bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, dmacr),
5749bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, int_enabled),
5849bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, int_level),
5949bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, read_fifo),
6049bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, ilpr),
6149bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, ibrd),
6249bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, fbrd),
6349bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, ifl),
6449bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, read_pos),
6549bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, read_count),
6649bfe63fSPaolo Bonzini vmstate_of!(PL011Registers, read_trigger),
6749bfe63fSPaolo Bonzini },
6849bfe63fSPaolo Bonzini ..Zeroable::ZERO
6949bfe63fSPaolo Bonzini };
7049bfe63fSPaolo Bonzini
7137fdb2f5SManos Pitsidianakis pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
72*f117857bSPaolo Bonzini name: c"pl011".as_ptr(),
7393243319SManos Pitsidianakis version_id: 2,
7493243319SManos Pitsidianakis minimum_version_id: 2,
7593243319SManos Pitsidianakis post_load: Some(pl011_post_load),
7693243319SManos Pitsidianakis fields: vmstate_fields! {
7793243319SManos Pitsidianakis vmstate_unused!(core::mem::size_of::<u32>()),
78a1ab4eedSPaolo Bonzini vmstate_struct!(PL011State, regs, &VMSTATE_PL011_REGS, BqlRefCell<PL011Registers>),
7993243319SManos Pitsidianakis },
8093243319SManos Pitsidianakis subsections: vmstate_subsections! {
8193243319SManos Pitsidianakis VMSTATE_PL011_CLOCK
8293243319SManos Pitsidianakis },
836e50bde1SPaolo Bonzini ..Zeroable::ZERO
8437fdb2f5SManos Pitsidianakis };
8537fdb2f5SManos Pitsidianakis
8637fdb2f5SManos Pitsidianakis qemu_api::declare_properties! {
8737fdb2f5SManos Pitsidianakis PL011_PROPERTIES,
8837fdb2f5SManos Pitsidianakis qemu_api::define_property!(
89*f117857bSPaolo Bonzini c"chardev",
9037fdb2f5SManos Pitsidianakis PL011State,
9137fdb2f5SManos Pitsidianakis char_backend,
9237fdb2f5SManos Pitsidianakis unsafe { &qdev_prop_chr },
9337fdb2f5SManos Pitsidianakis CharBackend
9437fdb2f5SManos Pitsidianakis ),
9537fdb2f5SManos Pitsidianakis qemu_api::define_property!(
96*f117857bSPaolo Bonzini c"migrate-clk",
9737fdb2f5SManos Pitsidianakis PL011State,
9837fdb2f5SManos Pitsidianakis migrate_clock,
9937fdb2f5SManos Pitsidianakis unsafe { &qdev_prop_bool },
100113c6688SPaolo Bonzini bool,
101113c6688SPaolo Bonzini default = true
10237fdb2f5SManos Pitsidianakis ),
10337fdb2f5SManos Pitsidianakis }
104