xref: /qemu/rust/hw/char/pl011/src/device_class.rs (revision e4fb0be1d1d6b67df7709d84d16133b64f455ce8)
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::{
6*e4fb0be1SPaolo 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     c_str,
13f7b87e46SZhao Liu     prelude::*,
14f7b87e46SZhao Liu     vmstate::VMStateDescription,
15f7b87e46SZhao Liu     vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmstate_unused,
16f7b87e46SZhao Liu     zeroable::Zeroable,
1793243319SManos Pitsidianakis };
1837fdb2f5SManos Pitsidianakis 
1949bfe63fSPaolo Bonzini use crate::device::{PL011Registers, PL011State};
2037fdb2f5SManos Pitsidianakis 
2193243319SManos Pitsidianakis extern "C" fn pl011_clock_needed(opaque: *mut c_void) -> bool {
227d052039SPaolo Bonzini     let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
237d052039SPaolo Bonzini     unsafe { state.as_ref().migrate_clock }
2493243319SManos Pitsidianakis }
2593243319SManos Pitsidianakis 
2693243319SManos Pitsidianakis /// Migration subsection for [`PL011State`] clock.
27d1f27ae9SPaolo Bonzini static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription {
28718e255fSPaolo Bonzini     name: c_str!("pl011/clock").as_ptr(),
2993243319SManos Pitsidianakis     version_id: 1,
3093243319SManos Pitsidianakis     minimum_version_id: 1,
3193243319SManos Pitsidianakis     needed: Some(pl011_clock_needed),
3293243319SManos Pitsidianakis     fields: vmstate_fields! {
3324f0e8d8SPaolo Bonzini         vmstate_clock!(PL011State, clock),
3493243319SManos Pitsidianakis     },
3593243319SManos Pitsidianakis     ..Zeroable::ZERO
3693243319SManos Pitsidianakis };
3793243319SManos Pitsidianakis 
3893243319SManos Pitsidianakis extern "C" fn pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int {
39a1ab4eedSPaolo Bonzini     let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
40a1ab4eedSPaolo Bonzini     let result = unsafe { state.as_ref().post_load(version_id as u32) };
4193243319SManos Pitsidianakis     if result.is_err() {
4293243319SManos Pitsidianakis         -1
4393243319SManos Pitsidianakis     } else {
4493243319SManos Pitsidianakis         0
4593243319SManos Pitsidianakis     }
4693243319SManos Pitsidianakis }
4793243319SManos Pitsidianakis 
4849bfe63fSPaolo Bonzini static VMSTATE_PL011_REGS: VMStateDescription = VMStateDescription {
4949bfe63fSPaolo Bonzini     name: c_str!("pl011/regs").as_ptr(),
5049bfe63fSPaolo Bonzini     version_id: 2,
5149bfe63fSPaolo Bonzini     minimum_version_id: 2,
5249bfe63fSPaolo Bonzini     fields: vmstate_fields! {
5349bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, flags),
5449bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, line_control),
5549bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, receive_status_error_clear),
5649bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, control),
5749bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, dmacr),
5849bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, int_enabled),
5949bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, int_level),
6049bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, read_fifo),
6149bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, ilpr),
6249bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, ibrd),
6349bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, fbrd),
6449bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, ifl),
6549bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, read_pos),
6649bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, read_count),
6749bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, read_trigger),
6849bfe63fSPaolo Bonzini     },
6949bfe63fSPaolo Bonzini     ..Zeroable::ZERO
7049bfe63fSPaolo Bonzini };
7149bfe63fSPaolo Bonzini 
7237fdb2f5SManos Pitsidianakis pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
73718e255fSPaolo Bonzini     name: c_str!("pl011").as_ptr(),
7493243319SManos Pitsidianakis     version_id: 2,
7593243319SManos Pitsidianakis     minimum_version_id: 2,
7693243319SManos Pitsidianakis     post_load: Some(pl011_post_load),
7793243319SManos Pitsidianakis     fields: vmstate_fields! {
7893243319SManos Pitsidianakis         vmstate_unused!(core::mem::size_of::<u32>()),
79a1ab4eedSPaolo Bonzini         vmstate_struct!(PL011State, regs, &VMSTATE_PL011_REGS, BqlRefCell<PL011Registers>),
8093243319SManos Pitsidianakis     },
8193243319SManos Pitsidianakis     subsections: vmstate_subsections! {
8293243319SManos Pitsidianakis         VMSTATE_PL011_CLOCK
8393243319SManos Pitsidianakis     },
846e50bde1SPaolo Bonzini     ..Zeroable::ZERO
8537fdb2f5SManos Pitsidianakis };
8637fdb2f5SManos Pitsidianakis 
8737fdb2f5SManos Pitsidianakis qemu_api::declare_properties! {
8837fdb2f5SManos Pitsidianakis     PL011_PROPERTIES,
8937fdb2f5SManos Pitsidianakis     qemu_api::define_property!(
90718e255fSPaolo Bonzini         c_str!("chardev"),
9137fdb2f5SManos Pitsidianakis         PL011State,
9237fdb2f5SManos Pitsidianakis         char_backend,
9337fdb2f5SManos Pitsidianakis         unsafe { &qdev_prop_chr },
9437fdb2f5SManos Pitsidianakis         CharBackend
9537fdb2f5SManos Pitsidianakis     ),
9637fdb2f5SManos Pitsidianakis     qemu_api::define_property!(
97718e255fSPaolo Bonzini         c_str!("migrate-clk"),
9837fdb2f5SManos Pitsidianakis         PL011State,
9937fdb2f5SManos Pitsidianakis         migrate_clock,
10037fdb2f5SManos Pitsidianakis         unsafe { &qdev_prop_bool },
101113c6688SPaolo Bonzini         bool,
102113c6688SPaolo Bonzini         default = true
10337fdb2f5SManos Pitsidianakis     ),
10437fdb2f5SManos Pitsidianakis }
105