Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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