Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion drivers/gpu/drm/asahi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ config DRM_ASAHI_G15
depends on DRM_APPLE=y || (DRM_APPLE=m && DRM_ASAHI=m)
select APPLE_T6030_GPU_PMP_LINK
select CRYPTO_LIB_SHA256
select RUST_FW_LOADER_ABSTRACTIONS
select DRM_ASAHI_UAT_ADOPTION
default n
help
Expand Down
57 changes: 42 additions & 15 deletions drivers/gpu/drm/asahi/g15/adt.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT

//! The GPU regions, firmware segments and performance states: from the boot loader's ADT
Expand Down Expand Up @@ -30,10 +30,13 @@
//! one cell per cluster). The same admission applies, without the DRAM bounds, and the four UAT
//! regions may lie in System RAM: they are reserved-memory nodes without `no-map`, which the
//! kernel maps, so the driver reaches them through its own mapping ([`super::regs::Mapping`]).
//! The GPU's sensor rows, which the node does not carry, come from the same ADT export as on
//! T6030: `/arm-io/aon-ptd` `ptd_data_table` ([`super::board::record::sensor_rows`]).

use core::ops::Range;
use kernel::{c_str, device, prelude::*};

use super::board::record;
use super::boot::glue;
use super::hw;

Expand All @@ -57,12 +60,13 @@
pub(crate) perf_mhz: [u32; PERF_STATES],
pub(crate) perf_mv: [u32; PERF_STATES],
pub(crate) sram_mv: [u32; PERF_STATES],
/// Per-cluster core mV of each state, rounded up from the device tree's microvolts, how
/// many voltage cells the node has (1 on the ADT path), and the state's power in mW (0 on
/// the ADT path).
/// Per-cluster core mV of each state, rounded up from the device tree's microvolts, and how
/// many voltage cells the node has (1 on the ADT path).
pub(crate) cluster_mv: [[u32; CLUSTERS]; PERF_STATES],
pub(crate) cluster_cells: usize,
pub(crate) perf_mw: [u32; PERF_STATES],
/// The GPU's six sensor rows of the ADT's `aon-ptd` table (T6031; zero on the T6030 path,
/// whose templates carry their own).
pub(crate) sensor_rows: [[u8; 12]; record::SENSOR_ROW_COUNT],
}

/// Voltage cells the layout keeps per state.
Expand Down Expand Up @@ -328,7 +332,7 @@
sram_mv: [0; PERF_STATES],
cluster_mv: [[0; CLUSTERS]; PERF_STATES],
cluster_cells: 1,
perf_mw: [0; PERF_STATES],
sensor_rows: [[0; 12]; record::SENSOR_ROW_COUNT],
};
collect_perf(dev, adt, sgx, &mut out)?;
for i in 0..PERF_STATES {
Expand Down Expand Up @@ -437,11 +441,11 @@
sram_mv: [0; PERF_STATES],
cluster_mv: [[0; CLUSTERS]; PERF_STATES],
cluster_cells: 0,
perf_mw: [0; PERF_STATES],
sensor_rows: [[0; 12]; record::SENSOR_ROW_COUNT],
};
// Operating points: MHz, the highest cluster voltage of each and the clusters' voltages
// (rounded up) and power for the hardware record; the SRAM voltage is not in the device
// tree.
// (rounded up) for the hardware record; the SRAM voltage is not in the device tree, and
// the powers are a boot-loader stand-in.
let opps = node
.parse_phandle(c_str!("operating-points-v2"), 0)
.ok_or(EINVAL)
Expand All @@ -450,7 +454,6 @@
for opp in opps.children() {
let hz: u64 = opp.get_property(c_str!("opp-hz"))?;
let uv: KVec<u32> = opp.get_property(c_str!("opp-microvolt"))?;
let uw: Option<u32> = opp.get_opt_property(c_str!("opp-microwatt"))?;
let mv = uv.iter().max().copied().unwrap_or(0) / 1000;
if uv.is_empty() || uv.len() > CLUSTERS || (count > 0 && uv.len() != out.cluster_cells) {
dev_err!(dev, "GPU operating point {} has {} voltage cells\n", count, uv.len());
Expand All @@ -467,7 +470,6 @@
out.cluster_mv[count][c] = v.div_ceil(1000);
}
out.cluster_cells = uv.len();
out.perf_mw[count] = uw.unwrap_or(0) / 1000;
}
count += 1;
}
Expand All @@ -480,19 +482,44 @@
);
return Err(EINVAL);
}
out.sensor_rows = sensor_rows(dev)?;
Ok(out)
}

/// A private copy of the boot loader's ADT export.
fn copy() -> Result<KVVec<u8>> {
let (start, size) = glue::adt_phram()?;
if size == 0 || size > 0x200000 || start & 0x3fff != 0 {
return Err(EINVAL);
}
super::identity::copy_physical(start, usize::try_from(size)?)
}

/// The GPU's six sensor rows: `/arm-io/aon-ptd` `ptd_data_table` of the ADT export
/// ([`record::sensor_rows`]), which the device tree does not carry.
fn sensor_rows(dev: &device::Device) -> Result<[[u8; 12]; record::SENSOR_ROW_COUNT]> {
let copy =
copy().inspect_err(|_| dev_err!(dev, "no usable ADT export for the GPU sensor rows\n"))?;
let adt = Adt { data: &copy };
let table = adt
.node_end(0, 0)
.and_then(|_| adt.child(0, "arm-io"))
.and_then(|armio| adt.child(armio, "aon-ptd"))
.and_then(|ptd| adt.prop(ptd, "ptd_data_table"))
.ok_or(EINVAL)
.inspect_err(|_| dev_err!(dev, "ADT has no aon-ptd ptd_data_table\n"))?;
record::sensor_rows(table).map_err(|why| {
dev_err!(dev, "ADT aon-ptd: {}\n", why);
EINVAL
})
}

/// Reads and admits the GPU's regions, segments and performance states (read-only), from the
/// source the SoC configuration names.
pub(crate) fn read(dev: &device::Device, cfg: &super::Config) -> Result<GpuAdt> {
if cfg.platform == hw::Platform::DeviceTree {
return from_device_tree(dev);
}
let (start, size) = glue::adt_phram()?;
if size == 0 || size > 0x200000 || start & 0x3fff != 0 {
return Err(EINVAL);
}
let copy = super::identity::copy_physical(start, usize::try_from(size)?)?;
let copy = copy()?;
parse(dev, &Adt { data: &copy })
}
35 changes: 13 additions & 22 deletions drivers/gpu/drm/asahi/g15/board.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT

//! Board-data templates of the supported firmware build.
Expand All @@ -10,11 +10,11 @@
//! against its hash at boot.
//!
//! A SoC whose board data comes from its device tree ([`super::hw::Platform::DeviceTree`]) gets
//! its hardware record from [`hardware_record`] ([`record`]) and its Globals and Power from
//! [`device_tree`]: the G15S templates with the GPU node's power words and the hardware
//! record's maximum power ([`words`]).
//! its hardware record from [`hardware_record`] ([`record`]: the GPU node, the ADT's sensor
//! rows and the SoC's reference words) and its Globals and Power from [`device_tree`]: the G15S
//! templates with the GPU node's power words and the hardware record's maximum power
//! ([`words`]).

pub(crate) mod blob;
pub(crate) mod data;
pub(crate) mod record;
pub(crate) mod template;
Expand Down Expand Up @@ -98,7 +98,6 @@
mhz,
mv: [uv[0].div_ceil(1000), 0, 0, 0],
cells: 1,
mw: 0,
};
n += 1;
}
Expand All @@ -110,13 +109,13 @@
}

/// The hardware record of a device-tree SoC ([`record`]): built from the GPU node's properties
/// and operating-point tables, the layout's IOMapping table and the ADT regions, with the
/// words the device tree does not carry copied from `file`, the machine's own record.
/// and operating-point tables, the layout's IOMapping table, the ADT regions and sensor rows,
/// and the SoC's `reference` words, which neither carries.
pub(crate) fn hardware_record(
dev: &device::Device,
cfg: &super::Config,
adt: &GpuAdt,
file: &[u8],
reference: &record::Reference,
) -> Result<KVVec<u8>> {
let layout = cfg.layout;
let node = dev.of_node().ok_or(ENODEV)?;
Expand All @@ -136,7 +135,6 @@
mhz: adt.perf_mhz[i],
mv: adt.cluster_mv[i],
cells: adt.cluster_cells,
mw: adt.perf_mw[i],
};
}
let mut cs = [record::Opp::default(); 16];
Expand All @@ -159,12 +157,6 @@
writable,
};
}
let max_power_mw = u32::from_le_bytes(
file.get(record::MAX_POWER..record::MAX_POWER + 4)
.ok_or(EINVAL)?
.try_into()
.map_err(|_| EINVAL)?,
);
let inputs = record::Inputs {
props,
zones: &zones,
Expand All @@ -177,15 +169,14 @@
usc_base: hw::client::COMPACT_WINDOW.start,
user_end: hw::USER_RANGE.end,
timestamps: va::TIMESTAMPS,
max_power_mw,
sensor_rows: adt.sensor_rows,
reference,
};
let mut out = KVVec::from_elem(0u8, record::SIZE, GFP_KERNEL)?;
record::from_file(&mut out, file)
.and_then(|()| record::build(&mut out, &inputs))
.map_err(|why| {
dev_err!(dev, "hardware record from the device tree: {}\n", why);
EINVAL
})?;
record::build(&mut out, &inputs).map_err(|why| {
dev_err!(dev, "hardware record from the device tree: {}\n", why);
EINVAL
})?;
Ok(out)
}

Expand Down
113 changes: 0 additions & 113 deletions drivers/gpu/drm/asahi/g15/board/blob.rs

This file was deleted.

Loading