clk: aspeed: Handle inverse polarity of USB port 1 clock gate
Subsystems (2)
PATCH 1/1 clk: aspeed: Handle inverse polarity of USB port 1 clock gate
The USB port 1 clock gate control has an inversed polarity from all the other clock gates in the chip. This makes the aspeed_clk_{enable,disable} functions honor the flag CLK_GATE_SET_TO_DISABLE and set that flag appropriately so it's set for all clocks except USB port 1.
--
I chose not to add a column to the table for that one special case. If future chips start growing more of these, we should consider adding this to the table instead.
Without this, USB port 1 doesn't work properly with the new clk driver.
--- drivers/clk/clk-aspeed.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/clk/clk-aspeed.c +12 -3
@@ -211,6 +211,7 @@ static int aspeed_clk_enable(struct clk_hw *hw)unsigned long flags;u32 clk =BIT (gate->clock_idx);u32 rst =BIT (gate->reset_idx); +u32 enval;spin_lock_irqsave (gate->lock, flags);
@@ -223,7 +224,8 @@ static int aspeed_clk_enable(struct clk_hw *hw) }/* Enable clock */ -regmap_update_bits (gate->map,ASPEED_CLK_STOP_CTRL , clk,0 ); + enval = (gate->flags &CLK_GATE_SET_TO_DISABLE ) ?0 : clk; +regmap_update_bits (gate->map,ASPEED_CLK_STOP_CTRL , clk, enval);if (gate->reset_idx >=0 ) {/* A delay of 10ms is specified by the ASPEED docs */
@@ -243,10 +245,12 @@ static void aspeed_clk_disable(struct clk_hw *hw)struct aspeed_clk_gate *gate =to_aspeed_clk_gate (hw);unsigned long flags;u32 clk =BIT (gate->clock_idx); +u32 enval;spin_lock_irqsave (gate->lock, flags); -regmap_update_bits (gate->map,ASPEED_CLK_STOP_CTRL , clk, clk); + enval = (gate->flags &CLK_GATE_SET_TO_DISABLE ) ? clk :0 ; +regmap_update_bits (gate->map,ASPEED_CLK_STOP_CTRL , clk, enval);spin_unlock_irqrestore (gate->lock, flags); }
@@ -478,7 +482,12 @@ static int aspeed_clk_probe(struct platform_device *pdev)for (i =0 ; i <ARRAY_SIZE (aspeed_gates); i++) {const struct aspeed_gate_data *gd = &aspeed_gates[i]; +u32 gate_flags; +/* Special case: the USB port 1 clock (bit 14) is always +* working the opposite way from the other ones. +*/ + gate_flags = (gd->clock_idx ==14 ) ?0 :CLK_GATE_SET_TO_DISABLE ; hw = aspeed_clk_hw_register_gate(dev, gd->name, gd->parent_name,
@@ -486,7 +495,7 @@ static int aspeed_clk_probe(struct platform_device *pdev) map, gd->clock_idx, gd->reset_idx, -CLK_GATE_SET_TO_DISABLE , + gate_flags, &aspeed_clk_lock);if (IS_ERR (hw))return PTR_ERR (hw);
Quoted 7 lines · Benjamin Herrenschmidt
The USB port 1 clock gate control has an inversed polarity from all the other clock gates in the chip. This makes the aspeed_clk_{enable,disable} functions honor the flag
CLK_GATE_SET_TO_DISABLEand set that flag appropriately so it's set for all clocks except USB port 1.Signed-off-by Benjamin Herrenschmidt <[email protected]>
Quoted 8 lines
--
I chose not to add a column to the table for that one special case. If future chips start growing more of these, we should consider adding this to the table instead.
Without this, USB port 1 doesn't work properly with the new clk driver.
Looks good. I gave this a spin on the ast2500 and the existing functionality worked fine. I don't have local access to test USB at the moment.
Cheers,
Joel
Quoted 65 lines
--- drivers/clk/clk-aspeed.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)drivers/clk/clk-aspeed.c +12
-3@@ -211,6 +211,7 @@ static int aspeed_clk_enable(struct clk_hw *hw)unsigned long flags;u32 clk =BIT (gate->clock_idx);u32 rst =BIT (gate->reset_idx); +u32 enval;spin_lock_irqsave (gate->lock, flags);@@ -223,7 +224,8 @@ static int aspeed_clk_enable(struct clk_hw *hw) }/* Enable clock */ -regmap_update_bits (gate->map,ASPEED_CLK_STOP_CTRL , clk,0 ); + enval = (gate->flags &CLK_GATE_SET_TO_DISABLE ) ?0 : clk; +regmap_update_bits (gate->map,ASPEED_CLK_STOP_CTRL , clk, enval);if (gate->reset_idx >=0 ) {/* A delay of 10ms is specified by the ASPEED docs */ @@ -243,10 +245,12 @@ static void aspeed_clk_disable(struct clk_hw *hw)struct aspeed_clk_gate *gate =to_aspeed_clk_gate (hw);unsigned long flags;u32 clk =BIT (gate->clock_idx); +u32 enval;spin_lock_irqsave (gate->lock, flags); -regmap_update_bits (gate->map,ASPEED_CLK_STOP_CTRL , clk, clk); + enval = (gate->flags &CLK_GATE_SET_TO_DISABLE ) ? clk :0 ; +regmap_update_bits (gate->map,ASPEED_CLK_STOP_CTRL , clk, enval);spin_unlock_irqrestore (gate->lock, flags); }@@ -478,7 +482,12 @@ static int aspeed_clk_probe(struct platform_device *pdev)for (i =0 ; i <ARRAY_SIZE (aspeed_gates); i++) {const struct aspeed_gate_data *gd = &aspeed_gates[i]; +u32 gate_flags; +/* Special case: the USB port 1 clock (bit 14) is always +* working the opposite way from the other ones. +*/ + gate_flags = (gd->clock_idx ==14 ) ?0 :CLK_GATE_SET_TO_DISABLE ; hw = aspeed_clk_hw_register_gate(dev, gd->name, gd->parent_name,@@ -486,7 +495,7 @@ static int aspeed_clk_probe(struct platform_device *pdev) map, gd->clock_idx, gd->reset_idx, -CLK_GATE_SET_TO_DISABLE , + gate_flags, &aspeed_clk_lock);if (IS_ERR (hw))return PTR_ERR (hw);
Stephen Boyd
AppliedQuoted 9 lines · Benjamin Herrenschmidt
The USB port 1 clock gate control has an inversed polarity from all the other clock gates in the chip. This makes the aspeed_clk_{enable,disable} functions honor the flag
CLK_GATE_SET_TO_DISABLEand set that flag appropriately so it's set for all clocks except USB port 1.Signed-off-by Benjamin Herrenschmidt <[email protected]>--
Quoted 8 lines
I chose not to add a column to the table for that one special case. If future chips start growing more of these, we should consider adding this to the table instead.
Without this, USB port 1 doesn't work properly with the new clk driver.
---
Applied to clk-next
Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project