xref: /qemu/rust/hw/char/pl011/src/device_class.rs (revision c48700e86d91004424e3a6496f194decb036dccb)
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 
5*c48700e8SZhao Liu use std::{
6*c48700e8SZhao Liu     os::raw::{c_int, c_void},
7*c48700e8SZhao Liu     ptr::NonNull,
8*c48700e8SZhao Liu };
937fdb2f5SManos Pitsidianakis 
1093243319SManos Pitsidianakis use qemu_api::{
11a1ab4eedSPaolo Bonzini     bindings::*, c_str, prelude::*, vmstate_clock, vmstate_fields, vmstate_of, vmstate_struct,
1249bfe63fSPaolo Bonzini     vmstate_subsections, vmstate_unused, zeroable::Zeroable,
1393243319SManos Pitsidianakis };
1437fdb2f5SManos Pitsidianakis 
1549bfe63fSPaolo Bonzini use crate::device::{PL011Registers, PL011State};
1637fdb2f5SManos Pitsidianakis 
1793243319SManos Pitsidianakis extern "C" fn pl011_clock_needed(opaque: *mut c_void) -> bool {
187d052039SPaolo Bonzini     let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
197d052039SPaolo Bonzini     unsafe { state.as_ref().migrate_clock }
2093243319SManos Pitsidianakis }
2193243319SManos Pitsidianakis 
2293243319SManos Pitsidianakis /// Migration subsection for [`PL011State`] clock.
23d1f27ae9SPaolo Bonzini static VMSTATE_PL011_CLOCK: VMStateDescription = VMStateDescription {
24718e255fSPaolo Bonzini     name: c_str!("pl011/clock").as_ptr(),
2593243319SManos Pitsidianakis     version_id: 1,
2693243319SManos Pitsidianakis     minimum_version_id: 1,
2793243319SManos Pitsidianakis     needed: Some(pl011_clock_needed),
2893243319SManos Pitsidianakis     fields: vmstate_fields! {
2924f0e8d8SPaolo Bonzini         vmstate_clock!(PL011State, clock),
3093243319SManos Pitsidianakis     },
3193243319SManos Pitsidianakis     ..Zeroable::ZERO
3293243319SManos Pitsidianakis };
3393243319SManos Pitsidianakis 
3493243319SManos Pitsidianakis extern "C" fn pl011_post_load(opaque: *mut c_void, version_id: c_int) -> c_int {
35a1ab4eedSPaolo Bonzini     let state = NonNull::new(opaque).unwrap().cast::<PL011State>();
36a1ab4eedSPaolo Bonzini     let result = unsafe { state.as_ref().post_load(version_id as u32) };
3793243319SManos Pitsidianakis     if result.is_err() {
3893243319SManos Pitsidianakis         -1
3993243319SManos Pitsidianakis     } else {
4093243319SManos Pitsidianakis         0
4193243319SManos Pitsidianakis     }
4293243319SManos Pitsidianakis }
4393243319SManos Pitsidianakis 
4449bfe63fSPaolo Bonzini static VMSTATE_PL011_REGS: VMStateDescription = VMStateDescription {
4549bfe63fSPaolo Bonzini     name: c_str!("pl011/regs").as_ptr(),
4649bfe63fSPaolo Bonzini     version_id: 2,
4749bfe63fSPaolo Bonzini     minimum_version_id: 2,
4849bfe63fSPaolo Bonzini     fields: vmstate_fields! {
4949bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, flags),
5049bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, line_control),
5149bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, receive_status_error_clear),
5249bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, control),
5349bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, dmacr),
5449bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, int_enabled),
5549bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, int_level),
5649bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, read_fifo),
5749bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, ilpr),
5849bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, ibrd),
5949bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, fbrd),
6049bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, ifl),
6149bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, read_pos),
6249bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, read_count),
6349bfe63fSPaolo Bonzini         vmstate_of!(PL011Registers, read_trigger),
6449bfe63fSPaolo Bonzini     },
6549bfe63fSPaolo Bonzini     ..Zeroable::ZERO
6649bfe63fSPaolo Bonzini };
6749bfe63fSPaolo Bonzini 
6837fdb2f5SManos Pitsidianakis pub static VMSTATE_PL011: VMStateDescription = VMStateDescription {
69718e255fSPaolo Bonzini     name: c_str!("pl011").as_ptr(),
7093243319SManos Pitsidianakis     version_id: 2,
7193243319SManos Pitsidianakis     minimum_version_id: 2,
7293243319SManos Pitsidianakis     post_load: Some(pl011_post_load),
7393243319SManos Pitsidianakis     fields: vmstate_fields! {
7493243319SManos Pitsidianakis         vmstate_unused!(core::mem::size_of::<u32>()),
75a1ab4eedSPaolo Bonzini         vmstate_struct!(PL011State, regs, &VMSTATE_PL011_REGS, BqlRefCell<PL011Registers>),
7693243319SManos Pitsidianakis     },
7793243319SManos Pitsidianakis     subsections: vmstate_subsections! {
7893243319SManos Pitsidianakis         VMSTATE_PL011_CLOCK
7993243319SManos Pitsidianakis     },
806e50bde1SPaolo Bonzini     ..Zeroable::ZERO
8137fdb2f5SManos Pitsidianakis };
8237fdb2f5SManos Pitsidianakis 
8337fdb2f5SManos Pitsidianakis qemu_api::declare_properties! {
8437fdb2f5SManos Pitsidianakis     PL011_PROPERTIES,
8537fdb2f5SManos Pitsidianakis     qemu_api::define_property!(
86718e255fSPaolo Bonzini         c_str!("chardev"),
8737fdb2f5SManos Pitsidianakis         PL011State,
8837fdb2f5SManos Pitsidianakis         char_backend,
8937fdb2f5SManos Pitsidianakis         unsafe { &qdev_prop_chr },
9037fdb2f5SManos Pitsidianakis         CharBackend
9137fdb2f5SManos Pitsidianakis     ),
9237fdb2f5SManos Pitsidianakis     qemu_api::define_property!(
93718e255fSPaolo Bonzini         c_str!("migrate-clk"),
9437fdb2f5SManos Pitsidianakis         PL011State,
9537fdb2f5SManos Pitsidianakis         migrate_clock,
9637fdb2f5SManos Pitsidianakis         unsafe { &qdev_prop_bool },
97113c6688SPaolo Bonzini         bool,
98113c6688SPaolo Bonzini         default = true
9937fdb2f5SManos Pitsidianakis     ),
10037fdb2f5SManos Pitsidianakis }
101