1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Operating performance points. 4 //! 5 //! This module provides rust abstractions for interacting with the OPP subsystem. 6 //! 7 //! C header: [`include/linux/pm_opp.h`](srctree/include/linux/pm_opp.h) 8 //! 9 //! Reference: <https://docs.kernel.org/power/opp.html> 10 11 use crate::{ 12 clk::Hertz, 13 cpumask::{Cpumask, CpumaskVar}, 14 device::Device, 15 error::{code::*, from_err_ptr, from_result, to_result, Error, Result, VTABLE_DEFAULT_ERROR}, 16 ffi::c_ulong, 17 prelude::*, 18 str::CString, 19 sync::aref::{ARef, AlwaysRefCounted}, 20 types::Opaque, 21 }; 22 23 #[cfg(CONFIG_CPU_FREQ)] 24 /// Frequency table implementation. 25 mod freq { 26 use super::*; 27 use crate::cpufreq; 28 use core::ops::Deref; 29 30 /// OPP frequency table. 31 /// 32 /// A [`cpufreq::Table`] created from [`Table`]. 33 pub struct FreqTable { 34 dev: ARef<Device>, 35 ptr: *mut bindings::cpufreq_frequency_table, 36 } 37 38 impl FreqTable { 39 /// Creates a new instance of [`FreqTable`] from [`Table`]. 40 pub(crate) fn new(table: &Table) -> Result<Self> { 41 let mut ptr: *mut bindings::cpufreq_frequency_table = ptr::null_mut(); 42 43 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 44 // requirements. 45 to_result(unsafe { 46 bindings::dev_pm_opp_init_cpufreq_table(table.dev.as_raw(), &mut ptr) 47 })?; 48 49 Ok(Self { 50 dev: table.dev.clone(), 51 ptr, 52 }) 53 } 54 55 /// Returns a reference to the underlying [`cpufreq::Table`]. 56 #[inline] 57 fn table(&self) -> &cpufreq::Table { 58 // SAFETY: The `ptr` is guaranteed by the C code to be valid. 59 unsafe { cpufreq::Table::from_raw(self.ptr) } 60 } 61 } 62 63 impl Deref for FreqTable { 64 type Target = cpufreq::Table; 65 66 #[inline] 67 fn deref(&self) -> &Self::Target { 68 self.table() 69 } 70 } 71 72 impl Drop for FreqTable { 73 fn drop(&mut self) { 74 // SAFETY: The pointer was created via `dev_pm_opp_init_cpufreq_table`, and is only 75 // freed here. 76 unsafe { 77 bindings::dev_pm_opp_free_cpufreq_table(self.dev.as_raw(), &mut self.as_raw()) 78 }; 79 } 80 } 81 } 82 83 #[cfg(CONFIG_CPU_FREQ)] 84 pub use freq::FreqTable; 85 86 use core::{marker::PhantomData, ptr}; 87 88 use macros::vtable; 89 90 /// Creates a null-terminated slice of pointers to [`Cstring`]s. 91 fn to_c_str_array(names: &[CString]) -> Result<KVec<*const u8>> { 92 // Allocated a null-terminated vector of pointers. 93 let mut list = KVec::with_capacity(names.len() + 1, GFP_KERNEL)?; 94 95 for name in names.iter() { 96 list.push(name.as_ptr().cast(), GFP_KERNEL)?; 97 } 98 99 list.push(ptr::null(), GFP_KERNEL)?; 100 Ok(list) 101 } 102 103 /// The voltage unit. 104 /// 105 /// Represents voltage in microvolts, wrapping a [`c_ulong`] value. 106 /// 107 /// # Examples 108 /// 109 /// ``` 110 /// use kernel::opp::MicroVolt; 111 /// 112 /// let raw = 90500; 113 /// let volt = MicroVolt(raw); 114 /// 115 /// assert_eq!(usize::from(volt), raw); 116 /// assert_eq!(volt, MicroVolt(raw)); 117 /// ``` 118 #[derive(Copy, Clone, PartialEq, Eq, Debug)] 119 pub struct MicroVolt(pub c_ulong); 120 121 impl From<MicroVolt> for c_ulong { 122 #[inline] 123 fn from(volt: MicroVolt) -> Self { 124 volt.0 125 } 126 } 127 128 /// The power unit. 129 /// 130 /// Represents power in microwatts, wrapping a [`c_ulong`] value. 131 /// 132 /// # Examples 133 /// 134 /// ``` 135 /// use kernel::opp::MicroWatt; 136 /// 137 /// let raw = 1000000; 138 /// let power = MicroWatt(raw); 139 /// 140 /// assert_eq!(usize::from(power), raw); 141 /// assert_eq!(power, MicroWatt(raw)); 142 /// ``` 143 #[derive(Copy, Clone, PartialEq, Eq, Debug)] 144 pub struct MicroWatt(pub c_ulong); 145 146 impl From<MicroWatt> for c_ulong { 147 #[inline] 148 fn from(power: MicroWatt) -> Self { 149 power.0 150 } 151 } 152 153 /// Handle for a dynamically created [`OPP`]. 154 /// 155 /// The associated [`OPP`] is automatically removed when the [`Token`] is dropped. 156 /// 157 /// # Examples 158 /// 159 /// The following example demonstrates how to create an [`OPP`] dynamically. 160 /// 161 /// ``` 162 /// use kernel::clk::Hertz; 163 /// use kernel::device::Device; 164 /// use kernel::error::Result; 165 /// use kernel::opp::{Data, MicroVolt, Token}; 166 /// use kernel::sync::aref::ARef; 167 /// 168 /// fn create_opp(dev: &ARef<Device>, freq: Hertz, volt: MicroVolt, level: u32) -> Result<Token> { 169 /// let data = Data::new(freq, volt, level, false); 170 /// 171 /// // OPP is removed once token goes out of scope. 172 /// data.add_opp(dev) 173 /// } 174 /// ``` 175 pub struct Token { 176 dev: ARef<Device>, 177 freq: Hertz, 178 } 179 180 impl Token { 181 /// Dynamically adds an [`OPP`] and returns a [`Token`] that removes it on drop. 182 fn new(dev: &ARef<Device>, mut data: Data) -> Result<Self> { 183 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 184 // requirements. 185 to_result(unsafe { bindings::dev_pm_opp_add_dynamic(dev.as_raw(), &mut data.0) })?; 186 Ok(Self { 187 dev: dev.clone(), 188 freq: data.freq(), 189 }) 190 } 191 } 192 193 impl Drop for Token { 194 fn drop(&mut self) { 195 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 196 // requirements. 197 unsafe { bindings::dev_pm_opp_remove(self.dev.as_raw(), self.freq.into()) }; 198 } 199 } 200 201 /// OPP data. 202 /// 203 /// Rust abstraction for the C `struct dev_pm_opp_data`, used to define operating performance 204 /// points (OPPs) dynamically. 205 /// 206 /// # Examples 207 /// 208 /// The following example demonstrates how to create an [`OPP`] with [`Data`]. 209 /// 210 /// ``` 211 /// use kernel::clk::Hertz; 212 /// use kernel::device::Device; 213 /// use kernel::error::Result; 214 /// use kernel::opp::{Data, MicroVolt, Token}; 215 /// use kernel::sync::aref::ARef; 216 /// 217 /// fn create_opp(dev: &ARef<Device>, freq: Hertz, volt: MicroVolt, level: u32) -> Result<Token> { 218 /// let data = Data::new(freq, volt, level, false); 219 /// 220 /// // OPP is removed once token goes out of scope. 221 /// data.add_opp(dev) 222 /// } 223 /// ``` 224 #[repr(transparent)] 225 pub struct Data(bindings::dev_pm_opp_data); 226 227 impl Data { 228 /// Creates a new instance of [`Data`]. 229 /// 230 /// This can be used to define a dynamic OPP to be added to a device. 231 pub fn new(freq: Hertz, volt: MicroVolt, level: u32, turbo: bool) -> Self { 232 Self(bindings::dev_pm_opp_data { 233 turbo, 234 freq: freq.into(), 235 u_volt: volt.into(), 236 level, 237 }) 238 } 239 240 /// Adds an [`OPP`] dynamically. 241 /// 242 /// Returns a [`Token`] that ensures the OPP is automatically removed 243 /// when it goes out of scope. 244 #[inline] 245 pub fn add_opp(self, dev: &ARef<Device>) -> Result<Token> { 246 Token::new(dev, self) 247 } 248 249 /// Returns the frequency associated with this OPP data. 250 #[inline] 251 fn freq(&self) -> Hertz { 252 Hertz(self.0.freq) 253 } 254 } 255 256 /// [`OPP`] search options. 257 /// 258 /// # Examples 259 /// 260 /// Defines how to search for an [`OPP`] in a [`Table`] relative to a frequency. 261 /// 262 /// ``` 263 /// use kernel::clk::Hertz; 264 /// use kernel::error::Result; 265 /// use kernel::opp::{OPP, SearchType, Table}; 266 /// use kernel::sync::aref::ARef; 267 /// 268 /// fn find_opp(table: &Table, freq: Hertz) -> Result<ARef<OPP>> { 269 /// let opp = table.opp_from_freq(freq, Some(true), None, SearchType::Exact)?; 270 /// 271 /// pr_info!("OPP frequency is: {:?}\n", opp.freq(None)); 272 /// pr_info!("OPP voltage is: {:?}\n", opp.voltage()); 273 /// pr_info!("OPP level is: {}\n", opp.level()); 274 /// pr_info!("OPP power is: {:?}\n", opp.power()); 275 /// 276 /// Ok(opp) 277 /// } 278 /// ``` 279 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 280 pub enum SearchType { 281 /// Match the exact frequency. 282 Exact, 283 /// Find the highest frequency less than or equal to the given value. 284 Floor, 285 /// Find the lowest frequency greater than or equal to the given value. 286 Ceil, 287 } 288 289 /// OPP configuration callbacks. 290 /// 291 /// Implement this trait to customize OPP clock and regulator setup for your device. 292 #[vtable] 293 pub trait ConfigOps { 294 /// This is typically used to scale clocks when transitioning between OPPs. 295 #[inline] 296 fn config_clks(_dev: &Device, _table: &Table, _opp: &OPP, _scaling_down: bool) -> Result { 297 build_error!(VTABLE_DEFAULT_ERROR) 298 } 299 300 /// This provides access to the old and new OPPs, allowing for safe regulator adjustments. 301 #[inline] 302 fn config_regulators( 303 _dev: &Device, 304 _opp_old: &OPP, 305 _opp_new: &OPP, 306 _data: *mut *mut bindings::regulator, 307 _count: u32, 308 ) -> Result { 309 build_error!(VTABLE_DEFAULT_ERROR) 310 } 311 } 312 313 /// OPP configuration token. 314 /// 315 /// Returned by the OPP core when configuration is applied to a [`Device`]. The associated 316 /// configuration is automatically cleared when the token is dropped. 317 pub struct ConfigToken(i32); 318 319 impl Drop for ConfigToken { 320 fn drop(&mut self) { 321 // SAFETY: This is the same token value returned by the C code via `dev_pm_opp_set_config`. 322 unsafe { bindings::dev_pm_opp_clear_config(self.0) }; 323 } 324 } 325 326 /// OPP configurations. 327 /// 328 /// Rust abstraction for the C `struct dev_pm_opp_config`. 329 /// 330 /// # Examples 331 /// 332 /// The following example demonstrates how to set OPP property-name configuration for a [`Device`]. 333 /// 334 /// ``` 335 /// use kernel::device::Device; 336 /// use kernel::error::Result; 337 /// use kernel::opp::{Config, ConfigOps, ConfigToken}; 338 /// use kernel::str::CString; 339 /// use kernel::sync::aref::ARef; 340 /// use kernel::macros::vtable; 341 /// 342 /// #[derive(Default)] 343 /// struct Driver; 344 /// 345 /// #[vtable] 346 /// impl ConfigOps for Driver {} 347 /// 348 /// fn configure(dev: &ARef<Device>) -> Result<ConfigToken> { 349 /// let name = CString::try_from_fmt(fmt!("slow"))?; 350 /// 351 /// // The OPP configuration is cleared once the [`ConfigToken`] goes out of scope. 352 /// Config::<Driver>::new() 353 /// .set_prop_name(name)? 354 /// .set(dev) 355 /// } 356 /// ``` 357 #[derive(Default)] 358 pub struct Config<T: ConfigOps> 359 where 360 T: Default, 361 { 362 clk_names: Option<KVec<CString>>, 363 prop_name: Option<CString>, 364 regulator_names: Option<KVec<CString>>, 365 supported_hw: Option<KVec<u32>>, 366 367 // Tuple containing (required device, index) 368 required_dev: Option<(ARef<Device>, u32)>, 369 _data: PhantomData<T>, 370 } 371 372 impl<T: ConfigOps + Default> Config<T> { 373 /// Creates a new instance of [`Config`]. 374 #[inline] 375 pub fn new() -> Self { 376 Self::default() 377 } 378 379 /// Initializes clock names. 380 pub fn set_clk_names(mut self, names: KVec<CString>) -> Result<Self> { 381 if self.clk_names.is_some() { 382 return Err(EBUSY); 383 } 384 385 if names.is_empty() { 386 return Err(EINVAL); 387 } 388 389 self.clk_names = Some(names); 390 Ok(self) 391 } 392 393 /// Initializes property name. 394 pub fn set_prop_name(mut self, name: CString) -> Result<Self> { 395 if self.prop_name.is_some() { 396 return Err(EBUSY); 397 } 398 399 self.prop_name = Some(name); 400 Ok(self) 401 } 402 403 /// Initializes regulator names. 404 pub fn set_regulator_names(mut self, names: KVec<CString>) -> Result<Self> { 405 if self.regulator_names.is_some() { 406 return Err(EBUSY); 407 } 408 409 if names.is_empty() { 410 return Err(EINVAL); 411 } 412 413 self.regulator_names = Some(names); 414 415 Ok(self) 416 } 417 418 /// Initializes required devices. 419 pub fn set_required_dev(mut self, dev: ARef<Device>, index: u32) -> Result<Self> { 420 if self.required_dev.is_some() { 421 return Err(EBUSY); 422 } 423 424 self.required_dev = Some((dev, index)); 425 Ok(self) 426 } 427 428 /// Initializes supported hardware. 429 pub fn set_supported_hw(mut self, hw: KVec<u32>) -> Result<Self> { 430 if self.supported_hw.is_some() { 431 return Err(EBUSY); 432 } 433 434 if hw.is_empty() { 435 return Err(EINVAL); 436 } 437 438 self.supported_hw = Some(hw); 439 Ok(self) 440 } 441 442 /// Sets the configuration with the OPP core. 443 /// 444 /// The returned [`ConfigToken`] will remove the configuration when dropped. 445 pub fn set(self, dev: &Device) -> Result<ConfigToken> { 446 let (_clk_list, clk_names) = match &self.clk_names { 447 Some(x) => { 448 let list = to_c_str_array(x)?; 449 let ptr = list.as_ptr(); 450 (Some(list), ptr) 451 } 452 None => (None, ptr::null()), 453 }; 454 455 let (_regulator_list, regulator_names) = match &self.regulator_names { 456 Some(x) => { 457 let list = to_c_str_array(x)?; 458 let ptr = list.as_ptr(); 459 (Some(list), ptr) 460 } 461 None => (None, ptr::null()), 462 }; 463 464 let prop_name = self 465 .prop_name 466 .as_ref() 467 .map_or(ptr::null(), |p| p.as_char_ptr()); 468 469 let (supported_hw, supported_hw_count) = self 470 .supported_hw 471 .as_ref() 472 .map_or((ptr::null(), 0), |hw| (hw.as_ptr(), hw.len() as u32)); 473 474 let (required_dev, required_dev_index) = self 475 .required_dev 476 .as_ref() 477 .map_or((ptr::null_mut(), 0), |(dev, idx)| (dev.as_raw(), *idx)); 478 479 let mut config = bindings::dev_pm_opp_config { 480 clk_names, 481 config_clks: if T::HAS_CONFIG_CLKS { 482 Some(Self::config_clks) 483 } else { 484 None 485 }, 486 prop_name, 487 regulator_names, 488 config_regulators: if T::HAS_CONFIG_REGULATORS { 489 Some(Self::config_regulators) 490 } else { 491 None 492 }, 493 supported_hw, 494 supported_hw_count, 495 496 required_dev, 497 required_dev_index, 498 }; 499 500 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 501 // requirements. The OPP core guarantees not to access fields of [`Config`] after this call 502 // and so we don't need to save a copy of them for future use. 503 let ret = unsafe { bindings::dev_pm_opp_set_config(dev.as_raw(), &mut config) }; 504 if ret < 0 { 505 Err(Error::from_errno(ret)) 506 } else { 507 Ok(ConfigToken(ret)) 508 } 509 } 510 511 /// Config's clk callback. 512 /// 513 /// SAFETY: Called from C. Inputs must be valid pointers. 514 extern "C" fn config_clks( 515 dev: *mut bindings::device, 516 opp_table: *mut bindings::opp_table, 517 opp: *mut bindings::dev_pm_opp, 518 _data: *mut c_void, 519 scaling_down: bool, 520 ) -> c_int { 521 from_result(|| { 522 // SAFETY: 'dev' is guaranteed by the C code to be valid. 523 let dev = unsafe { Device::get_device(dev) }; 524 T::config_clks( 525 &dev, 526 // SAFETY: 'opp_table' is guaranteed by the C code to be valid. 527 &unsafe { Table::from_raw_table(opp_table, &dev) }, 528 // SAFETY: 'opp' is guaranteed by the C code to be valid. 529 unsafe { OPP::from_raw_opp(opp)? }, 530 scaling_down, 531 ) 532 .map(|()| 0) 533 }) 534 } 535 536 /// Config's regulator callback. 537 /// 538 /// SAFETY: Called from C. Inputs must be valid pointers. 539 extern "C" fn config_regulators( 540 dev: *mut bindings::device, 541 old_opp: *mut bindings::dev_pm_opp, 542 new_opp: *mut bindings::dev_pm_opp, 543 regulators: *mut *mut bindings::regulator, 544 count: c_uint, 545 ) -> c_int { 546 from_result(|| { 547 // SAFETY: 'dev' is guaranteed by the C code to be valid. 548 let dev = unsafe { Device::get_device(dev) }; 549 T::config_regulators( 550 &dev, 551 // SAFETY: 'old_opp' is guaranteed by the C code to be valid. 552 unsafe { OPP::from_raw_opp(old_opp)? }, 553 // SAFETY: 'new_opp' is guaranteed by the C code to be valid. 554 unsafe { OPP::from_raw_opp(new_opp)? }, 555 regulators, 556 count, 557 ) 558 .map(|()| 0) 559 }) 560 } 561 } 562 563 /// A reference-counted OPP table. 564 /// 565 /// Rust abstraction for the C `struct opp_table`. 566 /// 567 /// # Invariants 568 /// 569 /// The pointer stored in `Self` is non-null and valid for the lifetime of the [`Table`]. 570 /// 571 /// Instances of this type are reference-counted. 572 /// 573 /// # Examples 574 /// 575 /// The following example demonstrates how to get OPP [`Table`] for a [`Cpumask`] and set its 576 /// frequency. 577 /// 578 /// ``` 579 /// # #![cfg(CONFIG_OF)] 580 /// use kernel::clk::Hertz; 581 /// use kernel::cpumask::Cpumask; 582 /// use kernel::device::Device; 583 /// use kernel::error::Result; 584 /// use kernel::opp::Table; 585 /// use kernel::sync::aref::ARef; 586 /// 587 /// fn get_table(dev: &ARef<Device>, mask: &mut Cpumask, freq: Hertz) -> Result<Table> { 588 /// let mut opp_table = Table::from_of_cpumask(dev, mask)?; 589 /// 590 /// if opp_table.opp_count()? == 0 { 591 /// return Err(EINVAL); 592 /// } 593 /// 594 /// pr_info!("Max transition latency is: {} ns\n", opp_table.max_transition_latency_ns()); 595 /// pr_info!("Suspend frequency is: {:?}\n", opp_table.suspend_freq()); 596 /// 597 /// opp_table.set_rate(freq)?; 598 /// Ok(opp_table) 599 /// } 600 /// ``` 601 pub struct Table { 602 ptr: *mut bindings::opp_table, 603 dev: ARef<Device>, 604 #[allow(dead_code)] 605 em: bool, 606 #[allow(dead_code)] 607 of: bool, 608 cpus: Option<CpumaskVar>, 609 } 610 611 /// SAFETY: It is okay to send ownership of [`Table`] across thread boundaries. 612 unsafe impl Send for Table {} 613 614 /// SAFETY: It is okay to access [`Table`] through shared references from other threads because 615 /// we're either accessing properties that don't change or that are properly synchronised by C code. 616 unsafe impl Sync for Table {} 617 618 impl Table { 619 /// Creates a new reference-counted [`Table`] from a raw pointer. 620 /// 621 /// # Safety 622 /// 623 /// Callers must ensure that `ptr` is valid and non-null. 624 unsafe fn from_raw_table(ptr: *mut bindings::opp_table, dev: &ARef<Device>) -> Self { 625 // SAFETY: By the safety requirements, ptr is valid and its refcount will be incremented. 626 // 627 // INVARIANT: The reference-count is decremented when [`Table`] goes out of scope. 628 unsafe { bindings::dev_pm_opp_get_opp_table_ref(ptr) }; 629 630 Self { 631 ptr, 632 dev: dev.clone(), 633 em: false, 634 of: false, 635 cpus: None, 636 } 637 } 638 639 /// Creates a new reference-counted [`Table`] instance for a [`Device`]. 640 pub fn from_dev(dev: &Device) -> Result<Self> { 641 // SAFETY: The requirements are satisfied by the existence of the [`Device`] and its safety 642 // requirements. 643 // 644 // INVARIANT: The reference-count is incremented by the C code and is decremented when 645 // [`Table`] goes out of scope. 646 let ptr = from_err_ptr(unsafe { bindings::dev_pm_opp_get_opp_table(dev.as_raw()) })?; 647 648 Ok(Self { 649 ptr, 650 dev: dev.into(), 651 em: false, 652 of: false, 653 cpus: None, 654 }) 655 } 656 657 /// Creates a new reference-counted [`Table`] instance for a [`Device`] based on device tree 658 /// entries. 659 #[cfg(CONFIG_OF)] 660 pub fn from_of(dev: &ARef<Device>, index: i32) -> Result<Self> { 661 // SAFETY: The requirements are satisfied by the existence of the [`Device`] and its safety 662 // requirements. 663 // 664 // INVARIANT: The reference-count is incremented by the C code and is decremented when 665 // [`Table`] goes out of scope. 666 to_result(unsafe { bindings::dev_pm_opp_of_add_table_indexed(dev.as_raw(), index) })?; 667 668 // Get the newly created [`Table`]. 669 let mut table = Self::from_dev(dev)?; 670 table.of = true; 671 672 Ok(table) 673 } 674 675 /// Remove device tree based [`Table`]. 676 #[cfg(CONFIG_OF)] 677 #[inline] 678 fn remove_of(&self) { 679 // SAFETY: The requirements are satisfied by the existence of the [`Device`] and its safety 680 // requirements. We took the reference from [`from_of`] earlier, it is safe to drop the 681 // same now. 682 unsafe { bindings::dev_pm_opp_of_remove_table(self.dev.as_raw()) }; 683 } 684 685 /// Creates a new reference-counted [`Table`] instance for a [`Cpumask`] based on device tree 686 /// entries. 687 #[cfg(CONFIG_OF)] 688 pub fn from_of_cpumask(dev: &Device, cpumask: &mut Cpumask) -> Result<Self> { 689 // SAFETY: The cpumask is valid and the returned pointer will be owned by the [`Table`] 690 // instance. 691 // 692 // INVARIANT: The reference-count is incremented by the C code and is decremented when 693 // [`Table`] goes out of scope. 694 to_result(unsafe { bindings::dev_pm_opp_of_cpumask_add_table(cpumask.as_raw()) })?; 695 696 // Fetch the newly created table. 697 let mut table = Self::from_dev(dev)?; 698 table.cpus = Some(CpumaskVar::try_clone(cpumask)?); 699 700 Ok(table) 701 } 702 703 /// Remove device tree based [`Table`] for a [`Cpumask`]. 704 #[cfg(CONFIG_OF)] 705 #[inline] 706 fn remove_of_cpumask(&self, cpumask: &Cpumask) { 707 // SAFETY: The cpumask is valid and we took the reference from [`from_of_cpumask`] earlier, 708 // it is safe to drop the same now. 709 unsafe { bindings::dev_pm_opp_of_cpumask_remove_table(cpumask.as_raw()) }; 710 } 711 712 /// Returns the number of [`OPP`]s in the [`Table`]. 713 pub fn opp_count(&self) -> Result<u32> { 714 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 715 // requirements. 716 let ret = unsafe { bindings::dev_pm_opp_get_opp_count(self.dev.as_raw()) }; 717 if ret < 0 { 718 Err(Error::from_errno(ret)) 719 } else { 720 Ok(ret as u32) 721 } 722 } 723 724 /// Returns max clock latency (in nanoseconds) of the [`OPP`]s in the [`Table`]. 725 #[inline] 726 pub fn max_clock_latency_ns(&self) -> usize { 727 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 728 // requirements. 729 unsafe { bindings::dev_pm_opp_get_max_clock_latency(self.dev.as_raw()) } 730 } 731 732 /// Returns max volt latency (in nanoseconds) of the [`OPP`]s in the [`Table`]. 733 #[inline] 734 pub fn max_volt_latency_ns(&self) -> usize { 735 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 736 // requirements. 737 unsafe { bindings::dev_pm_opp_get_max_volt_latency(self.dev.as_raw()) } 738 } 739 740 /// Returns max transition latency (in nanoseconds) of the [`OPP`]s in the [`Table`]. 741 #[inline] 742 pub fn max_transition_latency_ns(&self) -> usize { 743 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 744 // requirements. 745 unsafe { bindings::dev_pm_opp_get_max_transition_latency(self.dev.as_raw()) } 746 } 747 748 /// Returns the suspend [`OPP`]'s frequency. 749 #[inline] 750 pub fn suspend_freq(&self) -> Hertz { 751 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 752 // requirements. 753 Hertz(unsafe { bindings::dev_pm_opp_get_suspend_opp_freq(self.dev.as_raw()) }) 754 } 755 756 /// Synchronizes regulators used by the [`Table`]. 757 #[inline] 758 pub fn sync_regulators(&self) -> Result { 759 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 760 // requirements. 761 to_result(unsafe { bindings::dev_pm_opp_sync_regulators(self.dev.as_raw()) }) 762 } 763 764 /// Gets sharing CPUs. 765 #[inline] 766 pub fn sharing_cpus(dev: &Device, cpumask: &mut Cpumask) -> Result { 767 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 768 // requirements. 769 to_result(unsafe { bindings::dev_pm_opp_get_sharing_cpus(dev.as_raw(), cpumask.as_raw()) }) 770 } 771 772 /// Sets sharing CPUs. 773 pub fn set_sharing_cpus(&mut self, cpumask: &mut Cpumask) -> Result { 774 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 775 // requirements. 776 to_result(unsafe { 777 bindings::dev_pm_opp_set_sharing_cpus(self.dev.as_raw(), cpumask.as_raw()) 778 })?; 779 780 if let Some(mask) = self.cpus.as_mut() { 781 // Update the cpumask as this will be used while removing the table. 782 cpumask.copy(mask); 783 } 784 785 Ok(()) 786 } 787 788 /// Gets sharing CPUs from device tree. 789 #[cfg(CONFIG_OF)] 790 #[inline] 791 pub fn of_sharing_cpus(dev: &Device, cpumask: &mut Cpumask) -> Result { 792 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 793 // requirements. 794 to_result(unsafe { 795 bindings::dev_pm_opp_of_get_sharing_cpus(dev.as_raw(), cpumask.as_raw()) 796 }) 797 } 798 799 /// Updates the voltage value for an [`OPP`]. 800 #[inline] 801 pub fn adjust_voltage( 802 &self, 803 freq: Hertz, 804 volt: MicroVolt, 805 volt_min: MicroVolt, 806 volt_max: MicroVolt, 807 ) -> Result { 808 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 809 // requirements. 810 to_result(unsafe { 811 bindings::dev_pm_opp_adjust_voltage( 812 self.dev.as_raw(), 813 freq.into(), 814 volt.into(), 815 volt_min.into(), 816 volt_max.into(), 817 ) 818 }) 819 } 820 821 /// Creates [`FreqTable`] from [`Table`]. 822 #[cfg(CONFIG_CPU_FREQ)] 823 #[inline] 824 pub fn cpufreq_table(&mut self) -> Result<FreqTable> { 825 FreqTable::new(self) 826 } 827 828 /// Configures device with [`OPP`] matching the frequency value. 829 #[inline] 830 pub fn set_rate(&self, freq: Hertz) -> Result { 831 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 832 // requirements. 833 to_result(unsafe { bindings::dev_pm_opp_set_rate(self.dev.as_raw(), freq.into()) }) 834 } 835 836 /// Configures device with [`OPP`]. 837 #[inline] 838 pub fn set_opp(&self, opp: &OPP) -> Result { 839 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 840 // requirements. 841 to_result(unsafe { bindings::dev_pm_opp_set_opp(self.dev.as_raw(), opp.as_raw()) }) 842 } 843 844 /// Finds [`OPP`] based on frequency. 845 pub fn opp_from_freq( 846 &self, 847 freq: Hertz, 848 available: Option<bool>, 849 index: Option<u32>, 850 stype: SearchType, 851 ) -> Result<ARef<OPP>> { 852 let raw_dev = self.dev.as_raw(); 853 let index = index.unwrap_or(0); 854 let mut rate = freq.into(); 855 856 let ptr = from_err_ptr(match stype { 857 SearchType::Exact => { 858 if let Some(available) = available { 859 // SAFETY: The requirements are satisfied by the existence of [`Device`] and 860 // its safety requirements. The returned pointer will be owned by the new 861 // [`OPP`] instance. 862 unsafe { 863 bindings::dev_pm_opp_find_freq_exact_indexed( 864 raw_dev, rate, index, available, 865 ) 866 } 867 } else { 868 return Err(EINVAL); 869 } 870 } 871 872 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 873 // requirements. The returned pointer will be owned by the new [`OPP`] instance. 874 SearchType::Ceil => unsafe { 875 bindings::dev_pm_opp_find_freq_ceil_indexed(raw_dev, &mut rate, index) 876 }, 877 878 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 879 // requirements. The returned pointer will be owned by the new [`OPP`] instance. 880 SearchType::Floor => unsafe { 881 bindings::dev_pm_opp_find_freq_floor_indexed(raw_dev, &mut rate, index) 882 }, 883 })?; 884 885 // SAFETY: The `ptr` is guaranteed by the C code to be valid. 886 unsafe { OPP::from_raw_opp_owned(ptr) } 887 } 888 889 /// Finds [`OPP`] based on level. 890 pub fn opp_from_level(&self, mut level: u32, stype: SearchType) -> Result<ARef<OPP>> { 891 let raw_dev = self.dev.as_raw(); 892 893 let ptr = from_err_ptr(match stype { 894 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 895 // requirements. The returned pointer will be owned by the new [`OPP`] instance. 896 SearchType::Exact => unsafe { bindings::dev_pm_opp_find_level_exact(raw_dev, level) }, 897 898 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 899 // requirements. The returned pointer will be owned by the new [`OPP`] instance. 900 SearchType::Ceil => unsafe { 901 bindings::dev_pm_opp_find_level_ceil(raw_dev, &mut level) 902 }, 903 904 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 905 // requirements. The returned pointer will be owned by the new [`OPP`] instance. 906 SearchType::Floor => unsafe { 907 bindings::dev_pm_opp_find_level_floor(raw_dev, &mut level) 908 }, 909 })?; 910 911 // SAFETY: The `ptr` is guaranteed by the C code to be valid. 912 unsafe { OPP::from_raw_opp_owned(ptr) } 913 } 914 915 /// Finds [`OPP`] based on bandwidth. 916 pub fn opp_from_bw(&self, mut bw: u32, index: i32, stype: SearchType) -> Result<ARef<OPP>> { 917 let raw_dev = self.dev.as_raw(); 918 919 let ptr = from_err_ptr(match stype { 920 // The OPP core doesn't support this yet. 921 SearchType::Exact => return Err(EINVAL), 922 923 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 924 // requirements. The returned pointer will be owned by the new [`OPP`] instance. 925 SearchType::Ceil => unsafe { 926 bindings::dev_pm_opp_find_bw_ceil(raw_dev, &mut bw, index) 927 }, 928 929 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 930 // requirements. The returned pointer will be owned by the new [`OPP`] instance. 931 SearchType::Floor => unsafe { 932 bindings::dev_pm_opp_find_bw_floor(raw_dev, &mut bw, index) 933 }, 934 })?; 935 936 // SAFETY: The `ptr` is guaranteed by the C code to be valid. 937 unsafe { OPP::from_raw_opp_owned(ptr) } 938 } 939 940 /// Enables the [`OPP`]. 941 #[inline] 942 pub fn enable_opp(&self, freq: Hertz) -> Result { 943 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 944 // requirements. 945 to_result(unsafe { bindings::dev_pm_opp_enable(self.dev.as_raw(), freq.into()) }) 946 } 947 948 /// Disables the [`OPP`]. 949 #[inline] 950 pub fn disable_opp(&self, freq: Hertz) -> Result { 951 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 952 // requirements. 953 to_result(unsafe { bindings::dev_pm_opp_disable(self.dev.as_raw(), freq.into()) }) 954 } 955 956 /// Registers with the Energy model. 957 #[cfg(CONFIG_OF)] 958 pub fn of_register_em(&mut self, cpumask: &mut Cpumask) -> Result { 959 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 960 // requirements. 961 to_result(unsafe { 962 bindings::dev_pm_opp_of_register_em(self.dev.as_raw(), cpumask.as_raw()) 963 })?; 964 965 self.em = true; 966 Ok(()) 967 } 968 969 /// Unregisters with the Energy model. 970 #[cfg(all(CONFIG_OF, CONFIG_ENERGY_MODEL))] 971 #[inline] 972 fn of_unregister_em(&self) { 973 // SAFETY: The requirements are satisfied by the existence of [`Device`] and its safety 974 // requirements. We registered with the EM framework earlier, it is safe to unregister now. 975 unsafe { bindings::em_dev_unregister_perf_domain(self.dev.as_raw()) }; 976 } 977 } 978 979 impl Drop for Table { 980 fn drop(&mut self) { 981 // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe 982 // to relinquish it now. 983 unsafe { bindings::dev_pm_opp_put_opp_table(self.ptr) }; 984 985 #[cfg(CONFIG_OF)] 986 { 987 #[cfg(CONFIG_ENERGY_MODEL)] 988 if self.em { 989 self.of_unregister_em(); 990 } 991 992 if self.of { 993 self.remove_of(); 994 } else if let Some(cpumask) = self.cpus.take() { 995 self.remove_of_cpumask(&cpumask); 996 } 997 } 998 } 999 } 1000 1001 /// A reference-counted Operating performance point (OPP). 1002 /// 1003 /// Rust abstraction for the C `struct dev_pm_opp`. 1004 /// 1005 /// # Invariants 1006 /// 1007 /// The pointer stored in `Self` is non-null and valid for the lifetime of the [`OPP`]. 1008 /// 1009 /// Instances of this type are reference-counted. The reference count is incremented by the 1010 /// `dev_pm_opp_get` function and decremented by `dev_pm_opp_put`. The Rust type `ARef<OPP>` 1011 /// represents a pointer that owns a reference count on the [`OPP`]. 1012 /// 1013 /// A reference to the [`OPP`], &[`OPP`], isn't refcounted by the Rust code. 1014 /// 1015 /// # Examples 1016 /// 1017 /// The following example demonstrates how to get [`OPP`] corresponding to a frequency value and 1018 /// configure the device with it. 1019 /// 1020 /// ``` 1021 /// use kernel::clk::Hertz; 1022 /// use kernel::error::Result; 1023 /// use kernel::opp::{SearchType, Table}; 1024 /// 1025 /// fn configure_opp(table: &Table, freq: Hertz) -> Result { 1026 /// let opp = table.opp_from_freq(freq, Some(true), None, SearchType::Exact)?; 1027 /// 1028 /// if opp.freq(None) != freq { 1029 /// return Err(EINVAL); 1030 /// } 1031 /// 1032 /// table.set_opp(&opp) 1033 /// } 1034 /// ``` 1035 #[repr(transparent)] 1036 pub struct OPP(Opaque<bindings::dev_pm_opp>); 1037 1038 /// SAFETY: It is okay to send the ownership of [`OPP`] across thread boundaries. 1039 unsafe impl Send for OPP {} 1040 1041 /// SAFETY: It is okay to access [`OPP`] through shared references from other threads because we're 1042 /// either accessing properties that don't change or that are properly synchronised by C code. 1043 unsafe impl Sync for OPP {} 1044 1045 /// SAFETY: The type invariants guarantee that [`OPP`] is always refcounted. 1046 unsafe impl AlwaysRefCounted for OPP { 1047 fn inc_ref(&self) { 1048 // SAFETY: The existence of a shared reference means that the refcount is nonzero. 1049 unsafe { bindings::dev_pm_opp_get(self.0.get()) }; 1050 } 1051 1052 unsafe fn dec_ref(obj: ptr::NonNull<Self>) { 1053 // SAFETY: The safety requirements guarantee that the refcount is nonzero. 1054 unsafe { bindings::dev_pm_opp_put(obj.cast().as_ptr()) } 1055 } 1056 } 1057 1058 impl OPP { 1059 /// Creates an owned reference to a [`OPP`] from a valid pointer. 1060 /// 1061 /// The refcount is incremented by the C code and will be decremented by `dec_ref` when the 1062 /// [`ARef`] object is dropped. 1063 /// 1064 /// # Safety 1065 /// 1066 /// The caller must ensure that `ptr` is valid and the refcount of the [`OPP`] is incremented. 1067 /// The caller must also ensure that it doesn't explicitly drop the refcount of the [`OPP`], as 1068 /// the returned [`ARef`] object takes over the refcount increment on the underlying object and 1069 /// the same will be dropped along with it. 1070 pub unsafe fn from_raw_opp_owned(ptr: *mut bindings::dev_pm_opp) -> Result<ARef<Self>> { 1071 let ptr = ptr::NonNull::new(ptr).ok_or(ENODEV)?; 1072 1073 // SAFETY: The safety requirements guarantee the validity of the pointer. 1074 // 1075 // INVARIANT: The reference-count is decremented when [`OPP`] goes out of scope. 1076 Ok(unsafe { ARef::from_raw(ptr.cast()) }) 1077 } 1078 1079 /// Creates a reference to a [`OPP`] from a valid pointer. 1080 /// 1081 /// The refcount is not updated by the Rust API unless the returned reference is converted to 1082 /// an [`ARef`] object. 1083 /// 1084 /// # Safety 1085 /// 1086 /// The caller must ensure that `ptr` is valid and remains valid for the duration of `'a`. 1087 #[inline] 1088 pub unsafe fn from_raw_opp<'a>(ptr: *mut bindings::dev_pm_opp) -> Result<&'a Self> { 1089 // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the 1090 // duration of 'a. The cast is okay because [`OPP`] is `repr(transparent)`. 1091 Ok(unsafe { &*ptr.cast() }) 1092 } 1093 1094 #[inline] 1095 fn as_raw(&self) -> *mut bindings::dev_pm_opp { 1096 self.0.get() 1097 } 1098 1099 /// Returns the frequency of an [`OPP`]. 1100 pub fn freq(&self, index: Option<u32>) -> Hertz { 1101 let index = index.unwrap_or(0); 1102 1103 // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to 1104 // use it. 1105 Hertz(unsafe { bindings::dev_pm_opp_get_freq_indexed(self.as_raw(), index) }) 1106 } 1107 1108 /// Returns the voltage of an [`OPP`]. 1109 #[inline] 1110 pub fn voltage(&self) -> MicroVolt { 1111 // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to 1112 // use it. 1113 MicroVolt(unsafe { bindings::dev_pm_opp_get_voltage(self.as_raw()) }) 1114 } 1115 1116 /// Returns the level of an [`OPP`]. 1117 #[inline] 1118 pub fn level(&self) -> u32 { 1119 // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to 1120 // use it. 1121 unsafe { bindings::dev_pm_opp_get_level(self.as_raw()) } 1122 } 1123 1124 /// Returns the power of an [`OPP`]. 1125 #[inline] 1126 pub fn power(&self) -> MicroWatt { 1127 // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to 1128 // use it. 1129 MicroWatt(unsafe { bindings::dev_pm_opp_get_power(self.as_raw()) }) 1130 } 1131 1132 /// Returns the required pstate of an [`OPP`]. 1133 #[inline] 1134 pub fn required_pstate(&self, index: u32) -> u32 { 1135 // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to 1136 // use it. 1137 unsafe { bindings::dev_pm_opp_get_required_pstate(self.as_raw(), index) } 1138 } 1139 1140 /// Returns true if the [`OPP`] is turbo. 1141 #[inline] 1142 pub fn is_turbo(&self) -> bool { 1143 // SAFETY: By the type invariants, we know that `self` owns a reference, so it is safe to 1144 // use it. 1145 unsafe { bindings::dev_pm_opp_is_turbo(self.as_raw()) } 1146 } 1147 } 1148