Lines Matching +full:max +full:- +full:clk +full:- +full:rate +full:- +full:hz

1 // SPDX-License-Identifier: GPL-2.0
5 //! Rust T-HEAD TH1520 PWM driver
8 //! - The period and duty cycle are controlled by 32-bit hardware registers,
10 //! - The driver supports continuous output mode only; one-shot mode is not
12 //! - The controller hardware provides up to 6 PWM channels.
13 //! - Reconfiguration is glitch free - new period and duty cycle values are
15 //! - Polarity is handled via a simple hardware inversion bit; arbitrary
17 //! - Disabling a channel is achieved by configuring its duty cycle to zero to
26 clk::Clk,
38 const fn th1520_pwm_chn_base(n: u32) -> usize { in th1520_pwm_chn_base()
42 const fn th1520_pwm_ctrl(n: u32) -> usize { in th1520_pwm_ctrl()
46 const fn th1520_pwm_per(n: u32) -> usize { in th1520_pwm_per()
50 const fn th1520_pwm_fp(n: u32) -> usize { in th1520_pwm_fp()
62 fn ns_to_cycles(ns: u64, rate_hz: u64) -> u64 { in ns_to_cycles()
67 None => u64::MAX, in ns_to_cycles()
71 fn cycles_to_ns(cycles: u64, rate_hz: u64) -> u64 { in cycles_to_ns()
78 .saturating_add(rate_hz - 1); in cycles_to_ns()
83 /// Hardware-specific waveform representation for TH1520.
97 clk: Clk, field
100 // This `unsafe` implementation is a temporary necessity because the underlying `kernel::clk::Clk`
103 // TODO: Remove those unsafe impl's when Clk will support them itself.
107 // access to the contained `iomem` and `clk` resources.
122 ) -> Result<pwm::RoundedWaveform<Self::WfHw>> { in round_waveform_tohw()
138 let rate_hz = data.clk.rate().as_hz() as u64; in round_waveform_tohw()
140 let mut period_cycles = ns_to_cycles(wf.period_length_ns, rate_hz).min(u64::from(u32::MAX)); in round_waveform_tohw()
145 "Requested period {} ns is too small for clock rate {} Hz, rounding up.\n", in round_waveform_tohw()
154 let mut duty_cycles = ns_to_cycles(wf.duty_length_ns, rate_hz).min(u64::from(u32::MAX)); in round_waveform_tohw()
162 duty_cycles = period_cycles - duty_cycles; in round_waveform_tohw()
168 // The cast is safe because the value was clamped with `.min(u64::from(u32::MAX))`. in round_waveform_tohw()
177 "Requested: {}/{} ns [+{} ns] -> HW: {}/{} cycles, ctrl 0x{:x}, rate {} Hz\n", in round_waveform_tohw()
198 ) -> Result { in round_waveform_fromhw()
200 let rate_hz = data.clk.rate().as_hz() as u64; in round_waveform_fromhw()
222 // For an inverted signal, `duty_length_ns` is the high time (period - low_time). in round_waveform_fromhw()
235 ) -> Result<Self::WfHw> { in read_waveform()
254 … "PWM-{}: read_waveform: Read hw state - period: {}, duty: {}, ctrl: 0x{:x}, enabled: {}", in read_waveform()
270 ) -> Result { in write_waveform()
279 dev_dbg!(chip.device(), "PWM-{}: Disabling channel.\n", hwpwm); in write_waveform()
307 "PWM-{}: Wrote {}/{} cycles", in write_waveform()
320 self.clk.disable_unprepare(); in drop()
330 [(of::DeviceId::new(c_str!("thead,th1520-pwm")), ())]
340 ) -> impl PinInit<Self, Error> { in probe()
344 let clk = Clk::get(dev, None)?; in probe() localVariable
346 clk.prepare_enable()?; in probe()
348 // TODO: Get exclusive ownership of the clock to prevent rate changes. in probe()
351 let rate_hz = clk.rate().as_hz(); in probe()
353 dev_err!(dev, "Clock rate is zero\n"); in probe()
360 "Clock rate {} Hz is too high, not supported.\n", in probe()
370 iomem <- request.iomap_sized::<TH1520_PWM_REG_SIZE>(), in probe()
371 clk <- clk, in probe()
383 name: "pwm-th1520",
385 description: "T-HEAD TH1520 PWM driver",