Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: ingenic: Handle setting the Low-Power Mode bit

The Low-Power Mode, when enabled, will make the "wait" MIPS instruction
suspend the system.

This is not really clock-related, but this bit happens to be in the
register set of the CGU.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Paul Cercueil and committed by
Stephen Boyd
2ee93e3c dbc38ad0

+69 -32
+1 -1
drivers/clk/ingenic/Makefile
··· 1 - obj-$(CONFIG_INGENIC_CGU_COMMON) += cgu.o 1 + obj-$(CONFIG_INGENIC_CGU_COMMON) += cgu.o pm.o 2 2 obj-$(CONFIG_INGENIC_CGU_JZ4740) += jz4740-cgu.o 3 3 obj-$(CONFIG_INGENIC_CGU_JZ4725B) += jz4725b-cgu.o 4 4 obj-$(CONFIG_INGENIC_CGU_JZ4770) += jz4770-cgu.o
+3
drivers/clk/ingenic/jz4725b-cgu.c
··· 11 11 #include <linux/of.h> 12 12 #include <dt-bindings/clock/jz4725b-cgu.h> 13 13 #include "cgu.h" 14 + #include "pm.h" 14 15 15 16 /* CGU register offsets */ 16 17 #define CGU_REG_CPCCR 0x00 ··· 254 253 retval = ingenic_cgu_register_clocks(cgu); 255 254 if (retval) 256 255 pr_err("%s: failed to register CGU Clocks\n", __func__); 256 + 257 + ingenic_cgu_register_syscore_ops(cgu); 257 258 } 258 259 CLK_OF_DECLARE(jz4725b_cgu, "ingenic,jz4725b-cgu", jz4725b_cgu_init);
+3
drivers/clk/ingenic/jz4740-cgu.c
··· 22 22 #include <dt-bindings/clock/jz4740-cgu.h> 23 23 #include <asm/mach-jz4740/clock.h> 24 24 #include "cgu.h" 25 + #include "pm.h" 25 26 26 27 /* CGU register offsets */ 27 28 #define CGU_REG_CPCCR 0x00 ··· 248 247 retval = ingenic_cgu_register_clocks(cgu); 249 248 if (retval) 250 249 pr_err("%s: failed to register CGU Clocks\n", __func__); 250 + 251 + ingenic_cgu_register_syscore_ops(cgu); 251 252 } 252 253 CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init); 253 254
+2 -31
drivers/clk/ingenic/jz4770-cgu.c
··· 9 9 #include <linux/delay.h> 10 10 #include <linux/io.h> 11 11 #include <linux/of.h> 12 - #include <linux/syscore_ops.h> 13 12 #include <dt-bindings/clock/jz4770-cgu.h> 14 13 #include "cgu.h" 14 + #include "pm.h" 15 15 16 16 /* 17 17 * CPM registers offset address definition ··· 37 37 #define CGU_REG_MSC1CDR 0xA4 38 38 #define CGU_REG_MSC2CDR 0xA8 39 39 #define CGU_REG_BCHCDR 0xAC 40 - 41 - /* bits within the LCR register */ 42 - #define LCR_LPM BIT(0) /* Low Power Mode */ 43 40 44 41 /* bits within the OPCR register */ 45 42 #define OPCR_SPENDH BIT(5) /* UHC PHY suspend */ ··· 426 429 }, 427 430 }; 428 431 429 - #if IS_ENABLED(CONFIG_PM_SLEEP) 430 - static int jz4770_cgu_pm_suspend(void) 431 - { 432 - u32 val; 433 - 434 - val = readl(cgu->base + CGU_REG_LCR); 435 - writel(val | LCR_LPM, cgu->base + CGU_REG_LCR); 436 - return 0; 437 - } 438 - 439 - static void jz4770_cgu_pm_resume(void) 440 - { 441 - u32 val; 442 - 443 - val = readl(cgu->base + CGU_REG_LCR); 444 - writel(val & ~LCR_LPM, cgu->base + CGU_REG_LCR); 445 - } 446 - 447 - static struct syscore_ops jz4770_cgu_pm_ops = { 448 - .suspend = jz4770_cgu_pm_suspend, 449 - .resume = jz4770_cgu_pm_resume, 450 - }; 451 - #endif /* CONFIG_PM_SLEEP */ 452 - 453 432 static void __init jz4770_cgu_init(struct device_node *np) 454 433 { 455 434 int retval; ··· 439 466 if (retval) 440 467 pr_err("%s: failed to register CGU Clocks\n", __func__); 441 468 442 - #if IS_ENABLED(CONFIG_PM_SLEEP) 443 - register_syscore_ops(&jz4770_cgu_pm_ops); 444 - #endif 469 + ingenic_cgu_register_syscore_ops(cgu); 445 470 } 446 471 447 472 /* We only probe via devicetree, no need for a platform driver */
+3
drivers/clk/ingenic/jz4780-cgu.c
··· 21 21 #include <linux/of.h> 22 22 #include <dt-bindings/clock/jz4780-cgu.h> 23 23 #include "cgu.h" 24 + #include "pm.h" 24 25 25 26 /* CGU register offsets */ 26 27 #define CGU_REG_CLOCKCONTROL 0x00 ··· 731 730 pr_err("%s: failed to register CGU Clocks\n", __func__); 732 731 return; 733 732 } 733 + 734 + ingenic_cgu_register_syscore_ops(cgu); 734 735 } 735 736 CLK_OF_DECLARE(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init);
+45
drivers/clk/ingenic/pm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2019 Paul Cercueil <paul@crapouillou.net> 4 + */ 5 + 6 + #include "cgu.h" 7 + #include "pm.h" 8 + 9 + #include <linux/io.h> 10 + #include <linux/syscore_ops.h> 11 + 12 + #define CGU_REG_LCR 0x04 13 + 14 + #define LCR_LOW_POWER_MODE BIT(0) 15 + 16 + static void __iomem * __maybe_unused ingenic_cgu_base; 17 + 18 + static int __maybe_unused ingenic_cgu_pm_suspend(void) 19 + { 20 + u32 val = readl(ingenic_cgu_base + CGU_REG_LCR); 21 + 22 + writel(val | LCR_LOW_POWER_MODE, ingenic_cgu_base + CGU_REG_LCR); 23 + 24 + return 0; 25 + } 26 + 27 + static void __maybe_unused ingenic_cgu_pm_resume(void) 28 + { 29 + u32 val = readl(ingenic_cgu_base + CGU_REG_LCR); 30 + 31 + writel(val & ~LCR_LOW_POWER_MODE, ingenic_cgu_base + CGU_REG_LCR); 32 + } 33 + 34 + static struct syscore_ops __maybe_unused ingenic_cgu_pm_ops = { 35 + .suspend = ingenic_cgu_pm_suspend, 36 + .resume = ingenic_cgu_pm_resume, 37 + }; 38 + 39 + void ingenic_cgu_register_syscore_ops(struct ingenic_cgu *cgu) 40 + { 41 + if (IS_ENABLED(CONFIG_PM_SLEEP)) { 42 + ingenic_cgu_base = cgu->base; 43 + register_syscore_ops(&ingenic_cgu_pm_ops); 44 + } 45 + }
+12
drivers/clk/ingenic/pm.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2019 Paul Cercueil <paul@crapouillou.net> 4 + */ 5 + #ifndef DRIVERS_CLK_INGENIC_PM_H 6 + #define DRIVERS_CLK_INGENIC_PM_H 7 + 8 + struct ingenic_cgu; 9 + 10 + void ingenic_cgu_register_syscore_ops(struct ingenic_cgu *cgu); 11 + 12 + #endif /* DRIVERS_CLK_INGENIC_PM_H */