18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * OMAP2/3 clockdomain framework functions
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2008, 2012 Texas Instruments, Inc.
68c2ecf20Sopenharmony_ci * Copyright (C) 2008-2011 Nokia Corporation
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Paul Walmsley
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#ifndef __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H
128c2ecf20Sopenharmony_ci#define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#include <linux/init.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "powerdomain.h"
178c2ecf20Sopenharmony_ci#include "clock.h"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/*
208c2ecf20Sopenharmony_ci * Clockdomain flags
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * XXX Document CLKDM_CAN_* flags
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * CLKDM_NO_AUTODEPS: Prevent "autodeps" from being added/removed from this
258c2ecf20Sopenharmony_ci *     clockdomain.  (Currently, this applies to OMAP3 clockdomains only.)
268c2ecf20Sopenharmony_ci * CLKDM_ACTIVE_WITH_MPU: The PRCM guarantees that this clockdomain is
278c2ecf20Sopenharmony_ci *     active whenever the MPU is active.  True for interconnects and
288c2ecf20Sopenharmony_ci *     the WKUP clockdomains.
298c2ecf20Sopenharmony_ci * CLKDM_MISSING_IDLE_REPORTING: The idle status of the IP blocks and
308c2ecf20Sopenharmony_ci *     clocks inside this clockdomain are not taken into account by
318c2ecf20Sopenharmony_ci *     the PRCM when determining whether the clockdomain is idle.
328c2ecf20Sopenharmony_ci *     Without this flag, if the clockdomain is set to
338c2ecf20Sopenharmony_ci *     hardware-supervised idle mode, the PRCM may transition the
348c2ecf20Sopenharmony_ci *     enclosing powerdomain to a low power state, even when devices
358c2ecf20Sopenharmony_ci *     inside the clockdomain and powerdomain are in use.  (An example
368c2ecf20Sopenharmony_ci *     of such a clockdomain is the EMU clockdomain on OMAP3/4.)  If
378c2ecf20Sopenharmony_ci *     this flag is set, and the clockdomain does not support the
388c2ecf20Sopenharmony_ci *     force-sleep mode, then the HW_AUTO mode will be used to put the
398c2ecf20Sopenharmony_ci *     clockdomain to sleep.  Similarly, if the clockdomain supports
408c2ecf20Sopenharmony_ci *     the force-wakeup mode, then it will be used whenever a clock or
418c2ecf20Sopenharmony_ci *     IP block inside the clockdomain is active, rather than the
428c2ecf20Sopenharmony_ci *     HW_AUTO mode.
438c2ecf20Sopenharmony_ci */
448c2ecf20Sopenharmony_ci#define CLKDM_CAN_FORCE_SLEEP			(1 << 0)
458c2ecf20Sopenharmony_ci#define CLKDM_CAN_FORCE_WAKEUP			(1 << 1)
468c2ecf20Sopenharmony_ci#define CLKDM_CAN_ENABLE_AUTO			(1 << 2)
478c2ecf20Sopenharmony_ci#define CLKDM_CAN_DISABLE_AUTO			(1 << 3)
488c2ecf20Sopenharmony_ci#define CLKDM_NO_AUTODEPS			(1 << 4)
498c2ecf20Sopenharmony_ci#define CLKDM_ACTIVE_WITH_MPU			(1 << 5)
508c2ecf20Sopenharmony_ci#define CLKDM_MISSING_IDLE_REPORTING		(1 << 6)
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#define CLKDM_CAN_HWSUP		(CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
538c2ecf20Sopenharmony_ci#define CLKDM_CAN_SWSUP		(CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
548c2ecf20Sopenharmony_ci#define CLKDM_CAN_HWSUP_SWSUP	(CLKDM_CAN_SWSUP | CLKDM_CAN_HWSUP)
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/**
578c2ecf20Sopenharmony_ci * struct clkdm_autodep - clkdm deps to add when entering/exiting hwsup mode
588c2ecf20Sopenharmony_ci * @clkdm: clockdomain to add wkdep+sleepdep on - set name member only
598c2ecf20Sopenharmony_ci *
608c2ecf20Sopenharmony_ci * A clockdomain that should have wkdeps and sleepdeps added when a
618c2ecf20Sopenharmony_ci * clockdomain should stay active in hwsup mode; and conversely,
628c2ecf20Sopenharmony_ci * removed when the clockdomain should be allowed to go inactive in
638c2ecf20Sopenharmony_ci * hwsup mode.
648c2ecf20Sopenharmony_ci *
658c2ecf20Sopenharmony_ci * Autodeps are deprecated and should be removed after
668c2ecf20Sopenharmony_ci * omap_hwmod-based fine-grained module idle control is added.
678c2ecf20Sopenharmony_ci */
688c2ecf20Sopenharmony_cistruct clkdm_autodep {
698c2ecf20Sopenharmony_ci	union {
708c2ecf20Sopenharmony_ci		const char *name;
718c2ecf20Sopenharmony_ci		struct clockdomain *ptr;
728c2ecf20Sopenharmony_ci	} clkdm;
738c2ecf20Sopenharmony_ci};
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci/**
768c2ecf20Sopenharmony_ci * struct clkdm_dep - encode dependencies between clockdomains
778c2ecf20Sopenharmony_ci * @clkdm_name: clockdomain name
788c2ecf20Sopenharmony_ci * @clkdm: pointer to the struct clockdomain of @clkdm_name
798c2ecf20Sopenharmony_ci * @wkdep_usecount: Number of wakeup dependencies causing this clkdm to wake
808c2ecf20Sopenharmony_ci * @sleepdep_usecount: Number of sleep deps that could prevent clkdm from idle
818c2ecf20Sopenharmony_ci *
828c2ecf20Sopenharmony_ci * Statically defined.  @clkdm is resolved from @clkdm_name at runtime and
838c2ecf20Sopenharmony_ci * should not be pre-initialized.
848c2ecf20Sopenharmony_ci *
858c2ecf20Sopenharmony_ci * XXX Should also include hardware (fixed) dependencies.
868c2ecf20Sopenharmony_ci */
878c2ecf20Sopenharmony_cistruct clkdm_dep {
888c2ecf20Sopenharmony_ci	const char *clkdm_name;
898c2ecf20Sopenharmony_ci	struct clockdomain *clkdm;
908c2ecf20Sopenharmony_ci	s16 wkdep_usecount;
918c2ecf20Sopenharmony_ci	s16 sleepdep_usecount;
928c2ecf20Sopenharmony_ci};
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci/* Possible flags for struct clockdomain._flags */
958c2ecf20Sopenharmony_ci#define _CLKDM_FLAG_HWSUP_ENABLED		BIT(0)
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistruct omap_hwmod;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci/**
1008c2ecf20Sopenharmony_ci * struct clockdomain - OMAP clockdomain
1018c2ecf20Sopenharmony_ci * @name: clockdomain name
1028c2ecf20Sopenharmony_ci * @pwrdm: powerdomain containing this clockdomain
1038c2ecf20Sopenharmony_ci * @clktrctrl_reg: CLKSTCTRL reg for the given clock domain
1048c2ecf20Sopenharmony_ci * @clktrctrl_mask: CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg
1058c2ecf20Sopenharmony_ci * @flags: Clockdomain capability flags
1068c2ecf20Sopenharmony_ci * @_flags: Flags for use only by internal clockdomain code
1078c2ecf20Sopenharmony_ci * @dep_bit: Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit
1088c2ecf20Sopenharmony_ci * @prcm_partition: (OMAP4 only) PRCM partition ID for this clkdm's registers
1098c2ecf20Sopenharmony_ci * @cm_inst: (OMAP4 only) CM instance register offset
1108c2ecf20Sopenharmony_ci * @clkdm_offs: (OMAP4 only) CM clockdomain register offset
1118c2ecf20Sopenharmony_ci * @wkdep_srcs: Clockdomains that can be told to wake this powerdomain up
1128c2ecf20Sopenharmony_ci * @sleepdep_srcs: Clockdomains that can be told to keep this clkdm from inact
1138c2ecf20Sopenharmony_ci * @usecount: Usecount tracking
1148c2ecf20Sopenharmony_ci * @forcewake_count: Usecount for forcing the domain active
1158c2ecf20Sopenharmony_ci * @node: list_head to link all clockdomains together
1168c2ecf20Sopenharmony_ci *
1178c2ecf20Sopenharmony_ci * @prcm_partition should be a macro from mach-omap2/prcm44xx.h (OMAP4 only)
1188c2ecf20Sopenharmony_ci * @cm_inst should be a macro ending in _INST from the OMAP4 CM instance
1198c2ecf20Sopenharmony_ci *     definitions (OMAP4 only)
1208c2ecf20Sopenharmony_ci * @clkdm_offs should be a macro ending in _CDOFFS from the OMAP4 CM instance
1218c2ecf20Sopenharmony_ci *     definitions (OMAP4 only)
1228c2ecf20Sopenharmony_ci */
1238c2ecf20Sopenharmony_cistruct clockdomain {
1248c2ecf20Sopenharmony_ci	const char *name;
1258c2ecf20Sopenharmony_ci	union {
1268c2ecf20Sopenharmony_ci		const char *name;
1278c2ecf20Sopenharmony_ci		struct powerdomain *ptr;
1288c2ecf20Sopenharmony_ci	} pwrdm;
1298c2ecf20Sopenharmony_ci	const u16 clktrctrl_mask;
1308c2ecf20Sopenharmony_ci	const u8 flags;
1318c2ecf20Sopenharmony_ci	u8 _flags;
1328c2ecf20Sopenharmony_ci	const u8 dep_bit;
1338c2ecf20Sopenharmony_ci	const u8 prcm_partition;
1348c2ecf20Sopenharmony_ci	const u16 cm_inst;
1358c2ecf20Sopenharmony_ci	const u16 clkdm_offs;
1368c2ecf20Sopenharmony_ci	struct clkdm_dep *wkdep_srcs;
1378c2ecf20Sopenharmony_ci	struct clkdm_dep *sleepdep_srcs;
1388c2ecf20Sopenharmony_ci	int usecount;
1398c2ecf20Sopenharmony_ci	int forcewake_count;
1408c2ecf20Sopenharmony_ci	struct list_head node;
1418c2ecf20Sopenharmony_ci	u32 context;
1428c2ecf20Sopenharmony_ci};
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci/**
1458c2ecf20Sopenharmony_ci * struct clkdm_ops - Arch specific function implementations
1468c2ecf20Sopenharmony_ci * @clkdm_add_wkdep: Add a wakeup dependency between clk domains
1478c2ecf20Sopenharmony_ci * @clkdm_del_wkdep: Delete a wakeup dependency between clk domains
1488c2ecf20Sopenharmony_ci * @clkdm_read_wkdep: Read wakeup dependency state between clk domains
1498c2ecf20Sopenharmony_ci * @clkdm_clear_all_wkdeps: Remove all wakeup dependencies from the clk domain
1508c2ecf20Sopenharmony_ci * @clkdm_add_sleepdep: Add a sleep dependency between clk domains
1518c2ecf20Sopenharmony_ci * @clkdm_del_sleepdep: Delete a sleep dependency between clk domains
1528c2ecf20Sopenharmony_ci * @clkdm_read_sleepdep: Read sleep dependency state between clk domains
1538c2ecf20Sopenharmony_ci * @clkdm_clear_all_sleepdeps: Remove all sleep dependencies from the clk domain
1548c2ecf20Sopenharmony_ci * @clkdm_sleep: Force a clockdomain to sleep
1558c2ecf20Sopenharmony_ci * @clkdm_wakeup: Force a clockdomain to wakeup
1568c2ecf20Sopenharmony_ci * @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain
1578c2ecf20Sopenharmony_ci * @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain
1588c2ecf20Sopenharmony_ci * @clkdm_clk_enable: Put the clkdm in right state for a clock enable
1598c2ecf20Sopenharmony_ci * @clkdm_clk_disable: Put the clkdm in right state for a clock disable
1608c2ecf20Sopenharmony_ci * @clkdm_save_context: Save the current clkdm context
1618c2ecf20Sopenharmony_ci * @clkdm_restore_context: Restore the clkdm context
1628c2ecf20Sopenharmony_ci */
1638c2ecf20Sopenharmony_cistruct clkdm_ops {
1648c2ecf20Sopenharmony_ci	int	(*clkdm_add_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
1658c2ecf20Sopenharmony_ci	int	(*clkdm_del_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
1668c2ecf20Sopenharmony_ci	int	(*clkdm_read_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
1678c2ecf20Sopenharmony_ci	int	(*clkdm_clear_all_wkdeps)(struct clockdomain *clkdm);
1688c2ecf20Sopenharmony_ci	int	(*clkdm_add_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
1698c2ecf20Sopenharmony_ci	int	(*clkdm_del_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
1708c2ecf20Sopenharmony_ci	int	(*clkdm_read_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
1718c2ecf20Sopenharmony_ci	int	(*clkdm_clear_all_sleepdeps)(struct clockdomain *clkdm);
1728c2ecf20Sopenharmony_ci	int	(*clkdm_sleep)(struct clockdomain *clkdm);
1738c2ecf20Sopenharmony_ci	int	(*clkdm_wakeup)(struct clockdomain *clkdm);
1748c2ecf20Sopenharmony_ci	void	(*clkdm_allow_idle)(struct clockdomain *clkdm);
1758c2ecf20Sopenharmony_ci	void	(*clkdm_deny_idle)(struct clockdomain *clkdm);
1768c2ecf20Sopenharmony_ci	int	(*clkdm_clk_enable)(struct clockdomain *clkdm);
1778c2ecf20Sopenharmony_ci	int	(*clkdm_clk_disable)(struct clockdomain *clkdm);
1788c2ecf20Sopenharmony_ci	int	(*clkdm_save_context)(struct clockdomain *clkdm);
1798c2ecf20Sopenharmony_ci	int	(*clkdm_restore_context)(struct clockdomain *clkdm);
1808c2ecf20Sopenharmony_ci};
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ciint clkdm_register_platform_funcs(struct clkdm_ops *co);
1838c2ecf20Sopenharmony_ciint clkdm_register_autodeps(struct clkdm_autodep *ia);
1848c2ecf20Sopenharmony_ciint clkdm_register_clkdms(struct clockdomain **c);
1858c2ecf20Sopenharmony_ciint clkdm_complete_init(void);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_cistruct clockdomain *clkdm_lookup(const char *name);
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ciint clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
1908c2ecf20Sopenharmony_ci			void *user);
1918c2ecf20Sopenharmony_cistruct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ciint clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
1948c2ecf20Sopenharmony_ciint clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
1958c2ecf20Sopenharmony_ciint clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
1968c2ecf20Sopenharmony_ciint clkdm_clear_all_wkdeps(struct clockdomain *clkdm);
1978c2ecf20Sopenharmony_ciint clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
1988c2ecf20Sopenharmony_ciint clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
1998c2ecf20Sopenharmony_ciint clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
2008c2ecf20Sopenharmony_ciint clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_civoid clkdm_allow_idle_nolock(struct clockdomain *clkdm);
2038c2ecf20Sopenharmony_civoid clkdm_allow_idle(struct clockdomain *clkdm);
2048c2ecf20Sopenharmony_civoid clkdm_deny_idle_nolock(struct clockdomain *clkdm);
2058c2ecf20Sopenharmony_civoid clkdm_deny_idle(struct clockdomain *clkdm);
2068c2ecf20Sopenharmony_cibool clkdm_in_hwsup(struct clockdomain *clkdm);
2078c2ecf20Sopenharmony_cibool clkdm_missing_idle_reporting(struct clockdomain *clkdm);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ciint clkdm_wakeup_nolock(struct clockdomain *clkdm);
2108c2ecf20Sopenharmony_ciint clkdm_wakeup(struct clockdomain *clkdm);
2118c2ecf20Sopenharmony_ciint clkdm_sleep_nolock(struct clockdomain *clkdm);
2128c2ecf20Sopenharmony_ciint clkdm_sleep(struct clockdomain *clkdm);
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ciint clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
2158c2ecf20Sopenharmony_ciint clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
2168c2ecf20Sopenharmony_ciint clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh);
2178c2ecf20Sopenharmony_ciint clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_civoid clkdm_save_context(void);
2208c2ecf20Sopenharmony_civoid clkdm_restore_context(void);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ciextern void __init omap242x_clockdomains_init(void);
2238c2ecf20Sopenharmony_ciextern void __init omap243x_clockdomains_init(void);
2248c2ecf20Sopenharmony_ciextern void __init omap3xxx_clockdomains_init(void);
2258c2ecf20Sopenharmony_ciextern void __init am33xx_clockdomains_init(void);
2268c2ecf20Sopenharmony_ciextern void __init ti814x_clockdomains_init(void);
2278c2ecf20Sopenharmony_ciextern void __init ti816x_clockdomains_init(void);
2288c2ecf20Sopenharmony_ciextern void __init omap44xx_clockdomains_init(void);
2298c2ecf20Sopenharmony_ciextern void __init omap54xx_clockdomains_init(void);
2308c2ecf20Sopenharmony_ciextern void __init dra7xx_clockdomains_init(void);
2318c2ecf20Sopenharmony_civoid am43xx_clockdomains_init(void);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ciextern void clkdm_add_autodeps(struct clockdomain *clkdm);
2348c2ecf20Sopenharmony_ciextern void clkdm_del_autodeps(struct clockdomain *clkdm);
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ciextern struct clkdm_ops omap2_clkdm_operations;
2378c2ecf20Sopenharmony_ciextern struct clkdm_ops omap3_clkdm_operations;
2388c2ecf20Sopenharmony_ciextern struct clkdm_ops omap4_clkdm_operations;
2398c2ecf20Sopenharmony_ciextern struct clkdm_ops am33xx_clkdm_operations;
2408c2ecf20Sopenharmony_ciextern struct clkdm_ops am43xx_clkdm_operations;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ciextern struct clkdm_dep gfx_24xx_wkdeps[];
2438c2ecf20Sopenharmony_ciextern struct clkdm_dep dsp_24xx_wkdeps[];
2448c2ecf20Sopenharmony_ciextern struct clockdomain wkup_common_clkdm;
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci#endif
247