Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S966097AbcJ2N5W (ORCPT ); Sat, 29 Oct 2016 09:57:22 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:50342 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S943326AbcJ2NyW (ORCPT ); Sat, 29 Oct 2016 09:54:22 -0400 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Eric Anholt , Martin Sperl , Stephen Boyd Subject: [PATCH 4.8 086/125] clk: bcm2835: Skip PLLC clocks when deciding on a new clock parent Date: Sat, 29 Oct 2016 09:50:04 -0400 Message-Id: <20161029134950.758077657@linuxfoundation.org> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20161029134947.232372651@linuxfoundation.org> References: <20161029134947.232372651@linuxfoundation.org> User-Agent: quilt/0.64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2544 Lines: 78 4.8-stable review patch. If anyone has any objections, please let me know. ------------------ From: Eric Anholt commit 67615c588a059b731df9d019edc3c561d8006ec9 upstream. If the firmware had set up a clock to source from PLLC, go along with it. But if we're looking for a new parent, we don't want to switch it to PLLC because the firmware will force PLLC (and thus the AXI bus clock) to different frequencies during over-temp/under-voltage, without notification to Linux. On my system, this moves the Linux-enabled HDMI state machine and DSI1 escape clock over to plld_per from pllc_per. EMMC still ends up on pllc_per, because the firmware had set it up to use that. Signed-off-by: Eric Anholt Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks") Acked-by: Martin Sperl Signed-off-by: Stephen Boyd Signed-off-by: Greg Kroah-Hartman --- drivers/clk/bcm/clk-bcm2835.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -1006,16 +1006,28 @@ static int bcm2835_clock_set_rate(struct return 0; } +static bool +bcm2835_clk_is_pllc(struct clk_hw *hw) +{ + if (!hw) + return false; + + return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0; +} + static int bcm2835_clock_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); struct clk_hw *parent, *best_parent = NULL; + bool current_parent_is_pllc; unsigned long rate, best_rate = 0; unsigned long prate, best_prate = 0; size_t i; u32 div; + current_parent_is_pllc = bcm2835_clk_is_pllc(clk_hw_get_parent(hw)); + /* * Select parent clock that results in the closest but lower rate */ @@ -1023,6 +1035,17 @@ static int bcm2835_clock_determine_rate( parent = clk_hw_get_parent_by_index(hw, i); if (!parent) continue; + + /* + * Don't choose a PLLC-derived clock as our parent + * unless it had been manually set that way. PLLC's + * frequency gets adjusted by the firmware due to + * over-temp or under-voltage conditions, without + * prior notification to our clock consumer. + */ + if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc) + continue; + prate = clk_hw_get_rate(parent); div = bcm2835_clock_choose_div(hw, req->rate, prate, true); rate = bcm2835_clock_rate_from_divisor(clock, prate, div);