mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-22 03:12:27 +00:00
aarch64: Add PL061 for device tree implementation
This commit adds a new legacy device PL011 for the AArch64 device tree implementation. Signed-off-by: Henry Wang <Henry.Wang@arm.com>
This commit is contained in:
parent
7c86ef8a69
commit
a59ff42a95
@ -30,6 +30,8 @@ const GIC_PHANDLE: u32 = 1;
|
||||
const MSI_PHANDLE: u32 = 2;
|
||||
// This is a value for uniquely identifying the FDT node containing the clock definition.
|
||||
const CLOCK_PHANDLE: u32 = 3;
|
||||
// This is a value for uniquely identifying the FDT node containing the gpio controller.
|
||||
const GPIO_PHANDLE: u32 = 4;
|
||||
|
||||
// Read the documentation specified when appending the root node to the FDT.
|
||||
const ADDRESS_CELLS: u32 = 0x2;
|
||||
@ -45,6 +47,10 @@ const GIC_FDT_IRQ_TYPE_PPI: u32 = 1;
|
||||
const IRQ_TYPE_EDGE_RISING: u32 = 1;
|
||||
const IRQ_TYPE_LEVEL_HI: u32 = 4;
|
||||
|
||||
// Keys and Buttons
|
||||
// System Power Down
|
||||
const KEY_POWER: u32 = 116;
|
||||
|
||||
// This links to libfdt which handles the creation of the binary blob
|
||||
// flattened device tree (fdt) that is passed to the kernel and indicates
|
||||
// the hardware configuration of the machine.
|
||||
@ -520,6 +526,41 @@ fn create_rtc_node<T: DeviceInfoForFDT + Clone + Debug>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_gpio_node<T: DeviceInfoForFDT + Clone + Debug>(
|
||||
fdt: &mut Vec<u8>,
|
||||
dev_info: &T,
|
||||
) -> Result<()> {
|
||||
// PL061 GPIO controller node
|
||||
let compatible = b"arm,pl061\0arm,primecell\0";
|
||||
let gpio_reg_prop = generate_prop64(&[dev_info.addr(), dev_info.length()]);
|
||||
let irq = generate_prop32(&[GIC_FDT_IRQ_TYPE_SPI, dev_info.irq(), IRQ_TYPE_EDGE_RISING]);
|
||||
append_begin_node(fdt, &format!("pl061@{:x}", dev_info.addr()))?;
|
||||
append_property(fdt, "compatible", compatible)?;
|
||||
append_property(fdt, "reg", &gpio_reg_prop)?;
|
||||
append_property(fdt, "interrupts", &irq)?;
|
||||
append_property_null(fdt, "gpio-controller")?;
|
||||
append_property_u32(fdt, "#gpio-cells", 2)?;
|
||||
append_property_u32(fdt, "clocks", CLOCK_PHANDLE)?;
|
||||
append_property_string(fdt, "clock-names", "apb_pclk")?;
|
||||
append_property_u32(fdt, "phandle", GPIO_PHANDLE)?;
|
||||
append_end_node(fdt)?;
|
||||
|
||||
// gpio-keys node
|
||||
append_begin_node(fdt, "/gpio-keys")?;
|
||||
append_property_string(fdt, "compatible", "gpio-keys")?;
|
||||
append_property_u32(fdt, "#size-cells", 0)?;
|
||||
append_property_u32(fdt, "#address-cells", 1)?;
|
||||
append_begin_node(fdt, "/gpio-keys/poweroff")?;
|
||||
append_property_string(fdt, "label", "GPIO Key Poweroff")?;
|
||||
append_property_u32(fdt, "linux,code", KEY_POWER)?;
|
||||
let gpios = generate_prop32(&[GPIO_PHANDLE, 3, 0]);
|
||||
append_property(fdt, "gpios", &gpios)?;
|
||||
append_end_node(fdt)?;
|
||||
append_end_node(fdt)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn create_devices_node<T: DeviceInfoForFDT + Clone + Debug, S: ::std::hash::BuildHasher>(
|
||||
fdt: &mut Vec<u8>,
|
||||
dev_info: &HashMap<(DeviceType, String), T, S>,
|
||||
@ -529,6 +570,7 @@ fn create_devices_node<T: DeviceInfoForFDT + Clone + Debug, S: ::std::hash::Buil
|
||||
|
||||
for ((device_type, _device_id), info) in dev_info {
|
||||
match device_type {
|
||||
DeviceType::GPIO => create_gpio_node(fdt, info)?,
|
||||
DeviceType::RTC => create_rtc_node(fdt, info)?,
|
||||
DeviceType::Serial => create_serial_node(fdt, info)?,
|
||||
DeviceType::Virtio(_) => {
|
||||
|
@ -51,6 +51,7 @@ pub const MAPPED_IO_START: u64 = 0x0900_0000;
|
||||
/// Space 0x0900_0000 ~ 0x1000_0000 is reserved for legacy devices.
|
||||
pub const LEGACY_SERIAL_MAPPED_IO_START: u64 = 0x0900_0000;
|
||||
pub const LEGACY_RTC_MAPPED_IO_START: u64 = 0x0901_0000;
|
||||
pub const LEGACY_GPIO_MAPPED_IO_START: u64 = 0x0902_0000;
|
||||
|
||||
/// Legacy space will be allocated at once whiling setting up legacy devices.
|
||||
pub const LEGACY_DEVICES_MAPPED_IO_SIZE: u64 = 0x0700_0000;
|
||||
|
@ -129,6 +129,9 @@ pub enum DeviceType {
|
||||
/// Device Type: RTC.
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
RTC,
|
||||
/// Device Type: GPIO.
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
GPIO,
|
||||
}
|
||||
|
||||
/// Default (smallest) memory page size for the supported architectures.
|
||||
|
@ -25,6 +25,8 @@ pub use self::fwdebug::FwDebugDevice;
|
||||
pub use self::i8042::I8042Device;
|
||||
pub use self::serial::Serial;
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub use self::gpio_pl061::GPIO;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub use self::rtc_pl031::RTC;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
|
@ -118,6 +118,8 @@ const VFIO_DEVICE_NAME_PREFIX: &str = "_vfio";
|
||||
const IOAPIC_DEVICE_NAME: &str = "_ioapic";
|
||||
|
||||
const SERIAL_DEVICE_NAME_PREFIX: &str = "_serial";
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
const GPIO_DEVICE_NAME_PREFIX: &str = "_gpio";
|
||||
|
||||
const CONSOLE_DEVICE_NAME: &str = "_console";
|
||||
const DISK_DEVICE_NAME_PREFIX: &str = "_disk";
|
||||
@ -929,6 +931,10 @@ pub struct DeviceManager {
|
||||
|
||||
// Possible handle to the virtio-balloon device
|
||||
virtio_mem_devices: Vec<Arc<Mutex<virtio_devices::Mem>>>,
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
// GPIO device for AArch64
|
||||
gpio_device: Option<Arc<Mutex<devices::legacy::GPIO>>>,
|
||||
}
|
||||
|
||||
impl DeviceManager {
|
||||
@ -1015,6 +1021,8 @@ impl DeviceManager {
|
||||
serial_pty: None,
|
||||
console_pty: None,
|
||||
virtio_mem_devices: Vec::new(),
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
gpio_device: None,
|
||||
};
|
||||
|
||||
let device_manager = Arc::new(Mutex::new(device_manager));
|
||||
@ -1547,6 +1555,53 @@ impl DeviceManager {
|
||||
},
|
||||
);
|
||||
|
||||
// Add a GPIO device
|
||||
let id = String::from(GPIO_DEVICE_NAME_PREFIX);
|
||||
let gpio_irq = self
|
||||
.address_manager
|
||||
.allocator
|
||||
.lock()
|
||||
.unwrap()
|
||||
.allocate_irq()
|
||||
.unwrap();
|
||||
|
||||
let interrupt_group = interrupt_manager
|
||||
.create_group(LegacyIrqGroupConfig {
|
||||
irq: gpio_irq as InterruptIndex,
|
||||
})
|
||||
.map_err(DeviceManagerError::CreateInterruptGroup)?;
|
||||
|
||||
let gpio_device = Arc::new(Mutex::new(devices::legacy::GPIO::new(
|
||||
id.clone(),
|
||||
interrupt_group,
|
||||
)));
|
||||
|
||||
self.bus_devices
|
||||
.push(Arc::clone(&gpio_device) as Arc<Mutex<dyn BusDevice>>);
|
||||
|
||||
let addr = GuestAddress(arch::layout::LEGACY_GPIO_MAPPED_IO_START);
|
||||
|
||||
self.address_manager
|
||||
.mmio_bus
|
||||
.insert(gpio_device.clone(), addr.0, MMIO_LEN)
|
||||
.map_err(DeviceManagerError::BusError)?;
|
||||
|
||||
self.gpio_device = Some(gpio_device.clone());
|
||||
|
||||
self.id_to_dev_info.insert(
|
||||
(DeviceType::GPIO, "gpio".to_string()),
|
||||
MMIODeviceInfo {
|
||||
addr: addr.0,
|
||||
len: MMIO_LEN,
|
||||
irq: gpio_irq,
|
||||
},
|
||||
);
|
||||
|
||||
self.device_tree
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(id.clone(), device_node!(id, gpio_device));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user