Skip to content
Open
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
36 changes: 35 additions & 1 deletion Documentation/devicetree/bindings/pwm/clk-pwm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ description: |
It's often possible to control duty-cycle of such clocks which makes them
suitable for generating PWM signal.

Optionally, a GPIO and pinctrl states can be provided. When a constant
output level is needed (0%, 100%, or disabled), the pin is switched to
GPIO mode to drive the level directly. For normal PWM output the pin is
switched back to its clock function mux.

allOf:
- $ref: pwm.yaml#

Expand All @@ -29,6 +34,26 @@ properties:
"#pwm-cells":
const: 2

gpios:
description:
Optional GPIO used to drive a constant level when the PWM output is
disabled or set to 0% / 100% duty cycle. When provided, pinctrl states
"default" (clock mux) and "gpio" must also be defined.
maxItems: 1

pinctrl-names: true

pinctrl-0:
description: Pin configuration for clock function mux (normal PWM).
maxItems: 1

pinctrl-1:
description: Pin configuration for GPIO mode (constant level output).
maxItems: 1

dependencies:
gpios: [ pinctrl-0, pinctrl-1 ]

unevaluatedProperties: false

required:
Expand All @@ -41,6 +66,15 @@ examples:
compatible = "clk-pwm";
#pwm-cells = <2>;
clocks = <&gcc 0>;
pinctrl-names = "default";
};

- |
pwm {
compatible = "clk-pwm";
#pwm-cells = <2>;
clocks = <&gcc 0>;
pinctrl-names = "default", "gpio";
pinctrl-0 = <&pwm_clk_flash_default>;
pinctrl-1 = <&pwm_clk_flash_gpio>;
gpios = <&tlmm 32 0>;
};
22 changes: 20 additions & 2 deletions drivers/clk/qcom/clk-branch.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,27 @@ static bool clk_branch2_check_halt(const struct clk_branch *br, bool enabling)
return (val & CBCR_CLK_OFF) == (invert ? 0 : CBCR_CLK_OFF);
}

static int get_branch_timeout(const struct clk_branch *br)
{
unsigned long rate;
int timeout;

/*
* The time it takes a clock branch to toggle is roughly 3 clock cycles.
*/
rate = clk_hw_get_rate(&br->clkr.hw);
if (!rate)
return 200;

timeout = 3 * (USEC_PER_SEC / rate);

return max(timeout, 200);
}

static int clk_branch_wait(const struct clk_branch *br, bool enabling,
bool (check_halt)(const struct clk_branch *, bool))
{
int timeout, count;
bool voted = br->halt_check & BRANCH_VOTED;
const char *name = clk_hw_get_name(&br->clkr.hw);

Expand All @@ -78,9 +96,9 @@ static int clk_branch_wait(const struct clk_branch *br, bool enabling,
} else if (br->halt_check == BRANCH_HALT_ENABLE ||
br->halt_check == BRANCH_HALT ||
(enabling && voted)) {
int count = 200;
timeout = get_branch_timeout(br);

while (count-- > 0) {
for (count = timeout; count > 0; count--) {
if (check_halt(br, enabling))
return 0;
udelay(1);
Expand Down
3 changes: 3 additions & 0 deletions drivers/clk/qcom/clk-rcg.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ extern const struct clk_ops clk_dyn_rcg_ops;
* @clkr: regmap clock handle
* @cfg_off: defines the cfg register offset from the CMD_RCGR + CFG_REG
* @parked_cfg: cached value of the CFG register for parked RCGs
* @configured_freq: last configured frequency, used for timeout calculation
* @hw_clk_ctrl: whether to enable hardware clock control
*/
struct clk_rcg2 {
Expand All @@ -153,6 +154,7 @@ struct clk_rcg2 {
struct clk_regmap clkr;
u8 cfg_off;
u32 parked_cfg;
unsigned long configured_freq;
bool hw_clk_ctrl;
};

Expand All @@ -168,6 +170,7 @@ struct clk_rcg2_gfx3d {
container_of(to_clk_rcg2(_hw), struct clk_rcg2_gfx3d, rcg)

extern const struct clk_ops clk_rcg2_ops;
extern const struct clk_ops clk_rcg2_gp_ops;
extern const struct clk_ops clk_rcg2_floor_ops;
extern const struct clk_ops clk_rcg2_mux_closest_ops;
extern const struct clk_ops clk_edp_pixel_ops;
Expand Down
Loading