mirror of https://gitee.com/openkylin/linux.git
Allwinner clock fixes for 4.11
Two build errors fixes for the sunxi-ng drivers. The two other patches fix random CPU crashes happening on the A33 since CPUFreq has been enabled in 4.11. -----BEGIN PGP SIGNATURE----- iQIcBAABCAAGBQJY70tbAAoJEBx+YmzsjxAg7e4P/iZK+swlFL9JNnFUqYXQkcrV xH1WAwUFMe8FCgV2VJHdqfULpFN7TEvPPzElyedZ4mEuw8IwrL5amf8BZIIpYjwd u93EuZDhHBg303iNjpV+40JC5sxppmNfE6Tsycoxd/9ce87vOwVOIv7iNQ/TIZPN smHrrr0/BSVmFBwLuqcSW4/fmRYHPRASxH1bnf+hzx1pQ7VYEnQpMKYoDFROO9ba OSP08eBLGARj+qQSvUaE0LYrXE/bx7ndOXBjAJM6wpdmTwdtS85ePr3XYvwz0/Wo IZwgGheR3SJauOh4x0V5MnMF9DhHXqCVn3TNduiy2IQeJkxZ4ykugd4l39yhW9aQ M7mzHQ4vjSAc2+NaWAdXV89ZS9GvSdsgxboAvRGyrX1947puy5p7fpLcrzWW6l6S u0QVa7f4+9B0sBTDXUq/gwn/kMVeBD5jMZ8G8lB8VGyAWPetyFXeKdPykk0Mj9O4 ljdrNvbLWeLscy5YmeoFIdjjVswPLm+EDwhildeF/bN29jeuMpSeeNC8ycGEDpue HY/dgaD+rlt6Vph6GNeupCFGQrYDjyjqGzz1phgTRy3ZFth3/IG4dMO/hfRE2LgB 7BJyuFqgW3k+JqHKVn+s+3JdnJygiJCmq3KwkmCO1VoLcE1tDRSzZ8N1nJLlUzd5 MWhrdlexpP1zVZseHLuC =92GZ -----END PGP SIGNATURE----- Merge tag 'sunxi-clk-fixes-for-4.11-2-bis' of https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux into clk-fixes Pull Allwinner clock fixes for 4.11 from Maxime Ripard: Two build errors fixes for the sunxi-ng drivers. The two other patches fix random CPU crashes happening on the A33 since CPUFreq has been enabled in 4.11. * tag 'sunxi-clk-fixes-for-4.11-2-bis' of https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux: clk: sunxi-ng: a33: gate then ungate PLL CPU clk after rate change clk: sunxi-ng: Add clk notifier to gate then ungate PLL clocks clk: sunxi-ng: fix build failure in ccu-sun9i-a80 driver clk: sunxi-ng: fix build error without CONFIG_RESET_CONTROLLER
This commit is contained in:
commit
e7590308d1
|
@ -1,6 +1,7 @@
|
|||
config SUNXI_CCU
|
||||
bool "Clock support for Allwinner SoCs"
|
||||
depends on ARCH_SUNXI || COMPILE_TEST
|
||||
select RESET_CONTROLLER
|
||||
default ARCH_SUNXI
|
||||
|
||||
if SUNXI_CCU
|
||||
|
@ -135,6 +136,7 @@ config SUN8I_V3S_CCU
|
|||
config SUN9I_A80_CCU
|
||||
bool "Support for the Allwinner A80 CCU"
|
||||
select SUNXI_CCU_DIV
|
||||
select SUNXI_CCU_MULT
|
||||
select SUNXI_CCU_GATE
|
||||
select SUNXI_CCU_NKMP
|
||||
select SUNXI_CCU_NM
|
||||
|
|
|
@ -752,6 +752,13 @@ static const struct sunxi_ccu_desc sun8i_a33_ccu_desc = {
|
|||
.num_resets = ARRAY_SIZE(sun8i_a33_ccu_resets),
|
||||
};
|
||||
|
||||
static struct ccu_pll_nb sun8i_a33_pll_cpu_nb = {
|
||||
.common = &pll_cpux_clk.common,
|
||||
/* copy from pll_cpux_clk */
|
||||
.enable = BIT(31),
|
||||
.lock = BIT(28),
|
||||
};
|
||||
|
||||
static struct ccu_mux_nb sun8i_a33_cpu_nb = {
|
||||
.common = &cpux_clk.common,
|
||||
.cm = &cpux_clk.mux,
|
||||
|
@ -783,6 +790,10 @@ static void __init sun8i_a33_ccu_setup(struct device_node *node)
|
|||
|
||||
sunxi_ccu_probe(node, reg, &sun8i_a33_ccu_desc);
|
||||
|
||||
/* Gate then ungate PLL CPU after any rate changes */
|
||||
ccu_pll_notifier_register(&sun8i_a33_pll_cpu_nb);
|
||||
|
||||
/* Reparent CPU during PLL CPU rate changes */
|
||||
ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
|
||||
&sun8i_a33_cpu_nb);
|
||||
}
|
||||
|
|
|
@ -14,11 +14,13 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "ccu_common.h"
|
||||
#include "ccu_gate.h"
|
||||
#include "ccu_reset.h"
|
||||
|
||||
static DEFINE_SPINLOCK(ccu_lock);
|
||||
|
@ -39,6 +41,53 @@ void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
|
|||
WARN_ON(readl_relaxed_poll_timeout(addr, reg, reg & lock, 100, 70000));
|
||||
}
|
||||
|
||||
/*
|
||||
* This clock notifier is called when the frequency of a PLL clock is
|
||||
* changed. In common PLL designs, changes to the dividers take effect
|
||||
* almost immediately, while changes to the multipliers (implemented
|
||||
* as dividers in the feedback loop) take a few cycles to work into
|
||||
* the feedback loop for the PLL to stablize.
|
||||
*
|
||||
* Sometimes when the PLL clock rate is changed, the decrease in the
|
||||
* divider is too much for the decrease in the multiplier to catch up.
|
||||
* The PLL clock rate will spike, and in some cases, might lock up
|
||||
* completely.
|
||||
*
|
||||
* This notifier callback will gate and then ungate the clock,
|
||||
* effectively resetting it, so it proceeds to work. Care must be
|
||||
* taken to reparent consumers to other temporary clocks during the
|
||||
* rate change, and that this notifier callback must be the first
|
||||
* to be registered.
|
||||
*/
|
||||
static int ccu_pll_notifier_cb(struct notifier_block *nb,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
struct ccu_pll_nb *pll = to_ccu_pll_nb(nb);
|
||||
int ret = 0;
|
||||
|
||||
if (event != POST_RATE_CHANGE)
|
||||
goto out;
|
||||
|
||||
ccu_gate_helper_disable(pll->common, pll->enable);
|
||||
|
||||
ret = ccu_gate_helper_enable(pll->common, pll->enable);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ccu_helper_wait_for_lock(pll->common, pll->lock);
|
||||
|
||||
out:
|
||||
return notifier_from_errno(ret);
|
||||
}
|
||||
|
||||
int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb)
|
||||
{
|
||||
pll_nb->clk_nb.notifier_call = ccu_pll_notifier_cb;
|
||||
|
||||
return clk_notifier_register(pll_nb->common->hw.clk,
|
||||
&pll_nb->clk_nb);
|
||||
}
|
||||
|
||||
int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
|
||||
const struct sunxi_ccu_desc *desc)
|
||||
{
|
||||
|
|
|
@ -83,6 +83,18 @@ struct sunxi_ccu_desc {
|
|||
|
||||
void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock);
|
||||
|
||||
struct ccu_pll_nb {
|
||||
struct notifier_block clk_nb;
|
||||
struct ccu_common *common;
|
||||
|
||||
u32 enable;
|
||||
u32 lock;
|
||||
};
|
||||
|
||||
#define to_ccu_pll_nb(_nb) container_of(_nb, struct ccu_pll_nb, clk_nb)
|
||||
|
||||
int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb);
|
||||
|
||||
int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
|
||||
const struct sunxi_ccu_desc *desc);
|
||||
|
||||
|
|
Loading…
Reference in New Issue