code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * OMAP44xx sleep code.
 *
 * Copyright (C) 2011 Texas Instruments, Inc.
 * 	Santosh Shilimkar <santosh.shilimkar@ti.com>
 */

#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/smp_scu.h>
#include <asm/memory.h>
#include <asm/hardware/cache-l2x0.h>

#include "omap-secure.h"

#include "common.h"
#include "omap44xx.h"
#include "omap4-sar-layout.h"

	.arch armv7-a

#if defined(CONFIG_SMP) && defined(CONFIG_PM)

	.arch_extension sec
.macro	DO_SMC
	dsb
	smc	#0
	dsb
.endm

#ifdef CONFIG_ARCH_OMAP4

/*
 * =============================
 * == CPU suspend finisher ==
 * =============================
 *
 * void omap4_finish_suspend(unsigned long cpu_state)
 *
 * This function code saves the CPU context and performs the CPU
 * power down sequence. Calling WFI effectively changes the CPU
 * power domains states to the desired target power state.
 *
 * @cpu_state : contains context save state (r0)
 *	0 - No context lost
 * 	1 - CPUx L1 and logic lost: MPUSS CSWR
 * 	2 - CPUx L1 and logic lost + GIC lost: MPUSS OSWR
 *	3 - CPUx L1 and logic lost + GIC + L2 lost: MPUSS OFF
 * @return: This function never returns for CPU OFF and DORMANT power states.
 * Post WFI, CPU transitions to DORMANT or OFF power state and on wake-up
 * from this follows a full CPU reset path via ROM code to CPU restore code.
 * The restore function pointer is stored at CPUx_WAKEUP_NS_PA_ADDR_OFFSET.
 * It returns to the caller for CPU INACTIVE and ON power states or in case
 * CPU failed to transition to targeted OFF/DORMANT state.
 *
 * omap4_finish_suspend() calls v7_flush_dcache_all() which doesn't save
 * stack frame and it expects the caller to take care of it. Hence the entire
 * stack frame is saved to avoid possible stack corruption.
 */
ENTRY(omap4_finish_suspend)
	stmfd	sp!, {r4-r12, lr}
	cmp	r0, #0x0
	beq	do_WFI				@ No lowpower state, jump to WFI

	/*
	 * Flush all data from the L1 data cache before disabling
	 * SCTLR.C bit.
	 */
	bl	omap4_get_sar_ram_base
	ldr	r9, [r0, #OMAP_TYPE_OFFSET]
	cmp	r9, #0x1			@ Check for HS device
	bne	skip_secure_l1_clean
	mov	r0, #SCU_PM_NORMAL
	mov	r1, #0xFF			@ clean seucre L1
	stmfd   r13!, {r4-r12, r14}
	ldr	r12, =OMAP4_MON_SCU_PWR_INDEX
	DO_SMC
	ldmfd   r13!, {r4-r12, r14}
skip_secure_l1_clean:
	bl	v7_flush_dcache_all

	/*
	 * Clear the SCTLR.C bit to prevent further data cache
	 * allocation. Clearing SCTLR.C would make all the data accesses
	 * strongly ordered and would not hit the cache.
	 */
	mrc	p15, 0, r0, c1, c0, 0
	bic	r0, r0, #(1 << 2)		@ Disable the C bit
	mcr	p15, 0, r0, c1, c0, 0
	isb

	bl	v7_invalidate_l1

	/*
	 * Switch the CPU from Symmetric Multiprocessing (SMP) mode
	 * to AsymmetricMultiprocessing (AMP) mode by programming
	 * the SCU power status to DORMANT or OFF mode.
	 * This enables the CPU to be taken out of coherency by
	 * preventing the CPU from receiving cache, TLB, or BTB
	 * maintenance operations broadcast by other CPUs in the cluster.
	 */
	bl	omap4_get_sar_ram_base
	mov	r8, r0
	ldr	r9, [r8, #OMAP_TYPE_OFFSET]
	cmp	r9, #0x1			@ Check for HS device
	bne	scu_gp_set
	mrc	p15, 0, r0, c0, c0, 5		@ Read MPIDR
	ands	r0, r0, #0x0f
	ldreq	r0, [r8, #SCU_OFFSET0]
	ldrne	r0, [r8, #SCU_OFFSET1]
	mov	r1, #0x00
	stmfd   r13!, {r4-r12, r14}
	ldr	r12, =OMAP4_MON_SCU_PWR_INDEX
	DO_SMC
	ldmfd   r13!, {r4-r12, r14}
	b	skip_scu_gp_set
scu_gp_set:
	mrc	p15, 0, r0, c0, c0, 5		@ Read MPIDR
	ands	r0, r0, #0x0f
	ldreq	r1, [r8, #SCU_OFFSET0]
	ldrne	r1, [r8, #SCU_OFFSET1]
	bl	omap4_get_scu_base
	bl	scu_power_mode
skip_scu_gp_set:
	mrc	p15, 0, r0, c1, c1, 2		@ Read NSACR data
	tst	r0, #(1 << 18)
	mrcne	p15, 0, r0, c1, c0, 1
	bicne	r0, r0, #(1 << 6)		@ Disable SMP bit
	mcrne	p15, 0, r0, c1, c0, 1
	isb
	dsb
#ifdef CONFIG_CACHE_L2X0
	/*
	 * Clean and invalidate the L2 cache.
	 * Common cache-l2x0.c functions can't be used here since it
	 * uses spinlocks. We are out of coherency here with data cache
	 * disabled. The spinlock implementation uses exclusive load/store
	 * instruction which can fail without data cache being enabled.
	 * OMAP4 hardware doesn't support exclusive monitor which can
	 * overcome exclusive access issue. Because of this, CPU can
	 * lead to deadlock.
	 */
	bl	omap4_get_sar_ram_base
	mov	r8, r0
	mrc	p15, 0, r5, c0, c0, 5		@ Read MPIDR
	ands	r5, r5, #0x0f
	ldreq	r0, [r8, #L2X0_SAVE_OFFSET0]	@ Retrieve L2 state from SAR
	ldrne	r0, [r8, #L2X0_SAVE_OFFSET1]	@ memory.
	cmp	r0, #3
	bne	do_WFI
#ifdef CONFIG_PL310_ERRATA_727915
	mov	r0, #0x03
	mov	r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
	DO_SMC
#endif
	bl	omap4_get_l2cache_base
	mov	r2, r0
	ldr	r0, =0xffff
	str	r0, [r2, #L2X0_CLEAN_INV_WAY]
wait:
	ldr	r0, [r2, #L2X0_CLEAN_INV_WAY]
	ldr	r1, =0xffff
	ands	r0, r0, r1
	bne	wait
#ifdef CONFIG_PL310_ERRATA_727915
	mov	r0, #0x00
	mov	r12, #OMAP4_MON_L2X0_DBG_CTRL_INDEX
	DO_SMC
#endif
l2x_sync:
	bl	omap4_get_l2cache_base
	mov	r2, r0
	mov	r0, #0x0
	str	r0, [r2, #L2X0_CACHE_SYNC]
sync:
	ldr	r0, [r2, #L2X0_CACHE_SYNC]
	ands	r0, r0, #0x1
	bne	sync
#endif

do_WFI:
	bl	omap_do_wfi

	/*
	 * CPU is here when it failed to enter OFF/DORMANT or
	 * no low power state was attempted.
	 */
	mrc	p15, 0, r0, c1, c0, 0
	tst	r0, #(1 << 2)			@ Check C bit enabled?
	orreq	r0, r0, #(1 << 2)		@ Enable the C bit
	mcreq	p15, 0, r0, c1, c0, 0
	isb

	/*
	 * Ensure the CPU power state is set to NORMAL in
	 * SCU power state so that CPU is back in coherency.
	 * In non-coherent mode CPU can lock-up and lead to
	 * system deadlock.
	 */
	mrc	p15, 0, r0, c1, c0, 1
	tst	r0, #(1 << 6)			@ Check SMP bit enabled?
	orreq	r0, r0, #(1 << 6)
	mcreq	p15, 0, r0, c1, c0, 1
	isb
	bl	omap4_get_sar_ram_base
	mov	r8, r0
	ldr	r9, [r8, #OMAP_TYPE_OFFSET]
	cmp	r9, #0x1			@ Check for HS device
	bne	scu_gp_clear
	mov	r0, #SCU_PM_NORMAL
	mov	r1, #0x00
	stmfd   r13!, {r4-r12, r14}
	ldr	r12, =OMAP4_MON_SCU_PWR_INDEX
	DO_SMC
	ldmfd   r13!, {r4-r12, r14}
	b	skip_scu_gp_clear
scu_gp_clear:
	bl	omap4_get_scu_base
	mov	r1, #SCU_PM_NORMAL
	bl	scu_power_mode
skip_scu_gp_clear:
	isb
	dsb
	ldmfd	sp!, {r4-r12, pc}
ENDPROC(omap4_finish_suspend)

/*
 * ============================
 * == CPU resume entry point ==
 * ============================
 *
 * void omap4_cpu_resume(void)
 *
 * ROM code jumps to this function while waking up from CPU
 * OFF or DORMANT state. Physical address of the function is
 * stored in the SAR RAM while entering to OFF or DORMANT mode.
 * The restore function pointer is stored at CPUx_WAKEUP_NS_PA_ADDR_OFFSET.
 */
ENTRY(omap4_cpu_resume)
	/*
	 * Configure ACTRL and enable NS SMP bit access on CPU1 on HS device.
	 * OMAP44XX EMU/HS devices - CPU0 SMP bit access is enabled in PPA
	 * init and for CPU1, a secure PPA API provided. CPU0 must be ON
	 * while executing NS_SMP API on CPU1 and PPA version must be 1.4.0+.
	 * OMAP443X GP devices- SMP bit isn't accessible.
	 * OMAP446X GP devices - SMP bit access is enabled on both CPUs.
	 */
	ldr	r8, =OMAP44XX_SAR_RAM_BASE
	ldr	r9, [r8, #OMAP_TYPE_OFFSET]
	cmp	r9, #0x1			@ Skip if GP device
	bne	skip_ns_smp_enable
	mrc     p15, 0, r0, c0, c0, 5
	ands    r0, r0, #0x0f
	beq	skip_ns_smp_enable
ppa_actrl_retry:
	mov     r0, #OMAP4_PPA_CPU_ACTRL_SMP_INDEX
	adr	r1, ppa_zero_params_offset
	ldr	r3, [r1]
	add	r3, r3, r1			@ Pointer to ppa_zero_params
	mov	r1, #0x0			@ Process ID
	mov	r2, #0x4			@ Flag
	mov	r6, #0xff
	mov	r12, #0x00			@ Secure Service ID
	DO_SMC
	cmp	r0, #0x0			@ API returns 0 on success.
	beq	enable_smp_bit
	b	ppa_actrl_retry
enable_smp_bit:
	mrc	p15, 0, r0, c1, c0, 1
	tst	r0, #(1 << 6)			@ Check SMP bit enabled?
	orreq	r0, r0, #(1 << 6)
	mcreq	p15, 0, r0, c1, c0, 1
	isb
skip_ns_smp_enable:
#ifdef CONFIG_CACHE_L2X0
	/*
	 * Restore the L2 AUXCTRL and enable the L2 cache.
	 * OMAP4_MON_L2X0_AUXCTRL_INDEX =  Program the L2X0 AUXCTRL
	 * OMAP4_MON_L2X0_CTRL_INDEX =  Enable the L2 using L2X0 CTRL
	 * register r0 contains value to be programmed.
	 * L2 cache is already invalidate by ROM code as part
	 * of MPUSS OFF wakeup path.
	 */
	ldr	r2, =OMAP44XX_L2CACHE_BASE
	ldr	r0, [r2, #L2X0_CTRL]
	and	r0, #0x0f
	cmp	r0, #1
	beq	skip_l2en			@ Skip if already enabled
	ldr	r3, =OMAP44XX_SAR_RAM_BASE
	ldr	r1, [r3, #OMAP_TYPE_OFFSET]
	cmp	r1, #0x1			@ Check for HS device
	bne     set_gp_por
	ldr     r0, =OMAP4_PPA_L2_POR_INDEX
	ldr     r1, =OMAP44XX_SAR_RAM_BASE
	ldr     r4, [r1, #L2X0_PREFETCH_CTRL_OFFSET]
	adr     r1, ppa_por_params_offset
	ldr	r3, [r1]
	add	r3, r3, r1			@ Pointer to ppa_por_params
	str     r4, [r3, #0x04]
	mov	r1, #0x0			@ Process ID
	mov	r2, #0x4			@ Flag
	mov	r6, #0xff
	mov	r12, #0x00			@ Secure Service ID
	DO_SMC
	b	set_aux_ctrl
set_gp_por:
	ldr     r1, =OMAP44XX_SAR_RAM_BASE
	ldr     r0, [r1, #L2X0_PREFETCH_CTRL_OFFSET]
	ldr	r12, =OMAP4_MON_L2X0_PREFETCH_INDEX	@ Setup L2 PREFETCH
	DO_SMC
set_aux_ctrl:
	ldr     r1, =OMAP44XX_SAR_RAM_BASE
	ldr	r0, [r1, #L2X0_AUXCTRL_OFFSET]
	ldr	r12, =OMAP4_MON_L2X0_AUXCTRL_INDEX	@ Setup L2 AUXCTRL
	DO_SMC
	mov	r0, #0x1
	ldr	r12, =OMAP4_MON_L2X0_CTRL_INDEX		@ Enable L2 cache
	DO_SMC
skip_l2en:
#endif

	b	cpu_resume			@ Jump to generic resume
ppa_por_params_offset:
	.long	ppa_por_params - .
ENDPROC(omap4_cpu_resume)
#endif	/* CONFIG_ARCH_OMAP4 */

#endif	/* defined(CONFIG_SMP) && defined(CONFIG_PM) */

ENTRY(omap_do_wfi)
	stmfd	sp!, {lr}
#ifdef CONFIG_OMAP_INTERCONNECT_BARRIER
	/* Drain interconnect write buffers. */
	bl	omap_interconnect_sync
#endif

	/*
	 * Execute an ISB instruction to ensure that all of the
	 * CP15 register changes have been committed.
	 */
	isb

	/*
	 * Execute a barrier instruction to ensure that all cache,
	 * TLB and branch predictor maintenance operations issued
	 * by any CPU in the cluster have completed.
	 */
	dsb
	dmb

	/*
	 * Execute a WFI instruction and wait until the
	 * STANDBYWFI output is asserted to indicate that the
	 * CPU is in idle and low power state. CPU can specualatively
	 * prefetch the instructions so add NOPs after WFI. Sixteen
	 * NOPs as per Cortex-A9 pipeline.
	 */
	wfi					@ Wait For Interrupt
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop

	ldmfd	sp!, {pc}
ppa_zero_params_offset:
	.long	ppa_zero_params - .
ENDPROC(omap_do_wfi)

	.data
	.align	2
ppa_zero_params:
	.word		0

ppa_por_params:
	.word		1, 0


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Smart reflex Class 3 specific implementations
 *
 * Author: Thara Gopinath       <thara@ti.com>
 *
 * Copyright (C) 2010 Texas Instruments, Inc.
 * Thara Gopinath <thara@ti.com>
 */

#include <linux/power/smartreflex.h>
#include "soc.h"
#include "voltage.h"

static int sr_class3_enable(struct omap_sr *sr)
{
	unsigned long volt = voltdm_get_voltage(sr->voltdm);

	if (!volt) {
		pr_warn("%s: Curr voltage unknown. Cannot enable %s\n",
			__func__, sr->name);
		return -ENODATA;
	}

	omap_vp_enable(sr->voltdm);
	return sr_enable(sr, volt);
}

static int sr_class3_disable(struct omap_sr *sr, int is_volt_reset)
{
	sr_disable_errgen(sr);
	omap_vp_disable(sr->voltdm);
	sr_disable(sr);
	if (is_volt_reset)
		voltdm_reset(sr->voltdm);

	return 0;
}

static int sr_class3_configure(struct omap_sr *sr)
{
	return sr_configure_errgen(sr);
}

/* SR class3 structure */
static struct omap_sr_class_data class3_data = {
	.enable = sr_class3_enable,
	.disable = sr_class3_disable,
	.configure = sr_class3_configure,
	.class_type = SR_CLASS3,
};

/* Smartreflex Class3 init API to be called from board file */
static int __init sr_class3_init(void)
{
	pr_info("SmartReflex Class3 initialized\n");
	return sr_register_class(&class3_data);
}
omap_late_initcall(sr_class3_init);

repo_name: angery/linux


code:
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * OMAP cpu type detection
 *
 * Copyright (C) 2004, 2008 Nokia Corporation
 *
 * Copyright (C) 2009-11 Texas Instruments.
 *
 * Written by Tony Lindgren <tony.lindgren@nokia.com>
 *
 * Added OMAP4/5 specific defines - Santosh Shilimkar<santosh.shilimkar@ti.com>
 * Added DRA7xxx specific defines - Sricharan R<r.sricharan@ti.com>
 */

#include "omap24xx.h"
#include "omap34xx.h"
#include "omap44xx.h"
#include "ti81xx.h"
#include "am33xx.h"
#include "omap54xx.h"

#ifndef __ASSEMBLY__

#include <linux/bitops.h>
#include <linux/of.h>

/*
 * OMAP2+ is always defined as ARCH_MULTIPLATFORM in Kconfig
 */
#undef MULTI_OMAP2
#define MULTI_OMAP2

/*
 * Omap device type i.e. EMU/HS/TST/GP/BAD
 */
#define OMAP2_DEVICE_TYPE_TEST		0
#define OMAP2_DEVICE_TYPE_EMU		1
#define OMAP2_DEVICE_TYPE_SEC		2
#define OMAP2_DEVICE_TYPE_GP		3
#define OMAP2_DEVICE_TYPE_BAD		4

int omap_type(void);

/*
 * omap_rev bits:
 * SoC id bits	(0730, 1510, 1710, 2422...)	[31:16]
 * SoC revision	(See _REV_ defined in cpu.h)	[15:08]
 * SoC class bits (15xx, 16xx, 24xx, 34xx...)	[07:00]
 */
unsigned int omap_rev(void);

static inline int soc_is_omap(void)
{
	return omap_rev() != 0;
}

/*
 * Get the SoC revision for OMAP devices
 */
#define GET_OMAP_REVISION()	((omap_rev() >> 8) & 0xff)

/*
 * Macros to group OMAP into cpu classes.
 * These can be used in most places.
 * soc_is_omap24xx():	True for OMAP2420, OMAP2422, OMAP2423, OMAP2430
 * soc_is_omap242x():	True for OMAP2420, OMAP2422, OMAP2423
 * soc_is_omap243x():	True for OMAP2430
 * soc_is_omap343x():	True for OMAP3430
 * soc_is_omap443x():	True for OMAP4430
 * soc_is_omap446x():	True for OMAP4460
 * soc_is_omap447x():	True for OMAP4470
 * soc_is_omap543x():	True for OMAP5430, OMAP5432
 */
#define GET_OMAP_CLASS	(omap_rev() & 0xff)

#define IS_OMAP_CLASS(class, id)			\
static inline int is_omap ##class (void)		\
{							\
	return (GET_OMAP_CLASS == (id)) ? 1 : 0;	\
}

#define GET_AM_CLASS	((omap_rev() >> 24) & 0xff)

#define IS_AM_CLASS(class, id)				\
static inline int is_am ##class (void)			\
{							\
	return (GET_AM_CLASS == (id)) ? 1 : 0;		\
}

#define GET_TI_CLASS	((omap_rev() >> 24) & 0xff)

#define IS_TI_CLASS(class, id)			\
static inline int is_ti ##class (void)		\
{							\
	return (GET_TI_CLASS == (id)) ? 1 : 0;	\
}

#define GET_DRA_CLASS	((omap_rev() >> 24) & 0xff)

#define IS_DRA_CLASS(class, id)				\
static inline int is_dra ##class (void)			\
{							\
	return (GET_DRA_CLASS == (id)) ? 1 : 0;		\
}

#define GET_OMAP_SUBCLASS	((omap_rev() >> 20) & 0x0fff)

#define IS_OMAP_SUBCLASS(subclass, id)			\
static inline int is_omap ##subclass (void)		\
{							\
	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
}

#define IS_TI_SUBCLASS(subclass, id)			\
static inline int is_ti ##subclass (void)		\
{							\
	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
}

#define IS_AM_SUBCLASS(subclass, id)			\
static inline int is_am ##subclass (void)		\
{							\
	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
}

#define IS_DRA_SUBCLASS(subclass, id)			\
static inline int is_dra ##subclass (void)		\
{							\
	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
}

#define GET_DRA_PACKAGE		(omap_rev() & 0xff)

#define IS_DRA_SUBCLASS_PACKAGE(subclass, package, id)			\
static inline int is_dra ##subclass ##_ ##package (void)		\
{									\
	return (is_dra ##subclass () && GET_DRA_PACKAGE == id) ? 1 : 0;	\
}

IS_OMAP_CLASS(24xx, 0x24)
IS_OMAP_CLASS(34xx, 0x34)
IS_OMAP_CLASS(44xx, 0x44)
IS_AM_CLASS(35xx, 0x35)
IS_OMAP_CLASS(54xx, 0x54)
IS_AM_CLASS(33xx, 0x33)
IS_AM_CLASS(43xx, 0x43)

IS_TI_CLASS(81xx, 0x81)
IS_DRA_CLASS(7xx, 0x7)

IS_OMAP_SUBCLASS(242x, 0x242)
IS_OMAP_SUBCLASS(243x, 0x243)
IS_OMAP_SUBCLASS(343x, 0x343)
IS_OMAP_SUBCLASS(363x, 0x363)
IS_OMAP_SUBCLASS(443x, 0x443)
IS_OMAP_SUBCLASS(446x, 0x446)
IS_OMAP_SUBCLASS(447x, 0x447)
IS_OMAP_SUBCLASS(543x, 0x543)

IS_TI_SUBCLASS(816x, 0x816)
IS_TI_SUBCLASS(814x, 0x814)
IS_AM_SUBCLASS(335x, 0x335)
IS_AM_SUBCLASS(437x, 0x437)
IS_DRA_SUBCLASS(76x, 0x76)
IS_DRA_SUBCLASS_PACKAGE(76x, abz, 2)
IS_DRA_SUBCLASS_PACKAGE(76x, acd, 3)
IS_DRA_SUBCLASS(75x, 0x75)
IS_DRA_SUBCLASS(72x, 0x72)

#define soc_is_ti81xx()			0
#define soc_is_ti816x()			0
#define soc_is_ti814x()			0
#define soc_is_am35xx()			0
#define soc_is_am33xx()			0
#define soc_is_am335x()			0
#define soc_is_am43xx()			0
#define soc_is_am437x()			0
#define soc_is_omap44xx()		0
#define soc_is_omap443x()		0
#define soc_is_omap446x()		0
#define soc_is_omap447x()		0
#define soc_is_omap54xx()		0
#define soc_is_omap543x()		0
#define soc_is_dra7xx()			0
#define soc_is_dra76x()			0
#define soc_is_dra74x()			0
#define soc_is_dra72x()			0

#if defined(CONFIG_ARCH_OMAP2)
# define soc_is_omap24xx()		is_omap24xx()
#else
# define soc_is_omap24xx()		0
#endif
#if defined(CONFIG_SOC_OMAP2420)
# define soc_is_omap242x()		is_omap242x()
#else
# define soc_is_omap242x()		0
#endif
#if defined(CONFIG_SOC_OMAP2430)
# define soc_is_omap243x()		is_omap243x()
#else
# define soc_is_omap243x()		0
#endif
#if defined(CONFIG_ARCH_OMAP3)
# define soc_is_omap34xx()		is_omap34xx()
# define soc_is_omap343x()		is_omap343x()
#else
# define soc_is_omap34xx()		0
# define soc_is_omap343x()		0
#endif

/*
 * Macros to detect individual cpu types.
 * These are only rarely needed.
 * soc_is_omap2420():	True for OMAP2420
 * soc_is_omap2422():	True for OMAP2422
 * soc_is_omap2423():	True for OMAP2423
 * soc_is_omap2430():	True for OMAP2430
 * soc_is_omap3430():	True for OMAP3430
 */
#define GET_OMAP_TYPE	((omap_rev() >> 16) & 0xffff)

#define IS_OMAP_TYPE(type, id)				\
static inline int is_omap ##type (void)			\
{							\
	return (GET_OMAP_TYPE == (id)) ? 1 : 0;		\
}

IS_OMAP_TYPE(2420, 0x2420)
IS_OMAP_TYPE(2422, 0x2422)
IS_OMAP_TYPE(2423, 0x2423)
IS_OMAP_TYPE(2430, 0x2430)
IS_OMAP_TYPE(3430, 0x3430)

#define soc_is_omap2420()		0
#define soc_is_omap2422()		0
#define soc_is_omap2423()		0
#define soc_is_omap2430()		0
#define soc_is_omap3430()		0
#define soc_is_omap3630()		0
#define soc_is_omap5430()		0

/* These are needed for the common code */
#define soc_is_omap7xx()		0
#define soc_is_omap15xx()		0
#define soc_is_omap16xx()		0
#define soc_is_omap1510()		0
#define soc_is_omap1610()		0
#define soc_is_omap1611()		0
#define soc_is_omap1621()		0
#define soc_is_omap1710()		0
#define cpu_class_is_omap1()		0
#define cpu_class_is_omap2()		1

#if defined(CONFIG_ARCH_OMAP2)
# undef  soc_is_omap2420
# undef  soc_is_omap2422
# undef  soc_is_omap2423
# undef  soc_is_omap2430
# define soc_is_omap2420()		is_omap2420()
# define soc_is_omap2422()		is_omap2422()
# define soc_is_omap2423()		is_omap2423()
# define soc_is_omap2430()		is_omap2430()
#endif

#if defined(CONFIG_ARCH_OMAP3)
# undef soc_is_omap3430
# undef soc_is_ti81xx
# undef soc_is_ti816x
# undef soc_is_ti814x
# undef soc_is_am35xx
# define soc_is_omap3430()		is_omap3430()
# undef soc_is_omap3630
# define soc_is_omap3630()		is_omap363x()
# define soc_is_ti81xx()		is_ti81xx()
# define soc_is_ti816x()		is_ti816x()
# define soc_is_ti814x()		is_ti814x()
# define soc_is_am35xx()		is_am35xx()
#endif

# if defined(CONFIG_SOC_AM33XX)
# undef soc_is_am33xx
# undef soc_is_am335x
# define soc_is_am33xx()		is_am33xx()
# define soc_is_am335x()		is_am335x()
#endif

#ifdef	CONFIG_SOC_AM43XX
# undef soc_is_am43xx
# undef soc_is_am437x
# define soc_is_am43xx()		is_am43xx()
# define soc_is_am437x()		is_am437x()
#endif

# if defined(CONFIG_ARCH_OMAP4)
# undef soc_is_omap44xx
# undef soc_is_omap443x
# undef soc_is_omap446x
# undef soc_is_omap447x
# define soc_is_omap44xx()		is_omap44xx()
# define soc_is_omap443x()		is_omap443x()
# define soc_is_omap446x()		is_omap446x()
# define soc_is_omap447x()		is_omap447x()
# endif

# if defined(CONFIG_SOC_OMAP5)
# undef soc_is_omap54xx
# undef soc_is_omap543x
# define soc_is_omap54xx()		is_omap54xx()
# define soc_is_omap543x()		is_omap543x()
#endif

#if defined(CONFIG_SOC_DRA7XX)
#undef soc_is_dra7xx
#undef soc_is_dra76x
#undef soc_is_dra76x_abz
#undef soc_is_dra76x_acd
#undef soc_is_dra74x
#undef soc_is_dra72x
#define soc_is_dra7xx()	is_dra7xx()
#define soc_is_dra76x()	is_dra76x()
#define soc_is_dra76x_abz()	is_dra76x_abz()
#define soc_is_dra76x_acd()	is_dra76x_acd()
#define soc_is_dra74x()	is_dra75x()
#define soc_is_dra72x()	is_dra72x()
#endif

/* Various silicon revisions for omap2 */
#define OMAP242X_CLASS		0x24200024
#define OMAP2420_REV_ES1_0	OMAP242X_CLASS
#define OMAP2420_REV_ES2_0	(OMAP242X_CLASS | (0x1 << 8))

#define OMAP243X_CLASS		0x24300024
#define OMAP2430_REV_ES1_0	OMAP243X_CLASS

#define OMAP343X_CLASS		0x34300034
#define OMAP3430_REV_ES1_0	OMAP343X_CLASS
#define OMAP3430_REV_ES2_0	(OMAP343X_CLASS | (0x1 << 8))
#define OMAP3430_REV_ES2_1	(OMAP343X_CLASS | (0x2 << 8))
#define OMAP3430_REV_ES3_0	(OMAP343X_CLASS | (0x3 << 8))
#define OMAP3430_REV_ES3_1	(OMAP343X_CLASS | (0x4 << 8))
#define OMAP3430_REV_ES3_1_2	(OMAP343X_CLASS | (0x5 << 8))

#define OMAP363X_CLASS		0x36300034
#define OMAP3630_REV_ES1_0	OMAP363X_CLASS
#define OMAP3630_REV_ES1_1	(OMAP363X_CLASS | (0x1 << 8))
#define OMAP3630_REV_ES1_2	(OMAP363X_CLASS | (0x2 << 8))

#define TI816X_CLASS		0x81600081
#define TI8168_REV_ES1_0	TI816X_CLASS
#define TI8168_REV_ES1_1	(TI816X_CLASS | (0x1 << 8))
#define TI8168_REV_ES2_0	(TI816X_CLASS | (0x2 << 8))
#define TI8168_REV_ES2_1	(TI816X_CLASS | (0x3 << 8))

#define TI814X_CLASS		0x81400081
#define TI8148_REV_ES1_0	TI814X_CLASS
#define TI8148_REV_ES2_0	(TI814X_CLASS | (0x1 << 8))
#define TI8148_REV_ES2_1	(TI814X_CLASS | (0x2 << 8))

#define AM35XX_CLASS		0x35170034
#define AM35XX_REV_ES1_0	AM35XX_CLASS
#define AM35XX_REV_ES1_1	(AM35XX_CLASS | (0x1 << 8))

#define AM335X_CLASS		0x33500033
#define AM335X_REV_ES1_0	AM335X_CLASS
#define AM335X_REV_ES2_0	(AM335X_CLASS | (0x1 << 8))
#define AM335X_REV_ES2_1	(AM335X_CLASS | (0x2 << 8))

#define AM437X_CLASS		0x43700000
#define AM437X_REV_ES1_0	(AM437X_CLASS | (0x10 << 8))
#define AM437X_REV_ES1_1	(AM437X_CLASS | (0x11 << 8))
#define AM437X_REV_ES1_2	(AM437X_CLASS | (0x12 << 8))

#define OMAP443X_CLASS		0x44300044
#define OMAP4430_REV_ES1_0	(OMAP443X_CLASS | (0x10 << 8))
#define OMAP4430_REV_ES2_0	(OMAP443X_CLASS | (0x20 << 8))
#define OMAP4430_REV_ES2_1	(OMAP443X_CLASS | (0x21 << 8))
#define OMAP4430_REV_ES2_2	(OMAP443X_CLASS | (0x22 << 8))
#define OMAP4430_REV_ES2_3	(OMAP443X_CLASS | (0x23 << 8))

#define OMAP446X_CLASS		0x44600044
#define OMAP4460_REV_ES1_0	(OMAP446X_CLASS | (0x10 << 8))
#define OMAP4460_REV_ES1_1	(OMAP446X_CLASS | (0x11 << 8))

#define OMAP447X_CLASS		0x44700044
#define OMAP4470_REV_ES1_0	(OMAP447X_CLASS | (0x10 << 8))

#define OMAP54XX_CLASS		0x54000054
#define OMAP5430_REV_ES2_0	(OMAP54XX_CLASS | (0x30 << 16) | (0x20 << 8))
#define OMAP5432_REV_ES2_0	(OMAP54XX_CLASS | (0x32 << 16) | (0x20 << 8))

#define DRA7XX_CLASS		0x07000000
#define DRA762_REV_ES1_0	(DRA7XX_CLASS | (0x62 << 16) | (0x10 << 8))
#define DRA762_ABZ_REV_ES1_0	(DRA762_REV_ES1_0 | (2 << 0))
#define DRA762_ACD_REV_ES1_0	(DRA762_REV_ES1_0 | (3 << 0))
#define DRA752_REV_ES1_0	(DRA7XX_CLASS | (0x52 << 16) | (0x10 << 8))
#define DRA752_REV_ES1_1	(DRA7XX_CLASS | (0x52 << 16) | (0x11 << 8))
#define DRA752_REV_ES2_0	(DRA7XX_CLASS | (0x52 << 16) | (0x20 << 8))
#define DRA722_REV_ES1_0	(DRA7XX_CLASS | (0x22 << 16) | (0x10 << 8))
#define DRA722_REV_ES2_0	(DRA7XX_CLASS | (0x22 << 16) | (0x20 << 8))
#define DRA722_REV_ES2_1	(DRA7XX_CLASS | (0x22 << 16) | (0x21 << 8))

void omap2xxx_check_revision(void);
void omap3xxx_check_revision(void);
void omap4xxx_check_revision(void);
void omap5xxx_check_revision(void);
void dra7xxx_check_revision(void);
void omap3xxx_check_features(void);
void ti81xx_check_features(void);
void am33xx_check_features(void);
void omap4xxx_check_features(void);

/*
 * Runtime detection of OMAP3 features
 *
 * OMAP3_HAS_IO_CHAIN_CTRL: Some later members of the OMAP3 chip
 *    family have OS-level control over the I/O chain clock.  This is
 *    to avoid a window during which wakeups could potentially be lost
 *    during powerdomain transitions.  If this bit is set, it
 *    indicates that the chip does support OS-level control of this
 *    feature.
 */
extern u32 omap_features;

#define OMAP3_HAS_L2CACHE		BIT(0)
#define OMAP3_HAS_IVA			BIT(1)
#define OMAP3_HAS_SGX			BIT(2)
#define OMAP3_HAS_NEON			BIT(3)
#define OMAP3_HAS_ISP			BIT(4)
#define OMAP3_HAS_192MHZ_CLK		BIT(5)
#define OMAP3_HAS_IO_WAKEUP		BIT(6)
#define OMAP3_HAS_SDRC			BIT(7)
#define OMAP3_HAS_IO_CHAIN_CTRL		BIT(8)
#define OMAP4_HAS_PERF_SILICON		BIT(9)

#define OMAP3_HAS_FEATURE(feat,flag)			\
static inline unsigned int omap3_has_ ##feat(void)	\
{							\
	return omap_features & OMAP3_HAS_ ##flag;	\
}							\

OMAP3_HAS_FEATURE(l2cache, L2CACHE)
OMAP3_HAS_FEATURE(sgx, SGX)
OMAP3_HAS_FEATURE(iva, IVA)
OMAP3_HAS_FEATURE(neon, NEON)
OMAP3_HAS_FEATURE(isp, ISP)
OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
OMAP3_HAS_FEATURE(sdrc, SDRC)
OMAP3_HAS_FEATURE(io_chain_ctrl, IO_CHAIN_CTRL)

/*
 * Runtime detection of OMAP4 features
 */
#define OMAP4_HAS_FEATURE(feat, flag)			\
static inline unsigned int omap4_has_ ##feat(void)	\
{							\
	return omap_features & OMAP4_HAS_ ##flag;	\
}							\

OMAP4_HAS_FEATURE(perf_silicon, PERF_SILICON)

/*
 * We need to make sure omap initcalls don't run when
 * multiplatform kernels are booted on other SoCs.
 */
#define omap_initcall(level, fn)		\
static int __init __used __##fn(void)		\
{						\
	if (!soc_is_omap())			\
		return 0;			\
	return fn();				\
}						\
level(__##fn);

#define omap_early_initcall(fn)		omap_initcall(early_initcall, fn)
#define omap_core_initcall(fn)		omap_initcall(core_initcall, fn)
#define omap_postcore_initcall(fn)	omap_initcall(postcore_initcall, fn)
#define omap_arch_initcall(fn)		omap_initcall(arch_initcall, fn)
#define omap_subsys_initcall(fn)	omap_initcall(subsys_initcall, fn)
#define omap_device_initcall(fn)	omap_initcall(device_initcall, fn)
#define omap_late_initcall(fn)		omap_initcall(late_initcall, fn)
#define omap_late_initcall_sync(fn)	omap_initcall(late_initcall_sync, fn)

/* Legacy defines, these can be removed when users are removed */
#define cpu_is_omap2420()	soc_is_omap2420()
#define cpu_is_omap2422()	soc_is_omap2422()
#define cpu_is_omap242x()	soc_is_omap242x()
#define cpu_is_omap2430()	soc_is_omap2430()
#define cpu_is_omap243x()	soc_is_omap243x()
#define cpu_is_omap24xx()	soc_is_omap24xx()
#define cpu_is_omap3430()	soc_is_omap3430()
#define cpu_is_omap343x()	soc_is_omap343x()
#define cpu_is_omap34xx()	soc_is_omap34xx()
#define cpu_is_omap3630()	soc_is_omap3630()
#define cpu_is_omap443x()	soc_is_omap443x()
#define cpu_is_omap446x()	soc_is_omap446x()
#define cpu_is_omap44xx()	soc_is_omap44xx()
#define cpu_is_ti814x()		soc_is_ti814x()
#define cpu_is_ti816x()		soc_is_ti816x()
#define cpu_is_ti81xx()		soc_is_ti81xx()

#endif	/* __ASSEMBLY__ */


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * OMAP3/OMAP4 smartreflex device file
 *
 * Author: Thara Gopinath	<thara@ti.com>
 *
 * Based originally on code from smartreflex.c
 * Copyright (C) 2010 Texas Instruments, Inc.
 * Thara Gopinath <thara@ti.com>
 *
 * Copyright (C) 2008 Nokia Corporation
 * Kalle Jokiniemi
 *
 * Copyright (C) 2007 Texas Instruments, Inc.
 * Lesly A M <x0080970@ti.com>
 */
#include <linux/power/smartreflex.h>

#include <linux/err.h>
#include <linux/slab.h>
#include <linux/io.h>

#include "soc.h"
#include "omap_device.h"
#include "voltage.h"
#include "control.h"
#include "pm.h"

static bool sr_enable_on_init;

/* Read EFUSE values from control registers for OMAP3430 */
static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
				struct omap_sr_data *sr_data)
{
	struct omap_sr_nvalue_table *nvalue_table;
	int i, j, count = 0;

	sr_data->nvalue_count = 0;
	sr_data->nvalue_table = NULL;

	while (volt_data[count].volt_nominal)
		count++;

	nvalue_table = kcalloc(count, sizeof(*nvalue_table), GFP_KERNEL);
	if (!nvalue_table)
		return;

	for (i = 0, j = 0; i < count; i++) {
		u32 v;

		/*
		 * In OMAP4 the efuse registers are 24 bit aligned.
		 * A readl_relaxed will fail for non-32 bit aligned address
		 * and hence the 8-bit read and shift.
		 */
		if (cpu_is_omap44xx()) {
			u16 offset = volt_data[i].sr_efuse_offs;

			v = omap_ctrl_readb(offset) |
				omap_ctrl_readb(offset + 1) << 8 |
				omap_ctrl_readb(offset + 2) << 16;
		} else {
			v = omap_ctrl_readl(volt_data[i].sr_efuse_offs);
		}

		/*
		 * Many OMAP SoCs don't have the eFuse values set.
		 * For example, pretty much all OMAP3xxx before
		 * ES3.something.
		 *
		 * XXX There needs to be some way for board files or
		 * userspace to add these in.
		 */
		if (v == 0)
			continue;

		nvalue_table[j].nvalue = v;
		nvalue_table[j].efuse_offs = volt_data[i].sr_efuse_offs;
		nvalue_table[j].errminlimit = volt_data[i].sr_errminlimit;
		nvalue_table[j].volt_nominal = volt_data[i].volt_nominal;

		j++;
	}

	sr_data->nvalue_table = nvalue_table;
	sr_data->nvalue_count = j;
}

extern struct omap_sr_data omap_sr_pdata[];

static int __init sr_init_by_name(const char *name, const char *voltdm)
{
	struct omap_sr_data *sr_data = NULL;
	struct omap_volt_data *volt_data;
	static int i;

	if (!strncmp(name, "smartreflex_mpu_iva", 20) ||
	    !strncmp(name, "smartreflex_mpu", 16))
		sr_data = &omap_sr_pdata[OMAP_SR_MPU];
	else if (!strncmp(name, "smartreflex_core", 17))
		sr_data = &omap_sr_pdata[OMAP_SR_CORE];
	else if (!strncmp(name, "smartreflex_iva", 16))
		sr_data = &omap_sr_pdata[OMAP_SR_IVA];

	if (!sr_data) {
		pr_err("%s: Unknown instance %s\n", __func__, name);
		return -EINVAL;
	}

	sr_data->name = name;
	if (cpu_is_omap343x())
		sr_data->ip_type = 1;
	else
		sr_data->ip_type = 2;
	sr_data->senn_mod = 0x1;
	sr_data->senp_mod = 0x1;

	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
		sr_data->err_weight = OMAP3430_SR_ERRWEIGHT;
		sr_data->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
		sr_data->accum_data = OMAP3430_SR_ACCUMDATA;
		if (!(strcmp(sr_data->name, "smartreflex_mpu"))) {
			sr_data->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
			sr_data->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
		} else {
			sr_data->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
			sr_data->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
		}
	}

	sr_data->voltdm = voltdm_lookup(voltdm);
	if (!sr_data->voltdm) {
		pr_err("%s: Unable to get voltage domain pointer for VDD %s\n",
			__func__, voltdm);
		goto exit;
	}

	omap_voltage_get_volttable(sr_data->voltdm, &volt_data);
	if (!volt_data) {
		pr_err("%s: No Voltage table registered for VDD%d\n",
		       __func__, i + 1);
		goto exit;
	}

	sr_set_nvalues(volt_data, sr_data);

	sr_data->enable_on_init = sr_enable_on_init;

exit:
	i++;

	return 0;
}

#ifdef CONFIG_OMAP_HWMOD
static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
{
	struct omap_smartreflex_dev_attr *sr_dev_attr;

	sr_dev_attr = (struct omap_smartreflex_dev_attr *)oh->dev_attr;
	if (!sr_dev_attr || !sr_dev_attr->sensor_voltdm_name) {
		pr_err("%s: No voltage domain specified for %s. Cannot initialize\n",
		       __func__, oh->name);
		return 0;
	}

	return sr_init_by_name(oh->name, sr_dev_attr->sensor_voltdm_name);
}
#else
static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
{
	return -EINVAL;
}
#endif

/*
 * API to be called from board files to enable smartreflex
 * autocompensation at init.
 */
void __init omap_enable_smartreflex_on_init(void)
{
	sr_enable_on_init = true;
}

static const char * const omap4_sr_instances[] = {
	"mpu",
	"iva",
	"core",
};

static const char * const dra7_sr_instances[] = {
	"mpu",
	"core",
};

int __init omap_devinit_smartreflex(void)
{
	const char * const *sr_inst = NULL;
	int i, nr_sr = 0;

	if (soc_is_omap44xx()) {
		sr_inst = omap4_sr_instances;
		nr_sr = ARRAY_SIZE(omap4_sr_instances);

	} else if (soc_is_dra7xx()) {
		sr_inst = dra7_sr_instances;
		nr_sr = ARRAY_SIZE(dra7_sr_instances);
	}

	if (nr_sr) {
		const char *name, *voltdm;

		for (i = 0; i < nr_sr; i++) {
			name = kasprintf(GFP_KERNEL, "smartreflex_%s", sr_inst[i]);
			voltdm = sr_inst[i];
			sr_init_by_name(name, voltdm);
		}

		return 0;
	}

	return omap_hwmod_for_each_by_class("smartreflex", sr_dev_init, NULL);
}


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 *
 * OMAP SRAM detection and management
 *
 * Copyright (C) 2005 Nokia Corporation
 * Written by Tony Lindgren <tony@atomide.com>
 *
 * Copyright (C) 2009-2012 Texas Instruments
 * Added OMAP4/5 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>

#include <asm/fncpy.h>
#include <asm/tlb.h>
#include <asm/cacheflush.h>
#include <asm/set_memory.h>

#include <asm/mach/map.h>

#include "soc.h"
#include "iomap.h"
#include "prm2xxx_3xxx.h"
#include "sdrc.h"
#include "sram.h"

#define OMAP2_SRAM_PUB_PA	(OMAP2_SRAM_PA + 0xf800)
#define OMAP3_SRAM_PUB_PA       (OMAP3_SRAM_PA + 0x8000)

#define SRAM_BOOTLOADER_SZ	0x00

#define OMAP24XX_VA_REQINFOPERM0	OMAP2_L3_IO_ADDRESS(0x68005048)
#define OMAP24XX_VA_READPERM0		OMAP2_L3_IO_ADDRESS(0x68005050)
#define OMAP24XX_VA_WRITEPERM0		OMAP2_L3_IO_ADDRESS(0x68005058)

#define OMAP34XX_VA_REQINFOPERM0	OMAP2_L3_IO_ADDRESS(0x68012848)
#define OMAP34XX_VA_READPERM0		OMAP2_L3_IO_ADDRESS(0x68012850)
#define OMAP34XX_VA_WRITEPERM0		OMAP2_L3_IO_ADDRESS(0x68012858)
#define OMAP34XX_VA_ADDR_MATCH2		OMAP2_L3_IO_ADDRESS(0x68012880)
#define OMAP34XX_VA_SMS_RG_ATT0		OMAP2_L3_IO_ADDRESS(0x6C000048)

#define GP_DEVICE		0x300

#define ROUND_DOWN(value,boundary)	((value) & (~((boundary)-1)))

static unsigned long omap_sram_start;
static unsigned long omap_sram_size;
static void __iomem *omap_sram_base;
static unsigned long omap_sram_skip;
static void __iomem *omap_sram_ceil;

/*
 * Memory allocator for SRAM: calculates the new ceiling address
 * for pushing a function using the fncpy API.
 *
 * Note that fncpy requires the returned address to be aligned
 * to an 8-byte boundary.
 */
static void *omap_sram_push_address(unsigned long size)
{
	unsigned long available, new_ceil = (unsigned long)omap_sram_ceil;

	available = omap_sram_ceil - (omap_sram_base + omap_sram_skip);

	if (size > available) {
		pr_err("Not enough space in SRAM\n");
		return NULL;
	}

	new_ceil -= size;
	new_ceil = ROUND_DOWN(new_ceil, FNCPY_ALIGN);
	omap_sram_ceil = IOMEM(new_ceil);

	return (void __force *)omap_sram_ceil;
}

void *omap_sram_push(void *funcp, unsigned long size)
{
	void *sram;
	unsigned long base;
	int pages;
	void *dst = NULL;

	sram = omap_sram_push_address(size);
	if (!sram)
		return NULL;

	base = (unsigned long)sram & PAGE_MASK;
	pages = PAGE_ALIGN(size) / PAGE_SIZE;

	set_memory_rw(base, pages);

	dst = fncpy(sram, funcp, size);

	set_memory_ro(base, pages);
	set_memory_x(base, pages);

	return dst;
}

/*
 * The SRAM context is lost during off-idle and stack
 * needs to be reset.
 */
static void omap_sram_reset(void)
{
	omap_sram_ceil = omap_sram_base + omap_sram_size;
}

/*
 * Depending on the target RAMFS firewall setup, the public usable amount of
 * SRAM varies.  The default accessible size for all device types is 2k. A GP
 * device allows ARM11 but not other initiators for full size. This
 * functionality seems ok until some nice security API happens.
 */
static int is_sram_locked(void)
{
	if (OMAP2_DEVICE_TYPE_GP == omap_type()) {
		/* RAMFW: R/W access to all initiators for all qualifier sets */
		if (cpu_is_omap242x()) {
			writel_relaxed(0xFF, OMAP24XX_VA_REQINFOPERM0); /* all q-vects */
			writel_relaxed(0xCFDE, OMAP24XX_VA_READPERM0);  /* all i-read */
			writel_relaxed(0xCFDE, OMAP24XX_VA_WRITEPERM0); /* all i-write */
		}
		if (cpu_is_omap34xx()) {
			writel_relaxed(0xFFFF, OMAP34XX_VA_REQINFOPERM0); /* all q-vects */
			writel_relaxed(0xFFFF, OMAP34XX_VA_READPERM0);  /* all i-read */
			writel_relaxed(0xFFFF, OMAP34XX_VA_WRITEPERM0); /* all i-write */
			writel_relaxed(0x0, OMAP34XX_VA_ADDR_MATCH2);
			writel_relaxed(0xFFFFFFFF, OMAP34XX_VA_SMS_RG_ATT0);
		}
		return 0;
	} else
		return 1; /* assume locked with no PPA or security driver */
}

/*
 * The amount of SRAM depends on the core type.
 * Note that we cannot try to test for SRAM here because writes
 * to secure SRAM will hang the system. Also the SRAM is not
 * yet mapped at this point.
 */
static void __init omap_detect_sram(void)
{
	omap_sram_skip = SRAM_BOOTLOADER_SZ;
	if (is_sram_locked()) {
		if (cpu_is_omap34xx()) {
			omap_sram_start = OMAP3_SRAM_PUB_PA;
			if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) ||
			    (omap_type() == OMAP2_DEVICE_TYPE_SEC)) {
				omap_sram_size = 0x7000; /* 28K */
				omap_sram_skip += SZ_16K;
			} else {
				omap_sram_size = 0x8000; /* 32K */
			}
		} else {
			omap_sram_start = OMAP2_SRAM_PUB_PA;
			omap_sram_size = 0x800; /* 2K */
		}
	} else {
		if (cpu_is_omap34xx()) {
			omap_sram_start = OMAP3_SRAM_PA;
			omap_sram_size = 0x10000; /* 64K */
		} else {
			omap_sram_start = OMAP2_SRAM_PA;
			if (cpu_is_omap242x())
				omap_sram_size = 0xa0000; /* 640K */
			else if (cpu_is_omap243x())
				omap_sram_size = 0x10000; /* 64K */
		}
	}
}

/*
 * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
 */
static void __init omap2_map_sram(void)
{
	unsigned long base;
	int pages;
	int cached = 1;

	if (cpu_is_omap34xx()) {
		/*
		 * SRAM must be marked as non-cached on OMAP3 since the
		 * CORE DPLL M2 divider change code (in SRAM) runs with the
		 * SDRAM controller disabled, and if it is marked cached,
		 * the ARM may attempt to write cache lines back to SDRAM
		 * which will cause the system to hang.
		 */
		cached = 0;
	}

	if (omap_sram_size == 0)
		return;

	omap_sram_start = ROUND_DOWN(omap_sram_start, PAGE_SIZE);
	omap_sram_base = __arm_ioremap_exec(omap_sram_start, omap_sram_size, cached);
	if (!omap_sram_base) {
		pr_err("SRAM: Could not map\n");
		return;
	}

	omap_sram_reset();

	/*
	 * Looks like we need to preserve some bootloader code at the
	 * beginning of SRAM for jumping to flash for reboot to work...
	 */
	memset_io(omap_sram_base + omap_sram_skip, 0,
		  omap_sram_size - omap_sram_skip);

	base = (unsigned long)omap_sram_base;
	pages = PAGE_ALIGN(omap_sram_size) / PAGE_SIZE;

	set_memory_ro(base, pages);
	set_memory_x(base, pages);
}

static void (*_omap2_sram_ddr_init)(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
			      u32 base_cs, u32 force_unlock);

void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
		   u32 base_cs, u32 force_unlock)
{
	BUG_ON(!_omap2_sram_ddr_init);
	_omap2_sram_ddr_init(slow_dll_ctrl, fast_dll_ctrl,
			     base_cs, force_unlock);
}

static void (*_omap2_sram_reprogram_sdrc)(u32 perf_level, u32 dll_val,
					  u32 mem_type);

void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type)
{
	BUG_ON(!_omap2_sram_reprogram_sdrc);
	_omap2_sram_reprogram_sdrc(perf_level, dll_val, mem_type);
}

static u32 (*_omap2_set_prcm)(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);

u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass)
{
	BUG_ON(!_omap2_set_prcm);
	return _omap2_set_prcm(dpll_ctrl_val, sdrc_rfr_val, bypass);
}

#ifdef CONFIG_SOC_OMAP2420
static int __init omap242x_sram_init(void)
{
	_omap2_sram_ddr_init = omap_sram_push(omap242x_sram_ddr_init,
					omap242x_sram_ddr_init_sz);

	_omap2_sram_reprogram_sdrc = omap_sram_push(omap242x_sram_reprogram_sdrc,
					    omap242x_sram_reprogram_sdrc_sz);

	_omap2_set_prcm = omap_sram_push(omap242x_sram_set_prcm,
					 omap242x_sram_set_prcm_sz);

	return 0;
}
#else
static inline int omap242x_sram_init(void)
{
	return 0;
}
#endif

#ifdef CONFIG_SOC_OMAP2430
static int __init omap243x_sram_init(void)
{
	_omap2_sram_ddr_init = omap_sram_push(omap243x_sram_ddr_init,
					omap243x_sram_ddr_init_sz);

	_omap2_sram_reprogram_sdrc = omap_sram_push(omap243x_sram_reprogram_sdrc,
					    omap243x_sram_reprogram_sdrc_sz);

	_omap2_set_prcm = omap_sram_push(omap243x_sram_set_prcm,
					 omap243x_sram_set_prcm_sz);

	return 0;
}
#else
static inline int omap243x_sram_init(void)
{
	return 0;
}
#endif

#ifdef CONFIG_ARCH_OMAP3

void omap3_sram_restore_context(void)
{
	omap_sram_reset();

	omap_push_sram_idle();
}

static inline int omap34xx_sram_init(void)
{
	omap3_sram_restore_context();
	return 0;
}
#else
static inline int omap34xx_sram_init(void)
{
	return 0;
}
#endif /* CONFIG_ARCH_OMAP3 */

int __init omap_sram_init(void)
{
	omap_detect_sram();
	omap2_map_sram();

	if (cpu_is_omap242x())
		omap242x_sram_init();
	else if (cpu_is_omap2430())
		omap243x_sram_init();
	else if (cpu_is_omap34xx())
		omap34xx_sram_init();

	return 0;
}


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Interface for functions that need to be run in internal SRAM
 */

#ifndef __ASSEMBLY__

extern void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
				u32 base_cs, u32 force_unlock);
extern void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
				      u32 mem_type);
extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass);

extern void omap3_sram_restore_context(void);

extern int __init omap_sram_init(void);

extern void *omap_sram_push(void *funcp, unsigned long size);

/* Do not use these */
extern void omap24xx_sram_reprogram_clock(u32 ckctl, u32 dpllctl);
extern unsigned long omap24xx_sram_reprogram_clock_sz;

extern void omap242x_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
						u32 base_cs, u32 force_unlock);
extern unsigned long omap242x_sram_ddr_init_sz;

extern u32 omap242x_sram_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val,
						int bypass);
extern unsigned long omap242x_sram_set_prcm_sz;

extern void omap242x_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
						u32 mem_type);
extern unsigned long omap242x_sram_reprogram_sdrc_sz;

extern void omap243x_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
						u32 base_cs, u32 force_unlock);
extern unsigned long omap243x_sram_ddr_init_sz;

extern u32 omap243x_sram_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val,
						int bypass);
extern unsigned long omap243x_sram_set_prcm_sz;

extern void omap243x_sram_reprogram_sdrc(u32 perf_level, u32 dll_val,
						u32 mem_type);
extern unsigned long omap243x_sram_reprogram_sdrc_sz;

#ifdef CONFIG_PM
extern void omap_push_sram_idle(void);
#else
static inline void omap_push_sram_idle(void) {}
#endif /* CONFIG_PM */

#endif /* __ASSEMBLY__ */

/*
 * OMAP2+: define the SRAM PA addresses.
 * Used by the SRAM management code and the idle sleep code.
 */
#define OMAP2_SRAM_PA		0x40200000
#define OMAP3_SRAM_PA           0x40200000


code:
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * linux/arch/arm/mach-omap2/sram242x.S
 *
 * Omap2 specific functions that need to be run in internal SRAM
 *
 * (C) Copyright 2004
 * Texas Instruments, <www.ti.com>
 * Richard Woodruff <r-woodruff2@ti.com>
 *
 * Richard Woodruff notes that any changes to this code must be carefully
 * audited and tested to ensure that they don't cause a TLB miss while
 * the SDRAM is inaccessible.  Such a situation will crash the system
 * since it will cause the ARM MMU to attempt to walk the page tables.
 * These crashes may be intermittent.
 */
#include <linux/linkage.h>

#include <asm/assembler.h>

#include "soc.h"
#include "iomap.h"
#include "prm2xxx.h"
#include "cm2xxx.h"
#include "sdrc.h"

	.text

	.align	3
ENTRY(omap242x_sram_ddr_init)
	stmfd	sp!, {r0 - r12, lr}	@ save registers on stack

	mov	r12, r2			@ capture CS1 vs CS0
	mov	r8, r3			@ capture force parameter

	/* frequency shift down */
	ldr	r2, omap242x_sdi_cm_clksel2_pll	@ get address of dpllout reg
	mov	r3, #0x1		@ value for 1x operation
	str	r3, [r2]		@ go to L1-freq operation

	/* voltage shift down */
	mov r9, #0x1			@ set up for L1 voltage call
	bl voltage_shift		@ go drop voltage

	/* dll lock mode */
	ldr	r11, omap242x_sdi_sdrc_dlla_ctrl	@ addr of dlla ctrl
	ldr	r10, [r11]		@ get current val
	cmp	r12, #0x1		@ cs1 base (2422 es2.05/1)
	addeq	r11, r11, #0x8		@ if cs1 base, move to DLLB
	mvn	r9, #0x4		@ mask to get clear bit2
	and	r10, r10, r9		@ clear bit2 for lock mode.
	orr	r10, r10, #0x8		@ make sure DLL on (es2 bit pos)
	orr	r10, r10, #0x2		@ 90 degree phase for all below 133MHz
	str	r10, [r11]		@ commit to DLLA_CTRL
	bl	i_dll_wait		@ wait for dll to lock

	/* get dll value */
	add	r11, r11, #0x4		@ get addr of status reg
	ldr	r10, [r11]		@ get locked value

	/* voltage shift up */
	mov r9, #0x0			@ shift back to L0-voltage
	bl voltage_shift		@ go raise voltage

	/* frequency shift up */
	mov	r3, #0x2		@ value for 2x operation
	str	r3, [r2]		@ go to L0-freq operation

	/* reset entry mode for dllctrl */
	sub	r11, r11, #0x4		@ move from status to ctrl
	cmp	r12, #0x1		@ normalize if cs1 based
	subeq	r11, r11, #0x8		@ possibly back to DLLA
	cmp	r8, #0x1		@ if forced unlock exit
	orreq	r1, r1, #0x4		@ make sure exit with unlocked value
	str	r1, [r11]		@ restore DLLA_CTRL high value
	add	r11, r11, #0x8		@ move to DLLB_CTRL addr
	str	r1, [r11]		@ set value DLLB_CTRL
	bl	i_dll_wait		@ wait for possible lock

	/* set up for return, DDR should be good */
	str r10, [r0]			@ write dll_status and return counter
	ldmfd	sp!, {r0 - r12, pc}	@ restore regs and return

	/* ensure the DLL has relocked */
i_dll_wait:
	mov	r4, #0x800		@ delay DLL relock, min 0x400 L3 clocks
i_dll_delay:
	subs	r4, r4, #0x1
	bne	i_dll_delay
	ret	lr

	/*
	 * shift up or down voltage, use R9 as input to tell level.
	 * wait for it to finish, use 32k sync counter, 1tick=31uS.
	 */
voltage_shift:
	ldr	r4, omap242x_sdi_prcm_voltctrl	@ get addr of volt ctrl.
	ldr	r5, [r4]		@ get value.
	ldr	r6, prcm_mask_val	@ get value of mask
	and	r5, r5, r6		@ apply mask to clear bits
	orr	r5, r5, r9		@ bulld value for L0/L1-volt operation.
	str	r5, [r4]		@ set up for change.
	mov	r3, #0x4000		@ get val for force
	orr	r5, r5, r3		@ build value for force
	str	r5, [r4]		@ Force transition to L1

	ldr	r3, omap242x_sdi_timer_32ksynct_cr	@ get addr of counter
	ldr	r5, [r3]		@ get value
	add	r5, r5, #0x3		@ give it at most 93uS
volt_delay:
	ldr	r7, [r3]		@ get timer value
	cmp	r5, r7			@ time up?
	bhi	volt_delay		@ not yet->branch
	ret	lr			@ back to caller.

omap242x_sdi_cm_clksel2_pll:
	.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
omap242x_sdi_sdrc_dlla_ctrl:
	.word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
omap242x_sdi_prcm_voltctrl:
	.word OMAP2420_PRCM_VOLTCTRL
prcm_mask_val:
	.word 0xFFFF3FFC
omap242x_sdi_timer_32ksynct_cr:
	.word OMAP2_L4_IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010)
ENTRY(omap242x_sram_ddr_init_sz)
	.word	. - omap242x_sram_ddr_init

/*
 * Reprograms memory timings.
 * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
 * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
 */
	.align	3
ENTRY(omap242x_sram_reprogram_sdrc)
	stmfd	sp!, {r0 - r10, lr}	@ save registers on stack
	mov	r3, #0x0		@ clear for mrc call
	mcr	p15, 0, r3, c7, c10, 4	@ memory barrier, finish ARM SDR/DDR
	nop
	nop
	ldr	r6, omap242x_srs_sdrc_rfr_ctrl	@ get addr of refresh reg
	ldr	r5, [r6]		@ get value
	mov	r5, r5, lsr #8		@ isolate rfr field and drop burst

	cmp	r0, #0x1		@ going to half speed?
	movne	r9, #0x0		@ if up set flag up for pre up, hi volt

	blne	voltage_shift_c		@ adjust voltage

	cmp	r0, #0x1		@ going to half speed (post branch link)
	moveq	r5, r5, lsr #1		@ divide by 2 if to half
	movne	r5, r5, lsl #1		@ mult by 2 if to full
	mov	r5, r5, lsl #8		@ put rfr field back into place
	add	r5, r5, #0x1		@ turn on burst of 1
	ldr	r4, omap242x_srs_cm_clksel2_pll	@ get address of out reg
	ldr	r3, [r4]		@ get curr value
	orr	r3, r3, #0x3
	bic	r3, r3, #0x3		@ clear lower bits
	orr	r3, r3, r0		@ new state value
	str	r3, [r4]		@ set new state (pll/x, x=1 or 2)
	nop
	nop

	moveq	r9, #0x1		@ if speed down, post down, drop volt
	bleq	voltage_shift_c

	mcr	p15, 0, r3, c7, c10, 4	@ memory barrier
	str	r5, [r6]		@ set new RFR_1 value
	add	r6, r6, #0x30		@ get RFR_2 addr
	str	r5, [r6]		@ set RFR_2
	nop
	cmp	r2, #0x1		@ (SDR or DDR) do we need to adjust DLL
	bne	freq_out		@ leave if SDR, no DLL function

	/* With DDR, we need to take care of the DLL for the frequency change */
	ldr	r2, omap242x_srs_sdrc_dlla_ctrl	@ addr of dlla ctrl
	str	r1, [r2]		@ write out new SDRC_DLLA_CTRL
	add	r2, r2, #0x8		@ addr to SDRC_DLLB_CTRL
	str	r1, [r2]		@ commit to SDRC_DLLB_CTRL
	mov	r1, #0x2000		@ wait DLL relock, min 0x400 L3 clocks
dll_wait:
	subs	r1, r1, #0x1
	bne	dll_wait
freq_out:
	ldmfd	sp!, {r0 - r10, pc}	@ restore regs and return

    /*
     * shift up or down voltage, use R9 as input to tell level.
     *	wait for it to finish, use 32k sync counter, 1tick=31uS.
     */
voltage_shift_c:
	ldr	r10, omap242x_srs_prcm_voltctrl	@ get addr of volt ctrl
	ldr	r8, [r10]		@ get value
	ldr	r7, ddr_prcm_mask_val	@ get value of mask
	and	r8, r8, r7		@ apply mask to clear bits
	orr	r8, r8, r9		@ bulld value for L0/L1-volt operation.
	str	r8, [r10]		@ set up for change.
	mov	r7, #0x4000		@ get val for force
	orr	r8, r8, r7		@ build value for force
	str	r8, [r10]		@ Force transition to L1

	ldr	r10, omap242x_srs_timer_32ksynct	@ get addr of counter
	ldr	r8, [r10]		@ get value
	add	r8, r8, #0x2		@ give it at most 62uS (min 31+)
volt_delay_c:
	ldr	r7, [r10]		@ get timer value
	cmp	r8, r7			@ time up?
	bhi	volt_delay_c		@ not yet->branch
	ret	lr			@ back to caller

omap242x_srs_cm_clksel2_pll:
	.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
omap242x_srs_sdrc_dlla_ctrl:
	.word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
omap242x_srs_sdrc_rfr_ctrl:
	.word OMAP242X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
omap242x_srs_prcm_voltctrl:
	.word OMAP2420_PRCM_VOLTCTRL
ddr_prcm_mask_val:
	.word 0xFFFF3FFC
omap242x_srs_timer_32ksynct:
	.word OMAP2_L4_IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010)

ENTRY(omap242x_sram_reprogram_sdrc_sz)
	.word	. - omap242x_sram_reprogram_sdrc

/*
 * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
 */
	.align	3
ENTRY(omap242x_sram_set_prcm)
	stmfd	sp!, {r0-r12, lr}	@ regs to stack
	adr	r4, pbegin		@ addr of preload start
	adr	r8, pend		@ addr of preload end
	mcrr	p15, 1, r8, r4, c12	@ preload into icache
pbegin:
	/* move into fast relock bypass */
	ldr	r8, omap242x_ssp_pll_ctl	@ get addr
	ldr	r5, [r8]		@ get val
	mvn	r6, #0x3		@ clear mask
	and	r5, r5, r6		@ clear field
	orr	r7, r5, #0x2		@ fast relock val
	str	r7, [r8]		@ go to fast relock
	ldr	r4, omap242x_ssp_pll_stat	@ addr of stat
block:
	/* wait for bypass */
	ldr	r8, [r4]		@ stat value
	and	r8, r8, #0x3		@ mask for stat
	cmp	r8, #0x1		@ there yet
	bne	block			@ loop if not

	/* set new dpll dividers _after_ in bypass */
	ldr	r4, omap242x_ssp_pll_div	@ get addr
	str	r0, [r4]		@ set dpll ctrl val

	ldr	r4, omap242x_ssp_set_config	@ get addr
	mov	r8, #1			@ valid cfg msk
	str	r8, [r4]		@ make dividers take

	mov	r4, #100		@ dead spin a bit
wait_a_bit:
	subs	r4, r4, #1		@ dec loop
	bne	wait_a_bit		@ delay done?

	/* check if staying in bypass */
	cmp	r2, #0x1		@ stay in bypass?
	beq	pend			@ jump over dpll relock

	/* relock DPLL with new vals */
	ldr	r5, omap242x_ssp_pll_stat	@ get addr
	ldr	r4, omap242x_ssp_pll_ctl	@ get addr
	orr	r8, r7, #0x3		@ val for lock dpll
	str	r8, [r4]		@ set val
	mov	r0, #1000		@ dead spin a bit
wait_more:
	subs	r0, r0, #1		@ dec loop
	bne	wait_more		@ delay done?
wait_lock:
	ldr	r8, [r5]		@ get lock val
	and	r8, r8, #3		@ isolate field
	cmp	r8, #2			@ locked?
	bne	wait_lock		@ wait if not
pend:
	/* update memory timings & briefly lock dll */
	ldr	r4, omap242x_ssp_sdrc_rfr	@ get addr
	str	r1, [r4]		@ update refresh timing
	ldr	r11, omap242x_ssp_dlla_ctrl	@ get addr of DLLA ctrl
	ldr	r10, [r11]		@ get current val
	mvn	r9, #0x4		@ mask to get clear bit2
	and	r10, r10, r9		@ clear bit2 for lock mode
	orr	r10, r10, #0x8		@ make sure DLL on (es2 bit pos)
	str	r10, [r11]		@ commit to DLLA_CTRL
	add	r11, r11, #0x8		@ move to dllb
	str	r10, [r11]		@ hit DLLB also

	mov	r4, #0x800		@ relock time (min 0x400 L3 clocks)
wait_dll_lock:
	subs	r4, r4, #0x1
	bne	wait_dll_lock
	nop
	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return

omap242x_ssp_set_config:
	.word OMAP2420_PRCM_CLKCFG_CTRL
omap242x_ssp_pll_ctl:
	.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKEN)
omap242x_ssp_pll_stat:
	.word OMAP2420_CM_REGADDR(PLL_MOD, CM_IDLEST)
omap242x_ssp_pll_div:
	.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL1)
omap242x_ssp_sdrc_rfr:
	.word OMAP242X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
omap242x_ssp_dlla_ctrl:
	.word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)

ENTRY(omap242x_sram_set_prcm_sz)
	.word	. - omap242x_sram_set_prcm


code:
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * linux/arch/arm/mach-omap2/sram243x.S
 *
 * Omap2 specific functions that need to be run in internal SRAM
 *
 * (C) Copyright 2004
 * Texas Instruments, <www.ti.com>
 * Richard Woodruff <r-woodruff2@ti.com>
 *
 * Richard Woodruff notes that any changes to this code must be carefully
 * audited and tested to ensure that they don't cause a TLB miss while
 * the SDRAM is inaccessible.  Such a situation will crash the system
 * since it will cause the ARM MMU to attempt to walk the page tables.
 * These crashes may be intermittent.
 */
#include <linux/linkage.h>

#include <asm/assembler.h>

#include "soc.h"
#include "iomap.h"
#include "prm2xxx.h"
#include "cm2xxx.h"
#include "sdrc.h"

	.text

	.align	3
ENTRY(omap243x_sram_ddr_init)
	stmfd	sp!, {r0 - r12, lr}	@ save registers on stack

	mov	r12, r2			@ capture CS1 vs CS0
	mov	r8, r3			@ capture force parameter

	/* frequency shift down */
	ldr	r2, omap243x_sdi_cm_clksel2_pll	@ get address of dpllout reg
	mov	r3, #0x1		@ value for 1x operation
	str	r3, [r2]		@ go to L1-freq operation

	/* voltage shift down */
	mov r9, #0x1			@ set up for L1 voltage call
	bl voltage_shift		@ go drop voltage

	/* dll lock mode */
	ldr	r11, omap243x_sdi_sdrc_dlla_ctrl	@ addr of dlla ctrl
	ldr	r10, [r11]		@ get current val
	cmp	r12, #0x1		@ cs1 base (2422 es2.05/1)
	addeq	r11, r11, #0x8		@ if cs1 base, move to DLLB
	mvn	r9, #0x4		@ mask to get clear bit2
	and	r10, r10, r9		@ clear bit2 for lock mode.
	orr	r10, r10, #0x8		@ make sure DLL on (es2 bit pos)
	orr	r10, r10, #0x2		@ 90 degree phase for all below 133MHz
	str	r10, [r11]		@ commit to DLLA_CTRL
	bl	i_dll_wait		@ wait for dll to lock

	/* get dll value */
	add	r11, r11, #0x4		@ get addr of status reg
	ldr	r10, [r11]		@ get locked value

	/* voltage shift up */
	mov r9, #0x0			@ shift back to L0-voltage
	bl voltage_shift		@ go raise voltage

	/* frequency shift up */
	mov	r3, #0x2		@ value for 2x operation
	str	r3, [r2]		@ go to L0-freq operation

	/* reset entry mode for dllctrl */
	sub	r11, r11, #0x4		@ move from status to ctrl
	cmp	r12, #0x1		@ normalize if cs1 based
	subeq	r11, r11, #0x8		@ possibly back to DLLA
	cmp	r8, #0x1		@ if forced unlock exit
	orreq	r1, r1, #0x4		@ make sure exit with unlocked value
	str	r1, [r11]		@ restore DLLA_CTRL high value
	add	r11, r11, #0x8		@ move to DLLB_CTRL addr
	str	r1, [r11]		@ set value DLLB_CTRL
	bl	i_dll_wait		@ wait for possible lock

	/* set up for return, DDR should be good */
	str r10, [r0]			@ write dll_status and return counter
	ldmfd	sp!, {r0 - r12, pc}	@ restore regs and return

	/* ensure the DLL has relocked */
i_dll_wait:
	mov	r4, #0x800		@ delay DLL relock, min 0x400 L3 clocks
i_dll_delay:
	subs	r4, r4, #0x1
	bne	i_dll_delay
	ret	lr

	/*
	 * shift up or down voltage, use R9 as input to tell level.
	 * wait for it to finish, use 32k sync counter, 1tick=31uS.
	 */
voltage_shift:
	ldr	r4, omap243x_sdi_prcm_voltctrl	@ get addr of volt ctrl.
	ldr	r5, [r4]		@ get value.
	ldr	r6, prcm_mask_val	@ get value of mask
	and	r5, r5, r6		@ apply mask to clear bits
	orr	r5, r5, r9		@ bulld value for L0/L1-volt operation.
	str	r5, [r4]		@ set up for change.
	mov	r3, #0x4000		@ get val for force
	orr	r5, r5, r3		@ build value for force
	str	r5, [r4]		@ Force transition to L1

	ldr	r3, omap243x_sdi_timer_32ksynct_cr	@ get addr of counter
	ldr	r5, [r3]		@ get value
	add	r5, r5, #0x3		@ give it at most 93uS
volt_delay:
	ldr	r7, [r3]		@ get timer value
	cmp	r5, r7			@ time up?
	bhi	volt_delay		@ not yet->branch
	ret	lr			@ back to caller.

omap243x_sdi_cm_clksel2_pll:
	.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
omap243x_sdi_sdrc_dlla_ctrl:
	.word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)
omap243x_sdi_prcm_voltctrl:
	.word OMAP2430_PRCM_VOLTCTRL
prcm_mask_val:
	.word 0xFFFF3FFC
omap243x_sdi_timer_32ksynct_cr:
	.word OMAP2_L4_IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010)
ENTRY(omap243x_sram_ddr_init_sz)
	.word	. - omap243x_sram_ddr_init

/*
 * Reprograms memory timings.
 * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
 * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
 */
	.align	3
ENTRY(omap243x_sram_reprogram_sdrc)
	stmfd	sp!, {r0 - r10, lr}	@ save registers on stack
	mov	r3, #0x0		@ clear for mrc call
	mcr	p15, 0, r3, c7, c10, 4	@ memory barrier, finish ARM SDR/DDR
	nop
	nop
	ldr	r6, omap243x_srs_sdrc_rfr_ctrl	@ get addr of refresh reg
	ldr	r5, [r6]		@ get value
	mov	r5, r5, lsr #8		@ isolate rfr field and drop burst

	cmp	r0, #0x1		@ going to half speed?
	movne	r9, #0x0		@ if up set flag up for pre up, hi volt

	blne	voltage_shift_c		@ adjust voltage

	cmp	r0, #0x1		@ going to half speed (post branch link)
	moveq	r5, r5, lsr #1		@ divide by 2 if to half
	movne	r5, r5, lsl #1		@ mult by 2 if to full
	mov	r5, r5, lsl #8		@ put rfr field back into place
	add	r5, r5, #0x1		@ turn on burst of 1
	ldr	r4, omap243x_srs_cm_clksel2_pll	@ get address of out reg
	ldr	r3, [r4]		@ get curr value
	orr	r3, r3, #0x3
	bic	r3, r3, #0x3		@ clear lower bits
	orr	r3, r3, r0		@ new state value
	str	r3, [r4]		@ set new state (pll/x, x=1 or 2)
	nop
	nop

	moveq	r9, #0x1		@ if speed down, post down, drop volt
	bleq	voltage_shift_c

	mcr	p15, 0, r3, c7, c10, 4	@ memory barrier
	str	r5, [r6]		@ set new RFR_1 value
	add	r6, r6, #0x30		@ get RFR_2 addr
	str	r5, [r6]		@ set RFR_2
	nop
	cmp	r2, #0x1		@ (SDR or DDR) do we need to adjust DLL
	bne	freq_out		@ leave if SDR, no DLL function

	/* With DDR, we need to take care of the DLL for the frequency change */
	ldr	r2, omap243x_srs_sdrc_dlla_ctrl	@ addr of dlla ctrl
	str	r1, [r2]		@ write out new SDRC_DLLA_CTRL
	add	r2, r2, #0x8		@ addr to SDRC_DLLB_CTRL
	str	r1, [r2]		@ commit to SDRC_DLLB_CTRL
	mov	r1, #0x2000		@ wait DLL relock, min 0x400 L3 clocks
dll_wait:
	subs	r1, r1, #0x1
	bne	dll_wait
freq_out:
	ldmfd	sp!, {r0 - r10, pc}	@ restore regs and return

    /*
     * shift up or down voltage, use R9 as input to tell level.
     *	wait for it to finish, use 32k sync counter, 1tick=31uS.
     */
voltage_shift_c:
	ldr	r10, omap243x_srs_prcm_voltctrl	@ get addr of volt ctrl
	ldr	r8, [r10]		@ get value
	ldr	r7, ddr_prcm_mask_val	@ get value of mask
	and	r8, r8, r7		@ apply mask to clear bits
	orr	r8, r8, r9		@ bulld value for L0/L1-volt operation.
	str	r8, [r10]		@ set up for change.
	mov	r7, #0x4000		@ get val for force
	orr	r8, r8, r7		@ build value for force
	str	r8, [r10]		@ Force transition to L1

	ldr	r10, omap243x_srs_timer_32ksynct	@ get addr of counter
	ldr	r8, [r10]		@ get value
	add	r8, r8, #0x2		@ give it at most 62uS (min 31+)
volt_delay_c:
	ldr	r7, [r10]		@ get timer value
	cmp	r8, r7			@ time up?
	bhi	volt_delay_c		@ not yet->branch
	ret	lr			@ back to caller

omap243x_srs_cm_clksel2_pll:
	.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
omap243x_srs_sdrc_dlla_ctrl:
	.word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)
omap243x_srs_sdrc_rfr_ctrl:
	.word OMAP243X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
omap243x_srs_prcm_voltctrl:
	.word OMAP2430_PRCM_VOLTCTRL
ddr_prcm_mask_val:
	.word 0xFFFF3FFC
omap243x_srs_timer_32ksynct:
	.word OMAP2_L4_IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010)

ENTRY(omap243x_sram_reprogram_sdrc_sz)
	.word	. - omap243x_sram_reprogram_sdrc

/*
 * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
 */
	.align	3
ENTRY(omap243x_sram_set_prcm)
	stmfd	sp!, {r0-r12, lr}	@ regs to stack
	adr	r4, pbegin		@ addr of preload start
	adr	r8, pend		@ addr of preload end
	mcrr	p15, 1, r8, r4, c12	@ preload into icache
pbegin:
	/* move into fast relock bypass */
	ldr	r8, omap243x_ssp_pll_ctl	@ get addr
	ldr	r5, [r8]		@ get val
	mvn	r6, #0x3		@ clear mask
	and	r5, r5, r6		@ clear field
	orr	r7, r5, #0x2		@ fast relock val
	str	r7, [r8]		@ go to fast relock
	ldr	r4, omap243x_ssp_pll_stat	@ addr of stat
block:
	/* wait for bypass */
	ldr	r8, [r4]		@ stat value
	and	r8, r8, #0x3		@ mask for stat
	cmp	r8, #0x1		@ there yet
	bne	block			@ loop if not

	/* set new dpll dividers _after_ in bypass */
	ldr	r4, omap243x_ssp_pll_div	@ get addr
	str	r0, [r4]		@ set dpll ctrl val

	ldr	r4, omap243x_ssp_set_config	@ get addr
	mov	r8, #1			@ valid cfg msk
	str	r8, [r4]		@ make dividers take

	mov	r4, #100		@ dead spin a bit
wait_a_bit:
	subs	r4, r4, #1		@ dec loop
	bne	wait_a_bit		@ delay done?

	/* check if staying in bypass */
	cmp	r2, #0x1		@ stay in bypass?
	beq	pend			@ jump over dpll relock

	/* relock DPLL with new vals */
	ldr	r5, omap243x_ssp_pll_stat	@ get addr
	ldr	r4, omap243x_ssp_pll_ctl	@ get addr
	orr	r8, r7, #0x3		@ val for lock dpll
	str	r8, [r4]		@ set val
	mov	r0, #1000		@ dead spin a bit
wait_more:
	subs	r0, r0, #1		@ dec loop
	bne	wait_more		@ delay done?
wait_lock:
	ldr	r8, [r5]		@ get lock val
	and	r8, r8, #3		@ isolate field
	cmp	r8, #2			@ locked?
	bne	wait_lock		@ wait if not
pend:
	/* update memory timings & briefly lock dll */
	ldr	r4, omap243x_ssp_sdrc_rfr	@ get addr
	str	r1, [r4]		@ update refresh timing
	ldr	r11, omap243x_ssp_dlla_ctrl	@ get addr of DLLA ctrl
	ldr	r10, [r11]		@ get current val
	mvn	r9, #0x4		@ mask to get clear bit2
	and	r10, r10, r9		@ clear bit2 for lock mode
	orr	r10, r10, #0x8		@ make sure DLL on (es2 bit pos)
	str	r10, [r11]		@ commit to DLLA_CTRL
	add	r11, r11, #0x8		@ move to dllb
	str	r10, [r11]		@ hit DLLB also

	mov	r4, #0x800		@ relock time (min 0x400 L3 clocks)
wait_dll_lock:
	subs	r4, r4, #0x1
	bne	wait_dll_lock
	nop
	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return

omap243x_ssp_set_config:
	.word OMAP2430_PRCM_CLKCFG_CTRL
omap243x_ssp_pll_ctl:
	.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKEN)
omap243x_ssp_pll_stat:
	.word OMAP2430_CM_REGADDR(PLL_MOD, CM_IDLEST)
omap243x_ssp_pll_div:
	.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL1)
omap243x_ssp_sdrc_rfr:
	.word OMAP243X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
omap243x_ssp_dlla_ctrl:
	.word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)

ENTRY(omap243x_sram_set_prcm_sz)
	.word	. - omap243x_sram_set_prcm


code:
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/reboot.h>

#include "iomap.h"
#include "common.h"
#include "control.h"
#include "prm3xxx.h"

#define TI81XX_PRM_DEVICE_RSTCTRL	0x00a0
#define TI81XX_GLOBAL_RST_COLD		BIT(1)

/**
 * ti81xx_restart - trigger a software restart of the SoC
 * @mode: the "reboot mode", see arch/arm/kernel/{setup,process}.c
 * @cmd: passed from the userspace program rebooting the system (if provided)
 *
 * Resets the SoC.  For @cmd, see the 'reboot' syscall in
 * kernel/sys.c.  No return value.
 *
 * NOTE: Warm reset does not seem to work, may require resetting
 * clocks to bypass mode.
 */
void ti81xx_restart(enum reboot_mode mode, const char *cmd)
{
	omap2_prm_set_mod_reg_bits(TI81XX_GLOBAL_RST_COLD, 0,
				   TI81XX_PRM_DEVICE_RSTCTRL);
	while (1);
}


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * This file contains the address data for various TI81XX modules.
 *
 * Copyright (C) 2010 Texas Instruments, Inc. - https://www.ti.com/
 */

#ifndef __ASM_ARCH_TI81XX_H
#define __ASM_ARCH_TI81XX_H

#define L4_SLOW_TI81XX_BASE	0x48000000

#define TI81XX_SCM_BASE		0x48140000
#define TI81XX_CTRL_BASE	TI81XX_SCM_BASE
#define TI81XX_PRCM_BASE	0x48180000

/*
 * Adjust TAP register base such that omap3_check_revision accesses the correct
 * TI81XX register for checking device ID (it adds 0x204 to tap base while
 * TI81XX DEVICE ID register is at offset 0x600 from control base).
 */
#define TI81XX_TAP_BASE		(TI81XX_CTRL_BASE + \
				 TI81XX_CONTROL_DEVICE_ID - 0x204)

#define TI81XX_ARM_INTC_BASE	0x48200000

#endif /* __ASM_ARCH_TI81XX_H */


code:
/*
 * linux/arch/arm/mach-omap2/timer.c
 *
 * OMAP2 GP timer support.
 *
 * Copyright (C) 2009 Nokia Corporation
 *
 * Update to use new clocksource/clockevent layers
 * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
 * Copyright (C) 2007 MontaVista Software, Inc.
 *
 * Original driver:
 * Copyright (C) 2005 Nokia Corporation
 * Author: Paul Mundt <paul.mundt@nokia.com>
 *         Juha Yrjölä <juha.yrjola@nokia.com>
 * OMAP Dual-mode timer framework support by Timo Teras
 *
 * Some parts based off of TI's 24xx code:
 *
 * Copyright (C) 2004-2009 Texas Instruments, Inc.
 *
 * Roughly modelled after the OMAP1 MPU timer code.
 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License. See the file "COPYING" in the main directory of this archive
 * for more details.
 */
#include <linux/clk.h>
#include <linux/clocksource.h>

#include "soc.h"
#include "common.h"
#include "control.h"
#include "omap-secure.h"

#define REALTIME_COUNTER_BASE				0x48243200
#define INCREMENTER_NUMERATOR_OFFSET			0x10
#define INCREMENTER_DENUMERATOR_RELOAD_OFFSET		0x14
#define NUMERATOR_DENUMERATOR_MASK			0xfffff000

static unsigned long arch_timer_freq;

void set_cntfreq(void)
{
	omap_smc1(OMAP5_DRA7_MON_SET_CNTFRQ_INDEX, arch_timer_freq);
}

/*
 * The realtime counter also called master counter, is a free-running
 * counter, which is related to real time. It produces the count used
 * by the CPU local timer peripherals in the MPU cluster. The timer counts
 * at a rate of 6.144 MHz. Because the device operates on different clocks
 * in different power modes, the master counter shifts operation between
 * clocks, adjusting the increment per clock in hardware accordingly to
 * maintain a constant count rate.
 */
static void __init realtime_counter_init(void)
{
	void __iomem *base;
	static struct clk *sys_clk;
	unsigned long rate;
	unsigned int reg;
	unsigned long long num, den;

	base = ioremap(REALTIME_COUNTER_BASE, SZ_32);
	if (!base) {
		pr_err("%s: ioremap failed\n", __func__);
		return;
	}
	sys_clk = clk_get(NULL, "sys_clkin");
	if (IS_ERR(sys_clk)) {
		pr_err("%s: failed to get system clock handle\n", __func__);
		iounmap(base);
		return;
	}

	rate = clk_get_rate(sys_clk);

	if (soc_is_dra7xx()) {
		/*
		 * Errata i856 says the 32.768KHz crystal does not start at
		 * power on, so the CPU falls back to an emulated 32KHz clock
		 * based on sysclk / 610 instead. This causes the master counter
		 * frequency to not be 6.144MHz but at sysclk / 610 * 375 / 2
		 * (OR sysclk * 75 / 244)
		 *
		 * This affects at least the DRA7/AM572x 1.0, 1.1 revisions.
		 * Of course any board built without a populated 32.768KHz
		 * crystal would also need this fix even if the CPU is fixed
		 * later.
		 *
		 * Either case can be detected by using the two speedselect bits
		 * If they are not 0, then the 32.768KHz clock driving the
		 * coarse counter that corrects the fine counter every time it
		 * ticks is actually rate/610 rather than 32.768KHz and we
		 * should compensate to avoid the 570ppm (at 20MHz, much worse
		 * at other rates) too fast system time.
		 */
		reg = omap_ctrl_readl(DRA7_CTRL_CORE_BOOTSTRAP);
		if (reg & DRA7_SPEEDSELECT_MASK) {
			num = 75;
			den = 244;
			goto sysclk1_based;
		}
	}

	/* Numerator/denumerator values refer TRM Realtime Counter section */
	switch (rate) {
	case 12000000:
		num = 64;
		den = 125;
		break;
	case 13000000:
		num = 768;
		den = 1625;
		break;
	case 19200000:
		num = 8;
		den = 25;
		break;
	case 20000000:
		num = 192;
		den = 625;
		break;
	case 26000000:
		num = 384;
		den = 1625;
		break;
	case 27000000:
		num = 256;
		den = 1125;
		break;
	case 38400000:
	default:
		/* Program it for 38.4 MHz */
		num = 4;
		den = 25;
		break;
	}

sysclk1_based:
	/* Program numerator and denumerator registers */
	reg = readl_relaxed(base + INCREMENTER_NUMERATOR_OFFSET) &
			NUMERATOR_DENUMERATOR_MASK;
	reg |= num;
	writel_relaxed(reg, base + INCREMENTER_NUMERATOR_OFFSET);

	reg = readl_relaxed(base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET) &
			NUMERATOR_DENUMERATOR_MASK;
	reg |= den;
	writel_relaxed(reg, base + INCREMENTER_DENUMERATOR_RELOAD_OFFSET);

	arch_timer_freq = DIV_ROUND_UP_ULL(rate * num, den);
	set_cntfreq();

	iounmap(base);
}

void __init omap5_realtime_timer_init(void)
{
	omap_clk_init();
	realtime_counter_init();

	timer_probe();
}


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/arch/arm/mach-omap2/usb-tusb6010.c
 *
 * Copyright (C) 2006 Nokia Corporation
 */

#include <linux/err.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/export.h>
#include <linux/platform_data/usb-omap.h>

#include <linux/usb/musb.h>

#include "gpmc.h"

static u8		async_cs, sync_cs;
static unsigned		refclk_psec;

static struct gpmc_settings tusb_async = {
	.wait_on_read	= true,
	.wait_on_write	= true,
	.device_width	= GPMC_DEVWIDTH_16BIT,
	.mux_add_data	= GPMC_MUX_AD,
};

static struct gpmc_settings tusb_sync = {
	.burst_read	= true,
	.burst_write	= true,
	.sync_read	= true,
	.sync_write	= true,
	.wait_on_read	= true,
	.wait_on_write	= true,
	.burst_len	= GPMC_BURST_16,
	.device_width	= GPMC_DEVWIDTH_16BIT,
	.mux_add_data	= GPMC_MUX_AD,
};

/* NOTE:  timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */

static int tusb_set_async_mode(unsigned sysclk_ps)
{
	struct gpmc_device_timings dev_t;
	struct gpmc_timings	t;
	unsigned		t_acsnh_advnh = sysclk_ps + 3000;

	memset(&dev_t, 0, sizeof(dev_t));

	dev_t.t_ceasu = 8 * 1000;
	dev_t.t_avdasu = t_acsnh_advnh - 7000;
	dev_t.t_ce_avd = 1000;
	dev_t.t_avdp_r = t_acsnh_advnh;
	dev_t.t_oeasu = t_acsnh_advnh + 1000;
	dev_t.t_oe = 300;
	dev_t.t_cez_r = 7000;
	dev_t.t_cez_w = dev_t.t_cez_r;
	dev_t.t_avdp_w = t_acsnh_advnh;
	dev_t.t_weasu = t_acsnh_advnh + 1000;
	dev_t.t_wpl = 300;
	dev_t.cyc_aavdh_we = 1;

	gpmc_calc_timings(&t, &tusb_async, &dev_t);

	return gpmc_cs_set_timings(async_cs, &t, &tusb_async);
}

static int tusb_set_sync_mode(unsigned sysclk_ps)
{
	struct gpmc_device_timings dev_t;
	struct gpmc_timings	t;
	unsigned		t_scsnh_advnh = sysclk_ps + 3000;

	memset(&dev_t, 0, sizeof(dev_t));

	dev_t.clk = 11100;
	dev_t.t_bacc = 1000;
	dev_t.t_ces = 1000;
	dev_t.t_ceasu = 8 * 1000;
	dev_t.t_avdasu = t_scsnh_advnh - 7000;
	dev_t.t_ce_avd = 1000;
	dev_t.t_avdp_r = t_scsnh_advnh;
	dev_t.cyc_aavdh_oe = 3;
	dev_t.cyc_oe = 5;
	dev_t.t_ce_rdyz = 7000;
	dev_t.t_avdp_w = t_scsnh_advnh;
	dev_t.cyc_aavdh_we = 3;
	dev_t.cyc_wpl = 6;

	gpmc_calc_timings(&t, &tusb_sync, &dev_t);

	return gpmc_cs_set_timings(sync_cs, &t, &tusb_sync);
}

/* tusb driver calls this when it changes the chip's clocking */
int tusb6010_platform_retime(unsigned is_refclk)
{
	static const char	error[] =
		KERN_ERR "tusb6010 %s retime error %d\n";

	unsigned	sysclk_ps;
	int		status;

	if (!refclk_psec)
		return -ENODEV;

	sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;

	status = tusb_set_async_mode(sysclk_ps);
	if (status < 0) {
		printk(error, "async", status);
		goto done;
	}
	status = tusb_set_sync_mode(sysclk_ps);
	if (status < 0)
		printk(error, "sync", status);
done:
	return status;
}
EXPORT_SYMBOL_GPL(tusb6010_platform_retime);

static struct resource tusb_resources[] = {
	/* Order is significant!  The start/end fields
	 * are updated during setup..
	 */
	{ /* Asynchronous access */
		.flags	= IORESOURCE_MEM,
	},
	{ /* Synchronous access */
		.flags	= IORESOURCE_MEM,
	},
	{ /* IRQ */
		.name	= "mc",
		.flags	= IORESOURCE_IRQ,
	},
};

static u64 tusb_dmamask = ~(u32)0;

static struct platform_device tusb_device = {
	.name		= "musb-tusb",
	.id		= -1,
	.dev = {
		.dma_mask		= &tusb_dmamask,
		.coherent_dma_mask	= 0xffffffff,
	},
	.num_resources	= ARRAY_SIZE(tusb_resources),
	.resource	= tusb_resources,
};

/* this may be called only from board-*.c setup code */
int __init
tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
		unsigned ps_refclk, unsigned waitpin,
		unsigned async, unsigned sync,
		unsigned irq, unsigned dmachan)
{
	int		status;
	static char	error[] __initdata =
		KERN_ERR "tusb6010 init error %d, %d\n";

	/* ASYNC region, primarily for PIO */
	status = gpmc_cs_request(async, SZ_16M, (unsigned long *)
				&tusb_resources[0].start);
	if (status < 0) {
		printk(error, 1, status);
		return status;
	}
	tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
	tusb_async.wait_pin = waitpin;
	async_cs = async;

	status = gpmc_cs_program_settings(async_cs, &tusb_async);
	if (status < 0)
		return status;

	/* SYNC region, primarily for DMA */
	status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
				&tusb_resources[1].start);
	if (status < 0) {
		printk(error, 2, status);
		return status;
	}
	tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
	tusb_sync.wait_pin = waitpin;
	sync_cs = sync;

	status = gpmc_cs_program_settings(sync_cs, &tusb_sync);
	if (status < 0)
		return status;

	/* IRQ */
	status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq");
	if (status < 0) {
		printk(error, 3, status);
		return status;
	}
	tusb_resources[2].start = gpio_to_irq(irq);

	/* set up memory timings ... can speed them up later */
	if (!ps_refclk) {
		printk(error, 4, status);
		return -ENODEV;
	}
	refclk_psec = ps_refclk;
	status = tusb6010_platform_retime(1);
	if (status < 0) {
		printk(error, 5, status);
		return status;
	}

	/* finish device setup ... */
	if (!data) {
		printk(error, 6, status);
		return -ENODEV;
	}
	tusb_device.dev.platform_data = data;

	/* so far so good ... register the device */
	status = platform_device_register(&tusb_device);
	if (status < 0) {
		printk(error, 7, status);
		return status;
	}
	return 0;
}


code:
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/platform_data/usb-omap.h>

/* AM35x */
/* USB 2.0 PHY Control */
#define CONF2_PHY_GPIOMODE	(1 << 23)
#define CONF2_OTGMODE		(3 << 14)
#define CONF2_NO_OVERRIDE	(0 << 14)
#define CONF2_FORCE_HOST	(1 << 14)
#define CONF2_FORCE_DEVICE	(2 << 14)
#define CONF2_FORCE_HOST_VBUS_LOW (3 << 14)
#define CONF2_SESENDEN		(1 << 13)
#define CONF2_VBDTCTEN		(1 << 12)
#define CONF2_REFFREQ_24MHZ	(2 << 8)
#define CONF2_REFFREQ_26MHZ	(7 << 8)
#define CONF2_REFFREQ_13MHZ	(6 << 8)
#define CONF2_REFFREQ		(0xf << 8)
#define CONF2_PHYCLKGD		(1 << 7)
#define CONF2_VBUSSENSE		(1 << 6)
#define CONF2_PHY_PLLON		(1 << 5)
#define CONF2_RESET		(1 << 4)
#define CONF2_PHYPWRDN		(1 << 3)
#define CONF2_OTGPWRDN		(1 << 2)
#define CONF2_DATPOL		(1 << 1)

/* TI81XX specific definitions */
#define USBCTRL0	0x620
#define USBSTAT0	0x624

/* TI816X PHY controls bits */
#define TI816X_USBPHY0_NORMAL_MODE	(1 << 0)
#define TI816X_USBPHY_REFCLK_OSC	(1 << 8)

/* TI814X PHY controls bits */
#define USBPHY_CM_PWRDN		(1 << 0)
#define USBPHY_OTG_PWRDN	(1 << 1)
#define USBPHY_CHGDET_DIS	(1 << 2)
#define USBPHY_CHGDET_RSTRT	(1 << 3)
#define USBPHY_SRCONDM		(1 << 4)
#define USBPHY_SINKONDP		(1 << 5)
#define USBPHY_CHGISINK_EN	(1 << 6)
#define USBPHY_CHGVSRC_EN	(1 << 7)
#define USBPHY_DMPULLUP		(1 << 8)
#define USBPHY_DPPULLUP		(1 << 9)
#define USBPHY_CDET_EXTCTL	(1 << 10)
#define USBPHY_GPIO_MODE	(1 << 12)
#define USBPHY_DPOPBUFCTL	(1 << 13)
#define USBPHY_DMOPBUFCTL	(1 << 14)
#define USBPHY_DPINPUT		(1 << 15)
#define USBPHY_DMINPUT		(1 << 16)
#define USBPHY_DPGPIO_PD	(1 << 17)
#define USBPHY_DMGPIO_PD	(1 << 18)
#define USBPHY_OTGVDET_EN	(1 << 19)
#define USBPHY_OTGSESSEND_EN	(1 << 20)
#define USBPHY_DATA_POLARITY	(1 << 23)

struct usbhs_phy_data {
	int port;		/* 1 indexed port number */
	int reset_gpio;
	int vcc_gpio;
	bool vcc_polarity;	/* 1 active high, 0 active low */
};

extern void usb_musb_init(struct omap_musb_board_data *board_data);
extern void usbhs_init(struct usbhs_omap_platform_data *pdata);
extern int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys);

extern void am35x_musb_reset(void);
extern void am35x_musb_phy_power(u8 on);
extern void am35x_musb_clear_irq(void);
extern void am35x_set_mode(u8 musb_mode);